From f5bc2c7ae45d83d90770a3e55bac0ae2465a8775 Mon Sep 17 00:00:00 2001 From: Lee Yarwood Date: Wed, 19 Feb 2020 20:39:54 +0000 Subject: [PATCH] libvirt: Provide the backing file format when creating qcow2 disks Libvirt v6.0.0 [1] will now fail to launch a domain when using qcow2 disks where the backing file format is not recorded in the qcow2 metadata. There are some discussions upstream around relaxing this slightly [2] but for now any attempt to launch an instance using qcow2 disks will fail as Nova does not populate this value when creating the disk. Nova needs to at a minimum start populating this field and depending on the outcome of the thread upstream in Libvirt also potentially handle the upgrade case where we may need to rebase existing disks in order to update the metadata. For now this change simply adds the backing_fmt option to the qemu-img command line used to create these disks. [1] https://github.com/libvirt/libvirt/commit/3615e8b39badf2a526996a69dc91a92b04cf262e [2] https://www.redhat.com/archives/libvir-list/2020-February/msg00616.html Partial-Bug: #1864020 Change-Id: I77ebada015f6522a300be4fa043fb8676458402b (cherry picked from commit 0cfe9c81e3fe4d268c9949c6b8e873abab94a407) (cherry picked from commit 7fd41e9b8c0f0f9cbccd63fbdbcc863de7db50f5) --- nova/tests/unit/virt/libvirt/test_utils.py | 23 +++++++++++++--------- nova/virt/libvirt/utils.py | 3 ++- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/nova/tests/unit/virt/libvirt/test_utils.py b/nova/tests/unit/virt/libvirt/test_utils.py index 674b66f0cbc1..fbe54ff94451 100644 --- a/nova/tests/unit/virt/libvirt/test_utils.py +++ b/nova/tests/unit/virt/libvirt/test_utils.py @@ -353,16 +353,21 @@ ID TAG VM SIZE DATE VM CLOCK @mock.patch('os.path.exists', return_value=True) @mock.patch('oslo_concurrency.processutils.execute') - def test_create_cow_image(self, mock_execute, mock_exists): + @mock.patch('nova.virt.images.qemu_img_info') + def test_create_cow_image(self, mock_info, mock_execute, mock_exists): mock_execute.return_value = ('stdout', None) - libvirt_utils.create_cow_image('/some/path', '/the/new/cow') - expected_args = [(('env', 'LC_ALL=C', 'LANG=C', - 'qemu-img', 'info', '/some/path'), - {'prlimit': images.QEMU_IMG_LIMITS}), - (('qemu-img', 'create', '-f', 'qcow2', - '-o', 'backing_file=/some/path', - '/the/new/cow'),)] - self.assertEqual(expected_args, mock_execute.call_args_list) + mock_info.return_value = mock.Mock( + file_format=mock.sentinel.backing_fmt, + cluster_size=mock.sentinel.cluster_size) + libvirt_utils.create_cow_image(mock.sentinel.backing_path, + mock.sentinel.new_path) + mock_info.assert_called_once_with(mock.sentinel.backing_path) + mock_execute.assert_has_calls([mock.call( + 'qemu-img', 'create', '-f', 'qcow2', '-o', + 'backing_file=%s,backing_fmt=%s,cluster_size=%s' % ( + mock.sentinel.backing_path, mock.sentinel.backing_fmt, + mock.sentinel.cluster_size), + mock.sentinel.new_path)]) @ddt.unpack @ddt.data({'fs_type': 'some_fs_type', diff --git a/nova/virt/libvirt/utils.py b/nova/virt/libvirt/utils.py index cb80afdd9d83..18765a68afa4 100644 --- a/nova/virt/libvirt/utils.py +++ b/nova/virt/libvirt/utils.py @@ -108,8 +108,9 @@ def create_cow_image(backing_file, path, size=None): base_cmd = ['qemu-img', 'create', '-f', 'qcow2'] cow_opts = [] if backing_file: - cow_opts += ['backing_file=%s' % backing_file] base_details = images.qemu_img_info(backing_file) + cow_opts += ['backing_file=%s' % backing_file] + cow_opts += ['backing_fmt=%s' % base_details.file_format] else: base_details = None # Explicitly inherit the value of 'cluster_size' property of a qcow2