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:
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user