Add the swap and ephemeral BDMs if needed

After preparing the block device mapping for creating new instance(s),
check if any ephemeral and/or a swap disks have been already defined. If
that is not the case and the instance type requires them, create the
needed ephemeral and/or swap BDMs.

Closes-Bug: #1297325
Related-Bug: #1457527
Change-Id: I44b30625cf1023d20ebec5e38f46b7b8dab325f6
This commit is contained in:
Xavier Queralt 2014-04-10 13:59:47 +02:00 committed by Nikola Dipanov
parent b6e5d68c66
commit 7f8128f87f
4 changed files with 57 additions and 0 deletions

View File

@ -272,6 +272,17 @@ def create_image_bdm(image_ref, boot_index=0):
'destination_type': 'local'})
def create_blank_bdm(size, guest_format=None):
return BlockDeviceDict(
{'source_type': 'blank',
'delete_on_termination': True,
'device_type': 'disk',
'boot_index': -1,
'destination_type': 'local',
'guest_format': guest_format,
'volume_size': size})
def snapshot_from_bdm(snapshot_id, template):
"""Create a basic volume snapshot BDM from a given template bdm."""

View File

@ -699,6 +699,23 @@ class API(base.Base):
return image_defined_bdms
def _get_flavor_defined_bdms(self, instance_type, block_device_mapping):
flavor_defined_bdms = []
have_ephemeral_bdms = any(filter(
block_device.new_format_is_ephemeral, block_device_mapping))
have_swap_bdms = any(filter(
block_device.new_format_is_swap, block_device_mapping))
if instance_type.get('ephemeral_gb') and not have_ephemeral_bdms:
flavor_defined_bdms.append(
block_device.create_blank_bdm(instance_type['ephemeral_gb']))
if instance_type.get('swap') and not have_swap_bdms:
flavor_defined_bdms.append(
block_device.create_blank_bdm(instance_type['swap'], 'swap'))
return flavor_defined_bdms
def _check_and_transform_bdm(self, context, base_options, instance_type,
image_meta, min_count, max_count,
block_device_mapping, legacy_bdm):
@ -752,6 +769,9 @@ class API(base.Base):
' instances')
raise exception.InvalidRequest(msg)
block_device_mapping += self._get_flavor_defined_bdms(
instance_type, block_device_mapping)
return block_device_obj.block_device_make_list_from_dicts(
context, block_device_mapping)

View File

@ -7329,6 +7329,29 @@ class ComputeAPITestCase(BaseTestCase):
(refs, resv_id) = self.compute_api.create(self.context,
inst_type, self.fake_image['id'])
def test_create_bdm_from_flavor(self):
instance_type_params = {
'flavorid': 'test', 'name': 'test',
'swap': 1024, 'ephemeral_gb': 1, 'root_gb': 1,
}
self._create_instance_type(params=instance_type_params)
inst_type = flavors.get_flavor_by_name('test')
self.stubs.Set(fake_image._FakeImageService, 'show', self.fake_show)
(refs, resv_id) = self.compute_api.create(self.context, inst_type,
self.fake_image['id'])
instance_uuid = refs[0]['uuid']
bdms = block_device_obj.BlockDeviceMappingList.get_by_instance_uuid(
self.context, instance_uuid)
ephemeral = filter(block_device.new_format_is_ephemeral, bdms)
self.assertEqual(1, len(ephemeral))
swap = filter(block_device.new_format_is_swap, bdms)
self.assertEqual(1, len(swap))
self.assertEqual(1024, swap[0].volume_size)
self.assertEqual(1, ephemeral[0].volume_size)
def test_create_with_deleted_image(self):
# If we're given a deleted image by glance, we should not be able to
# build from it

View File

@ -227,6 +227,9 @@ class CellsComputeAPITestCase(test_compute.ComputeAPITestCase):
self.context, instance['uuid'])
self.assertEqual(0, len(bdms))
def test_create_bdm_from_flavor(self):
self.skipTest("Test is incompatible with cells.")
@mock.patch('nova.cells.messaging._TargetedMessage')
def test_rebuild_sig(self, mock_msg):
# TODO(belliott) Cells could benefit from better testing to ensure API