Merge "Create the image mappings BDMs earlier in the boot"

This commit is contained in:
Jenkins
2014-04-29 23:40:33 +00:00
committed by Gerrit Code Review
2 changed files with 57 additions and 66 deletions

View File

@@ -616,50 +616,58 @@ class API(base.Base):
if int(image.get('min_disk') or 0) > root_gb:
raise exception.FlavorDiskTooSmall()
def _check_and_transform_bdm(self, base_options, image_meta, min_count,
max_count, block_device_mapping, legacy_bdm):
def _get_image_defined_bdms(self, base_options, instance_type, image_meta,
root_device_name):
image_properties = image_meta.get('properties', {})
# Get the block device mappings defined by the image.
image_defined_bdms = image_properties.get('block_device_mapping', [])
legacy_image_defined = not image_properties.get('bdm_v2', False)
image_mapping = image_properties.get('mappings', [])
if legacy_image_defined:
image_defined_bdms = block_device.from_legacy_mapping(
image_defined_bdms, None, root_device_name)
else:
image_defined_bdms = map(block_device.BlockDeviceDict,
image_defined_bdms)
if image_mapping:
image_defined_bdms += self._prepare_image_mapping(
instance_type, image_mapping)
return image_defined_bdms
def _check_and_transform_bdm(self, base_options, instance_type, image_meta,
min_count, max_count, block_device_mapping,
legacy_bdm):
# NOTE (ndipanov): Assume root dev name is 'vda' if not supplied.
# It's needed for legacy conversion to work.
root_device_name = (base_options.get('root_device_name') or 'vda')
image_ref = base_options.get('image_ref', '')
# Get the block device mappings defined by the image.
image_defined_bdms = \
image_meta.get('properties', {}).get('block_device_mapping', [])
legacy_image_defined = not image_meta.get(
'properties', {}).get('bdm_v2', False)
if not legacy_image_defined:
image_defined_bdms = map(block_device.BlockDeviceDict,
image_defined_bdms)
image_defined_bdms = self._get_image_defined_bdms(
base_options, instance_type, image_meta, root_device_name)
root_in_image_bdms = (
block_device.get_root_bdm(image_defined_bdms) is not None)
if legacy_bdm:
if legacy_image_defined:
block_device_mapping += image_defined_bdms
block_device_mapping = block_device.from_legacy_mapping(
block_device_mapping, image_ref, root_device_name)
else:
root_in_image_bdms = block_device.get_root_bdm(
image_defined_bdms) is not None
block_device_mapping = block_device.from_legacy_mapping(
block_device_mapping, image_ref, root_device_name,
no_root=root_in_image_bdms) + image_defined_bdms
else:
block_device_mapping = block_device.from_legacy_mapping(
block_device_mapping, image_ref, root_device_name,
no_root=root_in_image_bdms)
elif image_ref and root_in_image_bdms:
# NOTE (ndipanov): client will insert an image mapping into the v2
# block_device_mapping, but if there is a bootable device in image
# mappings - we need to get rid of the inserted image.
if legacy_image_defined:
image_defined_bdms = block_device.from_legacy_mapping(
image_defined_bdms, None, root_device_name)
root_in_image_bdms = block_device.get_root_bdm(
image_defined_bdms) is not None
if image_ref and root_in_image_bdms:
block_device_mapping = [bdm for bdm in block_device_mapping
if not (
bdm.get('source_type') == 'image'
and bdm.get('boot_index') == 0)]
def not_image_and_root_bdm(bdm):
return not (bdm.get('boot_index') == 0 and
bdm.get('source_type') == 'image')
block_device_mapping += image_defined_bdms
block_device_mapping = (
filter(not_image_and_root_bdm, block_device_mapping))
block_device_mapping += image_defined_bdms
if min_count > 1 or max_count > 1:
if any(map(lambda bdm: bdm['source_type'] == 'volume',
@@ -980,7 +988,7 @@ class API(base.Base):
max_count = max_net_count
block_device_mapping = self._check_and_transform_bdm(
base_options, boot_meta, min_count, max_count,
base_options, instance_type, boot_meta, min_count, max_count,
block_device_mapping, legacy_bdm)
instances = self._provision_instances(context, instance_type,
@@ -1018,13 +1026,13 @@ class API(base.Base):
size = instance_type.get('ephemeral_gb', 0)
return size
def _prepare_image_mapping(self, instance_type, instance_uuid, mappings):
def _prepare_image_mapping(self, instance_type, mappings):
"""Extract and format blank devices from image mappings."""
prepared_mappings = []
for bdm in block_device.mappings_prepend_dev(mappings):
LOG.debug(_("Image bdm %s"), bdm, instance_uuid=instance_uuid)
LOG.debug(_("Image bdm %s"), bdm)
virtual_name = bdm['virtual']
if virtual_name == 'ami' or virtual_name == 'root':
@@ -1147,25 +1155,6 @@ class API(base.Base):
if num_local > max_local:
raise exception.InvalidBDMLocalsLimit()
def _populate_instance_for_bdm(self, context, instance, instance_type,
image, block_device_mapping):
"""Populate instance block device mapping information."""
instance_uuid = instance['uuid']
image_properties = image.get('properties', {})
image_mapping = image_properties.get('mappings', [])
if image_mapping:
image_mapping = self._prepare_image_mapping(instance_type,
instance_uuid, image_mapping)
self._validate_bdm(context, instance, instance_type,
block_device_mapping + image_mapping)
for mapping in (image_mapping, block_device_mapping):
if not mapping:
continue
self._update_block_device_mapping(context,
instance_type, instance_uuid, mapping)
def _populate_instance_shutdown_terminate(self, instance, image,
block_device_mapping):
"""Populate instance shutdown_terminate information."""
@@ -1271,12 +1260,15 @@ class API(base.Base):
# has been created, so delete it and re-raise so
# that other cleanup can happen.
try:
self._populate_instance_for_bdm(context, instance,
instance_type, image, block_device_mapping)
self._validate_bdm(
context, instance, instance_type, block_device_mapping)
except exception.InvalidBDM:
with excutils.save_and_reraise_exception():
instance.destroy(context)
self._update_block_device_mapping(
context, instance_type, instance['uuid'], block_device_mapping)
return instance
def _check_create_policies(self, context, availability_zone,

View File

@@ -765,7 +765,6 @@ class ComputeVolumeTestCase(BaseTestCase):
ephemeral_size = 1
instance_type = {'swap': swap_size,
'ephemeral_gb': ephemeral_size}
instance = self._create_fake_instance()
mappings = [
{'virtual': 'ami', 'device': 'sda1'},
{'virtual': 'root', 'device': '/dev/sda1'},
@@ -777,7 +776,7 @@ class ComputeVolumeTestCase(BaseTestCase):
]
preped_bdm = self.compute_api._prepare_image_mapping(
instance_type, instance['uuid'], mappings)
instance_type, mappings)
expected_result = [
{
@@ -7953,7 +7952,7 @@ class ComputeAPITestCase(BaseTestCase):
'no_device': True}]
image_mapping = self.compute_api._prepare_image_mapping(
instance_type, instance['uuid'], mappings)
instance_type, mappings)
self.compute_api._update_block_device_mapping(
self.context, instance_type, instance['uuid'], image_mapping)
@@ -8052,7 +8051,7 @@ class ComputeAPITestCase(BaseTestCase):
base_options = base_options or {'root_device_name': 'vda',
'image_ref': FAKE_IMAGE_REF}
transformed_bdm = self.compute_api._check_and_transform_bdm(
base_options, image_meta, 1, 1, bdms, legacy_bdms)
base_options, {}, image_meta, 1, 1, bdms, legacy_bdms)
self.assertThat(expected_bdms,
matchers.DictListMatches(transformed_bdm))
@@ -8152,27 +8151,27 @@ class ComputeAPITestCase(BaseTestCase):
# We get an image BDM
transformed_bdm = self.compute_api._check_and_transform_bdm(
base_options, {}, 1, 1, fake_legacy_bdms, True)
base_options, {}, {}, 1, 1, fake_legacy_bdms, True)
self.assertEqual(len(transformed_bdm), 2)
# No image BDM created if image already defines a root BDM
base_options['root_device_name'] = 'vda'
transformed_bdm = self.compute_api._check_and_transform_bdm(
base_options, image_meta, 1, 1, [], True)
base_options, {}, image_meta, 1, 1, [], True)
self.assertEqual(len(transformed_bdm), 1)
# No image BDM created
transformed_bdm = self.compute_api._check_and_transform_bdm(
base_options, {}, 1, 1, fake_legacy_bdms, True)
base_options, {}, {}, 1, 1, fake_legacy_bdms, True)
self.assertEqual(len(transformed_bdm), 1)
# Volumes with multiple instances fails
self.assertRaises(exception.InvalidRequest,
self.compute_api._check_and_transform_bdm,
base_options, {}, 1, 2, fake_legacy_bdms, True)
base_options, {}, {}, 1, 2, fake_legacy_bdms, True)
checked_bdm = self.compute_api._check_and_transform_bdm(
base_options, {}, 1, 1, transformed_bdm, True)
base_options, {}, {}, 1, 1, transformed_bdm, True)
self.assertEqual(checked_bdm, transformed_bdm)
def test_volume_size(self):