From 875afe92086cf60a701abeb45574802feed9329e Mon Sep 17 00:00:00 2001 From: Lee Yarwood Date: Wed, 20 Jun 2018 18:06:13 +0100 Subject: [PATCH] libvirt: Log breadcrumb for known encryption bug The initial implementation of native LUKS support within Libvirt introduced a small issue when using a passphrase that is a multiple of 16 bytes in size. This is documented in the following bug and associated patch posted to the Libvirt development list: Unable to use LUKS passphrase that is exactly 16 bytes long https://bugzilla.redhat.com/show_bug.cgi?id=1447297 [libvirt] [PATCH] Fix padding of encrypted data https://www.redhat.com/archives/libvir-list/2017-May/msg00030.html This change introduces a known issue release note and logs an additional breadcrumb when we appear to hit this with pointers to the above. Closes-Bug: #1778044 Change-Id: Id346bce6e47431988cce7001abcf29a9faf2936a (cherry picked from commit 78891c2305bff6e16706339a9c5eca99a84e409c) --- nova/tests/unit/virt/libvirt/test_driver.py | 40 +++++++++++++++++++ nova/virt/libvirt/driver.py | 10 +++++ .../notes/bug-1778044-f498ee2f2cfb35ea.yaml | 15 +++++++ 3 files changed, 65 insertions(+) create mode 100644 releasenotes/notes/bug-1778044-f498ee2f2cfb35ea.yaml diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 9bf18ace9cc8..0b7de16cbd98 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -7178,6 +7178,46 @@ class LibvirtConnTestCase(test.NoDBTestCase, self._test_check_discard(mock_log, driver_discard=None, bus='virtio', should_log=False) + @mock.patch('nova.virt.libvirt.blockinfo.get_info_from_bdm') + def test_attach_volume_with_libvirt_bug_breadcrumb(self, mock_get_info): + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) + instance = objects.Instance(**self.test_instance) + connection_info = {"driver_volume_type": "fake", + "data": {"device_path": "/fake", + "access_mode": "rw"}} + bdm = {'device_name': 'vdb', + 'disk_bus': 'fake-bus', + 'device_type': 'fake-type'} + disk_info = {'bus': bdm['disk_bus'], 'type': bdm['device_type'], + 'dev': 'vdb'} + libvirt_exc = fakelibvirt.make_libvirtError(fakelibvirt.libvirtError, + "unable to execute QEMU command 'object-add': Incorrect number" + " of padding bytes (56) found on decrypted data", + error_code=fakelibvirt.VIR_ERR_INTERNAL_ERROR) + + with test.nested( + mock.patch.object(drvr._host, 'get_guest'), + mock.patch('nova.virt.libvirt.driver.LOG'), + mock.patch.object(drvr, '_connect_volume'), + mock.patch.object(drvr, '_get_volume_config'), + mock.patch.object(drvr, '_check_discard_for_attach_volume'), + mock.patch.object(drvr, '_build_device_metadata'), + ) as (mock_get_guest, mock_log, mock_connect_volume, + mock_get_volume_config, mock_check_discard, mock_build_metadata): + + mock_conf = mock.MagicMock() + mock_guest = mock.MagicMock() + mock_guest.attach_device.side_effect = libvirt_exc + mock_get_volume_config.return_value = mock_conf + mock_get_guest.return_value = mock_guest + mock_get_info.return_value = disk_info + mock_build_metadata.return_value = objects.InstanceDeviceMetadata() + + self.assertRaises(fakelibvirt.libvirtError, drvr.attach_volume, + self.context, connection_info, instance, "/dev/vdb", + disk_bus=bdm['disk_bus'], device_type=bdm['device_type']) + mock_log.warning.assert_called_once() + @mock.patch('nova.utils.get_image_from_system_metadata') @mock.patch('nova.virt.libvirt.blockinfo.get_info_from_bdm') @mock.patch('nova.virt.libvirt.host.Host._get_domain') diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index ca4414fb70df..29d8687a0006 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -1466,6 +1466,16 @@ class LibvirtDriver(driver.ComputeDriver): instance.device_metadata = self._build_device_metadata( context, instance) instance.save() + + # TODO(lyarwood) Remove the following breadcrumb once all supported + # distributions provide Libvirt 3.3.0 or earlier with + # https://libvirt.org/git/?p=libvirt.git;a=commit;h=7189099 applied. + except libvirt.libvirtError as ex: + if 'Incorrect number of padding bytes' in six.text_type(ex): + LOG.warning(_('Failed to attach encrypted volume due to a ' + 'known Libvirt issue, see the following bug for details: ' + 'https://bugzilla.redhat.com/show_bug.cgi?id=1447297')) + raise except Exception: LOG.exception(_('Failed to attach volume at mountpoint: %s'), mountpoint, instance=instance) diff --git a/releasenotes/notes/bug-1778044-f498ee2f2cfb35ea.yaml b/releasenotes/notes/bug-1778044-f498ee2f2cfb35ea.yaml new file mode 100644 index 000000000000..0a348951de78 --- /dev/null +++ b/releasenotes/notes/bug-1778044-f498ee2f2cfb35ea.yaml @@ -0,0 +1,15 @@ +--- +issues: + - | + The initial implementation of native LUKS decryption within Libvirt 2.2.0 + had a `known issue`_ with the use of passphrases that were a multiple of 16 + bytes in size. This was `resolved`_ in the upstream 3.3.0 release of + Libvirt and has been backported to various downstream distribution specific + versions. + + A simple warning will reference the above if this issue is encountered by + Nova however operators of the environment will still need to update + Libvirt to a version where this issue has been fixed to resolve the issue. + + .. _known issue: https://bugzilla.redhat.com/show_bug.cgi?id=1447297 + .. _resolved: https://libvirt.org/git/?p=libvirt.git;a=commit;h=7189099