Check ephemeral and swap size in the API

Validate that ephemeral and swap disks passed in trough the API are
within size limits for the given instance type. The validation is done
in the API layer.

Closes-bug #1218977

Change-Id: I96c6e651e4b221313c39dfc41e79d536585fb955
This commit is contained in:
Nikola Dipanov
2013-08-30 16:40:43 +02:00
parent 8b5f0c9bee
commit fcf712ec35
3 changed files with 100 additions and 11 deletions

View File

@@ -879,15 +879,13 @@ class API(base.Base):
@staticmethod
def _volume_size(instance_type, bdm):
size = 0
if bdm.get('source_type') == 'blank':
size = bdm.get('volume_size')
if size is None and bdm.get('source_type') == 'blank':
if bdm.get('guest_format') == 'swap':
size = instance_type.get('swap', 0)
else:
size = instance_type.get('ephemeral_gb', 0)
return size
else:
return bdm.get('volume_size')
return size
def _prepare_image_mapping(self, instance_type, instance_uuid, mappings):
"""Extract and format blank devices from image mappings."""
@@ -937,11 +935,7 @@ class API(base.Base):
LOG.debug(_("block_device_mapping %s"), block_device_mapping,
instance_uuid=instance_uuid)
for bdm in block_device_mapping:
# Default the size of blank devices per instance type
dest_type = bdm.get('destination_type')
if dest_type == 'blank':
bdm['volume_size'] = self._volume_size(
instance_type, bdm)
bdm['volume_size'] = self._volume_size(instance_type, bdm)
if bdm.get('volume_size') == 0:
continue
@@ -991,6 +985,24 @@ class API(base.Base):
except Exception:
raise exception.InvalidBDMSnapshot(id=snapshot_id)
ephemeral_size = sum(bdm.get('volume_size') or 0
for bdm in all_mappings
if block_device.new_format_is_ephemeral(bdm))
if ephemeral_size > instance_type['ephemeral_gb']:
raise exception.InvalidBDMEphemeralSize()
# There should be only one swap
swap_list = [bdm for bdm in all_mappings
if block_device.new_format_is_swap(bdm)]
if len(swap_list) > 1:
msg = _("More than one swap drive requested.")
raise exception.InvalidBDMFormat(details=msg)
if swap_list:
swap_size = swap_list[0].get('volume_size') or 0
if swap_size > instance_type['swap']:
raise exception.InvalidBDMSwapSize()
max_local = CONF.max_local_block_devices
if max_local >= 0:
num_local = len([bdm for bdm in all_mappings

View File

@@ -235,6 +235,15 @@ class InvalidBDMLocalsLimit(InvalidBDM):
"limit allows")
class InvalidBDMEphemeralSize(InvalidBDM):
msg_fmt = _("Ephemeral disks requested are larger than "
"the instance type allows.")
class InvalidBDMSwapSize(InvalidBDM):
msg_fmt = _("Swap drive requested is larger than instance type allows.")
class InvalidBDMFormat(InvalidBDM):
msg_fmt = _("Block Device Mapping is Invalid: "
"%(details)s")

View File

@@ -686,7 +686,7 @@ class ComputeVolumeTestCase(BaseTestCase):
snapshot_id = '66666666-aaaa-bbbb-cccc-555555555555'
instance = self._create_fake_instance()
instance_type = {'swap': 1, 'ephemeral_gb': 1}
instance_type = {'swap': 1, 'ephemeral_gb': 2}
mappings = [
{
'device_name': '/dev/sdb4',
@@ -746,6 +746,68 @@ class ComputeVolumeTestCase(BaseTestCase):
self.compute_api._validate_bdm,
self.context, instance, instance_type,
mappings)
ephemerals = [
{
'device_name': '/dev/vdb',
'source_type': 'blank',
'destination_type': 'local',
'device_type': 'disk',
'volume_id': volume_id,
'guest_format': None,
'boot_index': -1,
'volume_size': 1
},
{
'device_name': '/dev/vdc',
'source_type': 'blank',
'destination_type': 'local',
'device_type': 'disk',
'volume_id': volume_id,
'guest_format': None,
'boot_index': -1,
'volume_size': 1
}]
self.flags(max_local_block_devices=4)
# More ephemerals are OK as long as they are not over the size limit
self.compute_api._validate_bdm(self.context, instance,
instance_type, mappings + ephemerals)
# Ephemerals over the size limit
ephemerals[0]['volume_size'] = 3
self.assertRaises(exception.InvalidBDMEphemeralSize,
self.compute_api._validate_bdm,
self.context, instance, instance_type,
mappings + ephemerals)
self.assertRaises(exception.InvalidBDMEphemeralSize,
self.compute_api._validate_bdm,
self.context, instance, instance_type,
mappings + [ephemerals[0]])
# Swap over the size limit
mappings[0]['volume_size'] = 3
self.assertRaises(exception.InvalidBDMSwapSize,
self.compute_api._validate_bdm,
self.context, instance, instance_type,
mappings)
mappings[0]['volume_size'] = 1
additional_swap = [
{
'device_name': '/dev/vdb',
'source_type': 'blank',
'destination_type': 'local',
'device_type': 'disk',
'guest_format': 'swap',
'boot_index': -1,
'volume_size': 1
}]
# More than one swap
self.assertRaises(exception.InvalidBDMFormat,
self.compute_api._validate_bdm,
self.context, instance, instance_type,
mappings + additional_swap)
def test_validate_bdm_media_service_exceptions(self):
instance_type = {'swap': 1, 'ephemeral_gb': 1}
@@ -6710,9 +6772,15 @@ class ComputeAPITestCase(BaseTestCase):
self.assertEqual(
self.compute_api._volume_size(inst_type, ephemeral_bdm),
ephemeral_size)
ephemeral_bdm['volume_size'] = 42
self.assertEqual(
self.compute_api._volume_size(inst_type, ephemeral_bdm), 42)
self.assertEqual(
self.compute_api._volume_size(inst_type, swap_bdm),
swap_size)
swap_bdm['volume_size'] = 42
self.assertEqual(
self.compute_api._volume_size(inst_type, swap_bdm), 42)
self.assertEqual(
self.compute_api._volume_size(inst_type, volume_bdm),
volume_size)