API: make sure a blank volume with no size is rejected

Currently - we would happily accept the request, but fail to create the
block device mapping record for such a volume. The result was that the
boot request for such an instance would be accepted, but would not
create a volume.

Also fix the _volume_size API method that was 0ing out blank volume's
size by mistake.

Change-Id: I1d243aed78da7c026e55ea145397b070d619a567
Closes-bug: #1461638
This commit is contained in:
Nikola Dipanov 2015-06-03 19:10:01 +01:00
parent 686621e2ad
commit 817946b90f
2 changed files with 37 additions and 4 deletions

View File

@ -1143,7 +1143,9 @@ class API(base.Base):
@staticmethod
def _volume_size(instance_type, bdm):
size = bdm.get('volume_size')
if size is None and bdm.get('source_type') == 'blank':
# NOTE (ndipanov): inherit flavour size only for swap and ephemeral
if (size is None and bdm.get('source_type') == 'blank' and
bdm.get('destination_type') == 'local'):
if bdm.get('guest_format') == 'swap':
size = instance_type.get('swap', 0)
else:
@ -1257,6 +1259,12 @@ class API(base.Base):
raise
except Exception:
raise exception.InvalidBDMSnapshot(id=snapshot_id)
elif (bdm.source_type == 'blank' and
bdm.destination_type == 'volume' and
not bdm.volume_size):
raise exception.InvalidBDM(message=_("Blank volumes "
"(source: 'blank', dest: 'volume') need to have non-zero "
"size"))
ephemeral_size = sum(bdm.volume_size or 0
for bdm in all_mappings

View File

@ -1034,6 +1034,25 @@ class ComputeVolumeTestCase(BaseTestCase):
self.context, instance, instance_type,
mappings_)
# blank device without a specified size fails
blank_no_size = [
fake_block_device.FakeDbBlockDeviceDict({
'device_name': '/dev/sda4',
'source_type': 'blank',
'destination_type': 'volume',
'boot_index': -1,
'volume_size': None,
}, anon=True)
]
blank_no_size = block_device_obj.block_device_make_list_from_dicts(
self.context, blank_no_size)
mappings_ = mappings[:]
mappings_.objects.extend(blank_no_size)
self.assertRaises(exception.InvalidBDM,
self.compute_api._validate_bdm,
self.context, instance, instance_type,
mappings_)
def test_validate_bdm_media_service_exceptions(self):
instance_type = {'swap': 1, 'ephemeral_gb': 1}
all_mappings = [fake_block_device.FakeDbBlockDeviceDict({
@ -8672,9 +8691,13 @@ class ComputeAPITestCase(BaseTestCase):
swap_size = 3
volume_size = 5
swap_bdm = {'source_type': 'blank', 'guest_format': 'swap'}
ephemeral_bdm = {'source_type': 'blank', 'guest_format': None}
volume_bdm = {'source_type': 'volume', 'volume_size': volume_size}
swap_bdm = {'source_type': 'blank', 'guest_format': 'swap',
'destination_type': 'local'}
ephemeral_bdm = {'source_type': 'blank', 'guest_format': None,
'destination_type': 'local'}
volume_bdm = {'source_type': 'volume', 'volume_size': volume_size,
'destination_type': 'volume'}
blank_bdm = {'source_type': 'blank', 'destination_type': 'volume'}
inst_type = {'ephemeral_gb': ephemeral_size, 'swap': swap_size}
self.assertEqual(
@ -8692,6 +8715,8 @@ class ComputeAPITestCase(BaseTestCase):
self.assertEqual(
self.compute_api._volume_size(inst_type, volume_bdm),
volume_size)
self.assertIsNone(
self.compute_api._volume_size(inst_type, blank_bdm))
def test_is_volume_backed_instance(self):
ctxt = self.context