diff --git a/nova/compute/api.py b/nova/compute/api.py index 22172f52b2eb..f90959f203bb 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -705,10 +705,8 @@ class API(base.Base): dest_size *= units.Gi if image_min_disk > dest_size: - # TODO(mdbooth) Raise a more descriptive exception here. - # This is the exception which calling code expects, but - # it's potentially misleading to the user. - raise exception.FlavorDiskTooSmall() + raise exception.VolumeSmallerThanMinDisk( + volume_size=dest_size, image_min_disk=image_min_disk) # Target disk is a local disk whose size is taken from the flavor else: @@ -719,10 +717,12 @@ class API(base.Base): # drivers. A value of 0 means don't check size. if dest_size != 0: if image_size > dest_size: - raise exception.FlavorDiskTooSmall() + raise exception.FlavorDiskSmallerThanImage( + flavor_size=dest_size, image_size=image_size) if image_min_disk > dest_size: - raise exception.FlavorDiskTooSmall() + raise exception.FlavorDiskSmallerThanMinDisk( + flavor_size=dest_size, image_min_disk=image_min_disk) def _get_image_defined_bdms(self, base_options, instance_type, image_meta, root_device_name): diff --git a/nova/exception.py b/nova/exception.py index 1e436ba9ee9f..ed567dbdc175 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -1255,7 +1255,24 @@ class FlavorMemoryTooSmall(NovaException): class FlavorDiskTooSmall(NovaException): - msg_fmt = _("Flavor's disk is too small for requested image.") + msg_fmt = _("The created instance's disk would be too small.") + + +class FlavorDiskSmallerThanImage(FlavorDiskTooSmall): + msg_fmt = _("Flavor's disk is too small for requested image. Flavor disk " + "is %(flavor_size)i bytes, image is %(image_size)i bytes.") + + +class FlavorDiskSmallerThanMinDisk(FlavorDiskTooSmall): + msg_fmt = _("Flavor's disk is smaller than the minimum size specified in " + "image metadata. Flavor disk is %(flavor_size)i bytes, " + "minimum size is %(image_min_disk)i bytes.") + + +class VolumeSmallerThanMinDisk(FlavorDiskTooSmall): + msg_fmt = _("Volume is smaller than the minimum size specified in image " + "metadata. Volume size is %(volume_size)i bytes, minimum " + "size is %(image_min_disk)i bytes.") class InsufficientFreeMemory(NovaException): diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py index 56f1afc193b4..bdb76fa7072e 100644 --- a/nova/tests/unit/compute/test_compute.py +++ b/nova/tests/unit/compute/test_compute.py @@ -7412,7 +7412,7 @@ class ComputeAPITestCase(BaseTestCase): self.fake_image['min_disk'] = 2 self.stubs.Set(fake_image._FakeImageService, 'show', self.fake_show) - self.assertRaises(exception.FlavorDiskTooSmall, + self.assertRaises(exception.FlavorDiskSmallerThanMinDisk, self.compute_api.create, self.context, inst_type, self.fake_image['id']) @@ -7431,7 +7431,7 @@ class ComputeAPITestCase(BaseTestCase): self.stubs.Set(fake_image._FakeImageService, 'show', self.fake_show) - self.assertRaises(exception.FlavorDiskTooSmall, + self.assertRaises(exception.FlavorDiskSmallerThanImage, self.compute_api.create, self.context, inst_type, self.fake_image['id']) @@ -7873,7 +7873,7 @@ class ComputeAPITestCase(BaseTestCase): self.fake_image['min_disk'] = 2 self.stubs.Set(fake_image._FakeImageService, 'show', self.fake_show) - self.assertRaises(exception.FlavorDiskTooSmall, + self.assertRaises(exception.FlavorDiskSmallerThanMinDisk, self.compute_api.rebuild, self.context, instance, self.fake_image['id'], 'new_password') @@ -7942,7 +7942,7 @@ class ComputeAPITestCase(BaseTestCase): self.fake_image['size'] = '1073741825' self.stubs.Set(fake_image._FakeImageService, 'show', self.fake_show) - self.assertRaises(exception.FlavorDiskTooSmall, + self.assertRaises(exception.FlavorDiskSmallerThanImage, self.compute_api.rebuild, self.context, instance, self.fake_image['id'], 'new_password') @@ -11580,7 +11580,7 @@ class CheckRequestedImageTestCase(test.TestCase): def test_image_min_disk_check(self): image = dict(id='123', status='active', min_disk='2') - self.assertRaises(exception.FlavorDiskTooSmall, + self.assertRaises(exception.FlavorDiskSmallerThanMinDisk, self.compute_api._check_requested_image, self.context, image['id'], image, self.instance_type, None) @@ -11591,7 +11591,7 @@ class CheckRequestedImageTestCase(test.TestCase): def test_image_too_large(self): image = dict(id='123', status='active', size='1073741825') - self.assertRaises(exception.FlavorDiskTooSmall, + self.assertRaises(exception.FlavorDiskSmallerThanImage, self.compute_api._check_requested_image, self.context, image['id'], image, self.instance_type, None) @@ -11659,7 +11659,7 @@ class CheckRequestedImageTestCase(test.TestCase): image_id=image_uuid, volume_id=volume_uuid, volume_size=self.instance_type.root_gb) - self.assertRaises(exception.FlavorDiskTooSmall, + self.assertRaises(exception.VolumeSmallerThanMinDisk, self.compute_api._check_requested_image, self.context, image_uuid, image, self.instance_type, root_bdm) @@ -11703,7 +11703,7 @@ class CheckRequestedImageTestCase(test.TestCase): root_bdm = block_device_obj.BlockDeviceMapping( source_type='image', destination_type='local', image_id=image_uuid) - self.assertRaises(exception.FlavorDiskTooSmall, + self.assertRaises(exception.FlavorDiskSmallerThanImage, self.compute_api._check_requested_image, self.context, image['id'], image, self.instance_type, root_bdm) @@ -11718,7 +11718,7 @@ class CheckRequestedImageTestCase(test.TestCase): root_bdm = block_device_obj.BlockDeviceMapping( source_type='image', destination_type='local', image_id=image_uuid) - self.assertRaises(exception.FlavorDiskTooSmall, + self.assertRaises(exception.FlavorDiskSmallerThanMinDisk, self.compute_api._check_requested_image, self.context, image['id'], image, self.instance_type, root_bdm) diff --git a/nova/tests/unit/compute/test_compute_mgr.py b/nova/tests/unit/compute/test_compute_mgr.py index e130e4620044..87f269c43931 100644 --- a/nova/tests/unit/compute/test_compute_mgr.py +++ b/nova/tests/unit/compute/test_compute_mgr.py @@ -3223,9 +3223,15 @@ class ComputeManagerBuildInstanceTestCase(test.NoDBTestCase): self._test_build_and_run_spawn_exceptions( exception.NoMoreFixedIps("error messge")) - def test_build_and_run_flavor_disk_too_small_exception(self): + def test_build_and_run_flavor_disk_smaller_image_exception(self): self._test_build_and_run_spawn_exceptions( - exception.FlavorDiskTooSmall()) + exception.FlavorDiskSmallerThanImage( + flavor_size=0, image_size=1)) + + def test_build_and_run_flavor_disk_smaller_min_disk(self): + self._test_build_and_run_spawn_exceptions( + exception.FlavorDiskSmallerThanMinDisk( + flavor_size=0, image_min_disk=1)) def test_build_and_run_flavor_memory_too_small_exception(self): self._test_build_and_run_spawn_exceptions( diff --git a/nova/tests/unit/virt/libvirt/test_imagebackend.py b/nova/tests/unit/virt/libvirt/test_imagebackend.py index ce70dd73937b..1ccb03724fa0 100644 --- a/nova/tests/unit/virt/libvirt/test_imagebackend.py +++ b/nova/tests/unit/virt/libvirt/test_imagebackend.py @@ -489,7 +489,7 @@ class Qcow2TestCase(_ImageTestCase, test.NoDBTestCase): self.mox.ReplayAll() image = self.image_class(self.INSTANCE, self.NAME) - self.assertRaises(exception.FlavorDiskTooSmall, + self.assertRaises(exception.FlavorDiskSmallerThanImage, image.create_image, fn, self.TEMPLATE_PATH, 1) self.mox.VerifyAll() @@ -1362,7 +1362,7 @@ class RbdTestCase(_ImageTestCase, test.NoDBTestCase): driver_mock.exists.return_value = True driver_mock.size.return_value = 2 - self.assertRaises(exception.FlavorDiskTooSmall, + self.assertRaises(exception.FlavorDiskSmallerThanImage, image.create_image, mock.MagicMock(), self.TEMPLATE_PATH, 1) driver_mock.size.assert_called_once_with(image.rbd_name) diff --git a/nova/tests/unit/virt/libvirt/test_utils.py b/nova/tests/unit/virt/libvirt/test_utils.py index 0ed7fb1077bf..964adce0c8d3 100644 --- a/nova/tests/unit/virt/libvirt/test_utils.py +++ b/nova/tests/unit/virt/libvirt/test_utils.py @@ -651,7 +651,7 @@ disk size: 4.4M target = 'big.qcow2' self.executes = [] expected_commands = [('rm', '-f', 'big.qcow2.part')] - self.assertRaises(exception.FlavorDiskTooSmall, + self.assertRaises(exception.FlavorDiskSmallerThanImage, images.fetch_to_raw, context, image_id, target, user_id, project_id, max_size=1) diff --git a/nova/tests/unit/virt/xenapi/test_vm_utils.py b/nova/tests/unit/virt/xenapi/test_vm_utils.py index edae8509ecca..8f2be4588484 100644 --- a/nova/tests/unit/virt/xenapi/test_vm_utils.py +++ b/nova/tests/unit/virt/xenapi/test_vm_utils.py @@ -387,7 +387,8 @@ class FetchVhdImageTestCase(VMUtilsTestBase): self.mox.StubOutWithMock(vm_utils, '_check_vdi_size') vm_utils._check_vdi_size(self.context, self.session, self.instance, - "vdi").AndRaise(exception.FlavorDiskTooSmall) + "vdi").AndRaise(exception.FlavorDiskSmallerThanImage( + flavor_size=0, image_size=1)) self.mox.StubOutWithMock(self.session, 'call_xenapi') self.session.call_xenapi("VDI.get_by_uuid", "vdi").AndReturn("ref") @@ -398,7 +399,7 @@ class FetchVhdImageTestCase(VMUtilsTestBase): self.mox.ReplayAll() - self.assertRaises(exception.FlavorDiskTooSmall, + self.assertRaises(exception.FlavorDiskSmallerThanImage, vm_utils._fetch_vhd_image, self.context, self.session, self.instance, 'image_id') @@ -628,7 +629,7 @@ class CheckVDISizeTestCase(VMUtilsTestBase): with mock.patch.object(self.instance, 'get_flavor') as get: self.flavor.root_gb = 1 get.return_value = self.flavor - self.assertRaises(exception.FlavorDiskTooSmall, + self.assertRaises(exception.FlavorDiskSmallerThanImage, vm_utils._check_vdi_size, self.context, self.session, self.instance, self.vdi_uuid) diff --git a/nova/virt/images.py b/nova/virt/images.py index c8f1b6c2549d..5b9374b682d1 100644 --- a/nova/virt/images.py +++ b/nova/virt/images.py @@ -116,7 +116,8 @@ def fetch_to_raw(context, image_href, path, user_id, project_id, max_size=0): {'base': path, 'disk_size': disk_size, 'size': max_size}) - raise exception.FlavorDiskTooSmall() + raise exception.FlavorDiskSmallerThanImage( + flavor_size=max_size, image_size=disk_size) if fmt != "raw" and CONF.force_raw_images: staged = "%s.converted" % path diff --git a/nova/virt/libvirt/imagebackend.py b/nova/virt/libvirt/imagebackend.py index d2b75a81137a..5e14f61691f4 100644 --- a/nova/virt/libvirt/imagebackend.py +++ b/nova/virt/libvirt/imagebackend.py @@ -286,7 +286,8 @@ class Image(object): LOG.error(msg % {'base': base, 'base_size': base_size, 'size': size}) - raise exception.FlavorDiskTooSmall() + raise exception.FlavorDiskSmallerThanImage( + flavor_size=base_size, image_size=size) def get_disk_size(self, name): return disk.get_disk_size(name) diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 0a835e3ae0cb..c20377d03f75 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -139,7 +139,7 @@ PROGRESS_INTERVAL_SECONDS = 300 # Fudge factor to allow for the VHD chain to be slightly larger than # the partitioned space. Otherwise, legitimate images near their -# maximum allowed size can fail on build with FlavorDiskTooSmall. +# maximum allowed size can fail on build with FlavorDiskSmallerThanImage. VHD_SIZE_CHECK_FUDGE_FACTOR_GB = 10 @@ -1497,7 +1497,9 @@ def _check_vdi_size(context, session, instance, vdi_uuid): {'size': size, 'allowed_size': allowed_size}, instance=instance) - raise exception.FlavorDiskTooSmall() + raise exception.FlavorDiskSmallerThanImage( + flavor_size=(flavor.root_gb * units.Gi), + image_size=(size * units.Gi)) def _fetch_disk_image(context, session, instance, name_label, image_id,