diff --git a/nova/tests/unit/virt/libvirt/test_utils.py b/nova/tests/unit/virt/libvirt/test_utils.py index 61155d707a31..27f220d2fd9f 100644 --- a/nova/tests/unit/virt/libvirt/test_utils.py +++ b/nova/tests/unit/virt/libvirt/test_utils.py @@ -419,6 +419,7 @@ class LibvirtUtilsTestCase(test.NoDBTestCase): FakeImgInfo.file_format = file_format FakeImgInfo.backing_file = backing_file FakeImgInfo.virtual_size = 1 + FakeImgInfo.format_specific = None if file_format == 'raw' else {} return FakeImgInfo() diff --git a/nova/tests/unit/virt/test_images.py b/nova/tests/unit/virt/test_images.py index 62a61c1e8b76..272a1cae3626 100644 --- a/nova/tests/unit/virt/test_images.py +++ b/nova/tests/unit/virt/test_images.py @@ -112,6 +112,37 @@ class QemuTestCase(test.NoDBTestCase): images.fetch_to_raw, None, 'href123', '/no/path') + @mock.patch.object(images, 'convert_image', + side_effect=exception.ImageUnacceptable) + @mock.patch.object(images, 'qemu_img_info') + @mock.patch.object(images, 'fetch') + def test_fetch_to_raw_data_file(self, convert_image, qemu_img_info_fn, + fetch): + # NOTE(danms): the above test needs the following line as well, as it + # is broken without it. + qemu_img_info = qemu_img_info_fn.return_value + qemu_img_info.backing_file = None + qemu_img_info.file_format = 'qcow2' + qemu_img_info.virtual_size = 20 + qemu_img_info.format_specific = {'data': {'data-file': 'somefile'}} + self.assertRaisesRegex(exception.ImageUnacceptable, + 'Image href123 is unacceptable.*somefile', + images.fetch_to_raw, + None, 'href123', '/no/path') + + @mock.patch('os.rename') + @mock.patch.object(images, 'qemu_img_info') + @mock.patch.object(images, 'fetch') + def test_fetch_to_raw_from_raw(self, fetch, qemu_img_info_fn, mock_rename): + # Make sure we support a case where we fetch an already-raw image and + # qemu-img returns None for "format_specific". + qemu_img_info = qemu_img_info_fn.return_value + qemu_img_info.file_format = 'raw' + qemu_img_info.backing_file = None + qemu_img_info.format_specific = None + images.fetch_to_raw(None, 'href123', '/no/path') + mock_rename.assert_called_once_with('/no/path.part', '/no/path') + @mock.patch.object(compute_utils, 'disk_ops_semaphore') @mock.patch('nova.privsep.utils.supports_direct_io', return_value=True) @mock.patch('oslo_concurrency.processutils.execute') diff --git a/nova/virt/images.py b/nova/virt/images.py index ad5aaa28878e..d4c09068d872 100644 --- a/nova/virt/images.py +++ b/nova/virt/images.py @@ -160,6 +160,15 @@ def fetch_to_raw(context, image_href, path, trusted_certs=None): reason=(_("fmt=%(fmt)s backed by: %(backing_file)s") % {'fmt': fmt, 'backing_file': backing_file})) + try: + data_file = data.format_specific['data']['data-file'] + except (KeyError, TypeError, AttributeError): + data_file = None + if data_file is not None: + raise exception.ImageUnacceptable(image_id=image_href, + reason=(_("fmt=%(fmt)s has data-file: %(data_file)s") % + {'fmt': fmt, 'data_file': data_file})) + if fmt == 'vmdk': check_vmdk_image(image_href, data)