Merge "Make _parse_block_device_mapping to return only passed attributes"
This commit is contained in:
commit
476e899552
|
@ -189,12 +189,12 @@ def register_image(context, name=None, image_location=None,
|
|||
if block_device_mapping:
|
||||
mappings = instance_api._parse_block_device_mapping(
|
||||
context, block_device_mapping)
|
||||
# NOTE(andrey-mp): image BDM requires resource_id instead of 'uuid'
|
||||
# TODO(ft): merge with image manifets's virtual device mappings
|
||||
short_root_device_name = (
|
||||
ec2utils.block_device_strip_dev(root_device_name))
|
||||
for bdm in mappings:
|
||||
uuid = bdm.pop('uuid', None)
|
||||
if uuid:
|
||||
resource = bdm['source_type'] + '_id'
|
||||
bdm[resource] = uuid
|
||||
instance_api._populate_parsed_bdm_parameter(bdm,
|
||||
short_root_device_name)
|
||||
properties['bdm_v2'] = True
|
||||
properties['block_device_mapping'] = json.dumps(mappings)
|
||||
if architecture is not None:
|
||||
|
|
|
@ -110,7 +110,7 @@ def run_instances(context, image_id, min_count, max_count,
|
|||
nova = clients.nova(context)
|
||||
os_flavor = _get_os_flavor(instance_type, nova)
|
||||
|
||||
bdm = _parse_block_device_mapping(context, block_device_mapping)
|
||||
bdm = _build_block_device_mapping(context, block_device_mapping, os_image)
|
||||
availability_zone = (placement or {}).get('availability_zone')
|
||||
if user_data:
|
||||
user_data = base64.b64decode(user_data)
|
||||
|
@ -887,30 +887,28 @@ def _parse_image_parameters(context, image_id, kernel_id, ramdisk_id):
|
|||
|
||||
def _parse_block_device_mapping(context, block_device_mapping):
|
||||
# TODO(ft): check block_device_mapping structure
|
||||
# TODO(ft): support virtual devices
|
||||
# TODO(ft): support no_device
|
||||
bdms = []
|
||||
for args_bd in (block_device_mapping or []):
|
||||
bdm = {
|
||||
'device_name': args_bd['device_name'],
|
||||
'destination_type': 'volume',
|
||||
'boot_index': -1,
|
||||
'source_type': 'blank',
|
||||
'delete_on_termination': True
|
||||
}
|
||||
|
||||
ebs = args_bd.get('ebs')
|
||||
if ebs:
|
||||
bdm['delete_on_termination'] = ebs.get('delete_on_termination',
|
||||
True)
|
||||
ec2_id = ebs.get('snapshot_id')
|
||||
if ec2_id:
|
||||
if ec2_id.startswith('snap-'):
|
||||
bdm['source_type'] = 'snapshot'
|
||||
snapshot = ec2utils.get_db_item(context, ec2_id)
|
||||
bdm['uuid'] = snapshot['os_id']
|
||||
bdm['snapshot_id'] = snapshot['os_id']
|
||||
# NOTE(ft): OpenStack extension, AWS incompatibility
|
||||
elif ec2_id.startswith('vol-'):
|
||||
bdm['source_type'] = 'volume'
|
||||
volume = ec2utils.get_db_item(context, ec2_id)
|
||||
bdm['uuid'] = volume['os_id']
|
||||
bdm['volume_id'] = volume['os_id']
|
||||
else:
|
||||
# NOTE(ft): AWS returns undocumented
|
||||
# InvalidSnapshotID.NotFound
|
||||
|
@ -918,12 +916,42 @@ def _parse_block_device_mapping(context, block_device_mapping):
|
|||
snapshot_id=ec2_id)
|
||||
if 'volume_size' in ebs:
|
||||
bdm['volume_size'] = ebs['volume_size']
|
||||
if 'delete_on_termination' in ebs:
|
||||
bdm['delete_on_termination'] = ebs['delete_on_termination']
|
||||
|
||||
bdms.append(bdm)
|
||||
|
||||
return bdms
|
||||
|
||||
|
||||
def _build_block_device_mapping(context, block_device_mapping, os_image):
|
||||
mappings = _parse_block_device_mapping(context, block_device_mapping)
|
||||
properties = ec2utils.deserialize_os_image_properties(os_image)
|
||||
root_device_name = (
|
||||
ec2utils.block_device_properties_root_device_name(properties))
|
||||
short_root_device_name = ec2utils.block_device_strip_dev(root_device_name)
|
||||
result = []
|
||||
for bdm in mappings:
|
||||
_populate_parsed_bdm_parameter(bdm, short_root_device_name)
|
||||
source_type = bdm.get('source_type')
|
||||
if source_type:
|
||||
uuid = bdm.pop('_'.join([source_type, 'id']), None)
|
||||
if uuid:
|
||||
bdm['uuid'] = uuid
|
||||
result.append(bdm)
|
||||
return result
|
||||
|
||||
|
||||
def _populate_parsed_bdm_parameter(bdm, short_root_device_name):
|
||||
bdm.setdefault('delete_on_termination', True)
|
||||
bdm.setdefault('source_type', 'blank')
|
||||
if (short_root_device_name ==
|
||||
ec2utils.block_device_strip_dev(bdm['device_name'])):
|
||||
bdm['boot_index'] = 0
|
||||
else:
|
||||
bdm['boot_index'] = -1
|
||||
|
||||
|
||||
def _format_group_set(context, os_security_groups, groups):
|
||||
if not os_security_groups:
|
||||
return None
|
||||
|
|
|
@ -196,7 +196,10 @@ class ImageTestCase(base.ApiTestCase):
|
|||
'KernelId': fakes.ID_EC2_IMAGE_AKI_1,
|
||||
'RamdiskId': fakes.ID_EC2_IMAGE_ARI_1,
|
||||
'BlockDeviceMapping.1.DeviceName': fakes.ROOT_DEVICE_NAME_IMAGE_2,
|
||||
'BlockDeviceMapping.1.Ebs.SnapshotId': fakes.ID_EC2_SNAPSHOT_1})
|
||||
'BlockDeviceMapping.1.Ebs.SnapshotId': fakes.ID_EC2_SNAPSHOT_1,
|
||||
'BlockDeviceMapping.2.DeviceName': '/dev/vdf',
|
||||
'BlockDeviceMapping.2.Ebs.VolumeSize': '100',
|
||||
'BlockDeviceMapping.2.Ebs.DeleteOnTermination': 'False'})
|
||||
self.assertThat(resp, matchers.DictMatches(
|
||||
{'imageId': fakes.ID_EC2_IMAGE_2}))
|
||||
self.db_api.add_item.assert_called_once_with(
|
||||
|
@ -211,7 +214,7 @@ class ImageTestCase(base.ApiTestCase):
|
|||
self.glance.images.create.call_args[1]['properties'],
|
||||
dict)
|
||||
bdm = self.glance.images.create.call_args[1]['properties'].pop(
|
||||
'block_device_mapping', None)
|
||||
'block_device_mapping', 'null')
|
||||
self.assertEqual(
|
||||
{'is_public': False,
|
||||
'size': 0,
|
||||
|
@ -222,12 +225,18 @@ class ImageTestCase(base.ApiTestCase):
|
|||
'ramdisk_id': fakes.ID_OS_IMAGE_ARI_1,
|
||||
'bdm_v2': True}},
|
||||
self.glance.images.create.call_args[1])
|
||||
self.assertEqual([{'boot_index': -1,
|
||||
self.assertEqual([{'boot_index': 0,
|
||||
'delete_on_termination': True,
|
||||
'destination_type': 'volume',
|
||||
'device_name': fakes.ROOT_DEVICE_NAME_IMAGE_2,
|
||||
'source_type': 'snapshot',
|
||||
'snapshot_id': fakes.ID_OS_SNAPSHOT_1}],
|
||||
'snapshot_id': fakes.ID_OS_SNAPSHOT_1},
|
||||
{'boot_index': -1,
|
||||
'delete_on_termination': False,
|
||||
'destination_type': 'volume',
|
||||
'device_name': '/dev/vdf',
|
||||
'source_type': 'blank',
|
||||
'volume_size': 100}],
|
||||
json.loads(bdm))
|
||||
get_os_image.assert_has_calls(
|
||||
[mock.call(mock.ANY, fakes.ID_EC2_IMAGE_AKI_1),
|
||||
|
|
|
@ -318,7 +318,7 @@ class InstanceTestCase(base.ApiTestCase):
|
|||
fakes.ID_OS_IMAGE_ARI_1: fakes.OSImage(fakes.OS_IMAGE_ARI_1)}))
|
||||
get_ec2_classic_os_network.return_value = {'id': fakes.random_os_id()}
|
||||
user_data = base64.b64decode(fakes.USER_DATA_INSTANCE_2)
|
||||
parse_block_device_mapping.return_value = 'fake_bdm'
|
||||
parse_block_device_mapping.return_value = []
|
||||
|
||||
def do_check(engine, extra_kwargs={}, extra_db_instance={}):
|
||||
instance_api.instance_engine = engine
|
||||
|
@ -347,7 +347,7 @@ class InstanceTestCase(base.ApiTestCase):
|
|||
mock.ANY, mock.ANY, mock.ANY, min_count=1, max_count=1,
|
||||
userdata=user_data, kernel_id=fakes.ID_OS_IMAGE_AKI_1,
|
||||
ramdisk_id=fakes.ID_OS_IMAGE_ARI_1, key_name=None,
|
||||
block_device_mapping_v2='fake_bdm',
|
||||
block_device_mapping_v2=[],
|
||||
availability_zone='fake_zone', security_groups=['default'],
|
||||
**extra_kwargs)
|
||||
self.nova.servers.reset_mock()
|
||||
|
@ -1434,40 +1434,72 @@ class InstancePrivateTestCase(test_base.BaseTestCase):
|
|||
{'device_name': '/dev/sdb1',
|
||||
'ebs': {'volume_size': 55}}])
|
||||
|
||||
expected = [{'boot_index': -1,
|
||||
'uuid': fakes.ID_OS_SNAPSHOT_1,
|
||||
expected = [{'snapshot_id': fakes.ID_OS_SNAPSHOT_1,
|
||||
'device_name': '/dev/vdf',
|
||||
'source_type': 'snapshot',
|
||||
'destination_type': 'volume',
|
||||
'delete_on_termination': True},
|
||||
{'boot_index': -1,
|
||||
'uuid': fakes.ID_OS_SNAPSHOT_2,
|
||||
'destination_type': 'volume'},
|
||||
{'snapshot_id': fakes.ID_OS_SNAPSHOT_2,
|
||||
'volume_size': 111,
|
||||
'device_name': '/dev/vdg',
|
||||
'source_type': 'snapshot',
|
||||
'destination_type': 'volume',
|
||||
'delete_on_termination': False},
|
||||
{'boot_index': -1,
|
||||
'uuid': fakes.ID_OS_VOLUME_1,
|
||||
{'volume_id': fakes.ID_OS_VOLUME_1,
|
||||
'device_name': '/dev/vdh',
|
||||
'source_type': 'volume',
|
||||
'destination_type': 'volume',
|
||||
'delete_on_termination': True},
|
||||
{'boot_index': -1,
|
||||
'uuid': fakes.ID_OS_VOLUME_2,
|
||||
'destination_type': 'volume'},
|
||||
{'volume_id': fakes.ID_OS_VOLUME_2,
|
||||
'device_name': '/dev/vdi',
|
||||
'source_type': 'volume',
|
||||
'destination_type': 'volume',
|
||||
'delete_on_termination': True},
|
||||
{'boot_index': -1,
|
||||
'volume_size': 55,
|
||||
{'volume_size': 55,
|
||||
'device_name': '/dev/sdb1',
|
||||
'source_type': 'blank',
|
||||
'destination_type': 'volume',
|
||||
'delete_on_termination': True}]
|
||||
'destination_type': 'volume'}]
|
||||
|
||||
self.assertThat(expected, matchers.ListMatches(res,
|
||||
orderless_lists=True))
|
||||
self.assertThat(expected,
|
||||
matchers.ListMatches(res, orderless_lists=True),
|
||||
verbose=True)
|
||||
|
||||
@mock.patch('ec2api.db.api.IMPL')
|
||||
def test_build_block_device_mapping(self, db_api):
|
||||
fake_context = mock.Mock(service_catalog=[{'type': 'fake'}])
|
||||
db_api.get_item_by_id.side_effect = tools.get_db_api_get_item_by_id(
|
||||
fakes.DB_SNAPSHOT_1, fakes.DB_VOLUME_1)
|
||||
|
||||
bdms = [
|
||||
{'device_name': '/dev/sda1',
|
||||
'ebs': {'snapshot_id': fakes.ID_EC2_SNAPSHOT_1}},
|
||||
{'device_name': '/dev/vdb',
|
||||
'ebs': {'snapshot_id': fakes.ID_EC2_VOLUME_1,
|
||||
'delete_on_termination': False}},
|
||||
{'device_name': 'vdc',
|
||||
'ebs': {'volume_size': 100}},
|
||||
]
|
||||
expected = [
|
||||
{'device_name': '/dev/sda1',
|
||||
'source_type': 'snapshot',
|
||||
'destination_type': 'volume',
|
||||
'uuid': fakes.ID_OS_SNAPSHOT_1,
|
||||
'delete_on_termination': True,
|
||||
'boot_index': 0},
|
||||
{'device_name': '/dev/vdb',
|
||||
'source_type': 'volume',
|
||||
'destination_type': 'volume',
|
||||
'uuid': fakes.ID_OS_VOLUME_1,
|
||||
'delete_on_termination': False,
|
||||
'boot_index': -1},
|
||||
{'device_name': 'vdc',
|
||||
'source_type': 'blank',
|
||||
'destination_type': 'volume',
|
||||
'volume_size': 100,
|
||||
'delete_on_termination': True,
|
||||
'boot_index': -1},
|
||||
]
|
||||
|
||||
result = instance_api._build_block_device_mapping(
|
||||
fake_context, bdms, fakes.OSImage(fakes.OS_IMAGE_1))
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
@mock.patch('cinderclient.client.Client')
|
||||
@mock.patch('novaclient.client.Client')
|
||||
|
|
Loading…
Reference in New Issue