summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2015-04-21 10:49:53 +0000
committerGerrit Code Review <review@openstack.org>2015-04-21 10:49:53 +0000
commit290839b853f58e515dc07c77f03b5ebd1502f57b (patch)
tree166edac046fa124e4f44e0d7fb2c3fa8662b6226
parent916ce6f6efe46964f4d9afafd8bedb0cc2779183 (diff)
parent3cff2c673c6cdf487c2a1eb2a5c6c89c6de80d11 (diff)
downloadnova-290839b853f58e515dc07c77f03b5ebd1502f57b.tar.gz
Merge "Release bdm constraint source and dest type" into stable/kilo
-rw-r--r--nova/api/openstack/compute/plugins/v3/block_device_mapping.py8
-rw-r--r--nova/api/openstack/compute/servers.py9
-rw-r--r--nova/block_device.py11
-rw-r--r--nova/tests/unit/test_block_device.py27
4 files changed, 45 insertions, 10 deletions
diff --git a/nova/api/openstack/compute/plugins/v3/block_device_mapping.py b/nova/api/openstack/compute/plugins/v3/block_device_mapping.py
index c28851e265..4a6f667688 100644
--- a/nova/api/openstack/compute/plugins/v3/block_device_mapping.py
+++ b/nova/api/openstack/compute/plugins/v3/block_device_mapping.py
@@ -47,6 +47,11 @@ class BlockDeviceMapping(extensions.V3APIExtensionBase):
# NOTE(gmann): This function is not supposed to use 'body_deprecated_param'
# parameter as this is placed to handle scheduler_hint extension for V2.1.
def server_create(self, server_dict, create_kwargs, body_deprecated_param):
+
+ # Have to check whether --image is given, see bug 1433609
+ image_href = server_dict.get('imageRef')
+ image_uuid_specified = image_href is not None
+
bdm = server_dict.get(ATTRIBUTE_NAME, [])
legacy_bdm = server_dict.get(LEGACY_ATTRIBUTE_NAME, [])
@@ -57,7 +62,8 @@ class BlockDeviceMapping(extensions.V3APIExtensionBase):
try:
block_device_mapping = [
- block_device.BlockDeviceDict.from_api(bdm_dict)
+ block_device.BlockDeviceDict.from_api(bdm_dict,
+ image_uuid_specified)
for bdm_dict in bdm]
except exception.InvalidBDMFormat as e:
raise exc.HTTPBadRequest(explanation=e.format_message())
diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py
index 999685ee46..d3d52aedd4 100644
--- a/nova/api/openstack/compute/servers.py
+++ b/nova/api/openstack/compute/servers.py
@@ -383,7 +383,7 @@ class Controller(wsgi.Controller):
raise exc.HTTPBadRequest(explanation=expl)
return user_data
- def _extract_bdm(self, server_dict):
+ def _extract_bdm(self, server_dict, image_uuid_specified):
legacy_bdm = True
block_device_mapping = None
block_device_mapping_v2 = None
@@ -424,7 +424,8 @@ class Controller(wsgi.Controller):
try:
block_device_mapping_v2 = [
- block_device.BlockDeviceDict.from_api(bdm_dict)
+ block_device.BlockDeviceDict.from_api(bdm_dict,
+ image_uuid_specified)
for bdm_dict in block_device_mapping_v2]
except exception.InvalidBDMFormat as e:
raise exc.HTTPBadRequest(explanation=e.format_message())
@@ -552,7 +553,9 @@ class Controller(wsgi.Controller):
user_data = self._extract(server_dict, 'os-user-data', 'user_data')
self._validate_user_data(user_data)
- legacy_bdm, block_device_mapping = self._extract_bdm(server_dict)
+ image_uuid_specified = bool(image_uuid)
+ legacy_bdm, block_device_mapping = self._extract_bdm(server_dict,
+ image_uuid_specified)
ret_resv_id = False
# min_count and max_count are optional. If they exist, they may come
diff --git a/nova/block_device.py b/nova/block_device.py
index 28b496c2c1..d8ae4a6b98 100644
--- a/nova/block_device.py
+++ b/nova/block_device.py
@@ -171,7 +171,7 @@ class BlockDeviceDict(dict):
return cls(new_bdm, non_computable_fields)
@classmethod
- def from_api(cls, api_dict):
+ def from_api(cls, api_dict, image_uuid_specified):
"""Transform the API format of data to the internally used one.
Only validate if the source_type field makes sense.
@@ -194,8 +194,13 @@ class BlockDeviceDict(dict):
details=_("Missing device UUID."))
api_dict[source_type + '_id'] = device_uuid
if source_type == 'image' and destination_type == 'local':
- raise exception.InvalidBDMFormat(
- details=_("Mapping image to local is not supported."))
+ boot_index = api_dict.get('boot_index', -1)
+
+ # if this bdm is generated from --image ,then
+ # source_type = image and destination_type = local is allowed
+ if not (image_uuid_specified and boot_index == 0):
+ raise exception.InvalidBDMFormat(
+ details=_("Mapping image to local is not supported."))
api_dict.pop('uuid', None)
return cls(api_dict)
diff --git a/nova/tests/unit/test_block_device.py b/nova/tests/unit/test_block_device.py
index 6abb58d6fd..7d1bee0bde 100644
--- a/nova/tests/unit/test_block_device.py
+++ b/nova/tests/unit/test_block_device.py
@@ -523,7 +523,7 @@ class TestBlockDeviceDict(test.NoDBTestCase):
if new['snapshot_id']:
new['volume_id'] = None
self.assertThat(
- block_device.BlockDeviceDict.from_api(api),
+ block_device.BlockDeviceDict.from_api(api, False),
matchers.IsSubDictOf(new))
def test_from_api_invalid_blank_id(self):
@@ -534,7 +534,8 @@ class TestBlockDeviceDict(test.NoDBTestCase):
'delete_on_termination': True,
'boot_index': -1}
self.assertRaises(exception.InvalidBDMFormat,
- block_device.BlockDeviceDict.from_api, api_dict)
+ block_device.BlockDeviceDict.from_api, api_dict,
+ False)
def test_from_api_invalid_source_to_local_mapping(self):
api_dict = {'id': 1,
@@ -542,7 +543,27 @@ class TestBlockDeviceDict(test.NoDBTestCase):
'destination_type': 'local',
'uuid': 'fake-volume-id-1'}
self.assertRaises(exception.InvalidBDMFormat,
- block_device.BlockDeviceDict.from_api, api_dict)
+ block_device.BlockDeviceDict.from_api, api_dict,
+ False)
+
+ def test_from_api_valid_source_to_local_mapping(self):
+ api_dict = {'id': 1,
+ 'source_type': 'image',
+ 'destination_type': 'local',
+ 'volume_id': 'fake-volume-id-1',
+ 'uuid': 1,
+ 'boot_index': 0}
+
+ retexp = block_device.BlockDeviceDict(
+ {'id': 1,
+ 'source_type': 'image',
+ 'image_id': 1,
+ 'destination_type': 'local',
+ 'volume_id': 'fake-volume-id-1',
+ 'boot_index': 0})
+ self.assertEqual(
+ block_device.BlockDeviceDict.from_api(api_dict, True),
+ retexp)
def test_legacy(self):
for legacy, new in zip(self.legacy_mapping, self.new_mapping):