diff -Nru nova-18.1.0/debian/changelog nova-18.1.0/debian/changelog --- nova-18.1.0/debian/changelog 2019-02-28 20:48:43.000000000 +0000 +++ nova-18.1.0/debian/changelog 2019-05-16 08:58:45.000000000 +0000 @@ -1,3 +1,20 @@ +nova (2:18.1.0-0ubuntu3) cosmic; urgency=medium + + * d/p/bug_1825882.patch: Cherry-picked from upstream to ensure + virsh disk attach does not fail silently (LP: #1825882). + * d/p/bug_1826523.patch: Cherry-picked from upstream to ensure + always disconnect volumes after libvirt exceptions (LP: #1826523). + + -- Sahid Orentino Ferdjaoui Thu, 16 May 2019 10:58:45 +0200 + +nova (2:18.1.0-0ubuntu2) cosmic; urgency=medium + + * d/p/xenapi-agent-change-openssl-error-handling.patch: Cherry-picked from + upstream to ensure xenapi agent only raises a RuntimeError exception + when openssl returns a non-zero exit code (LP: #1771506). + + -- Corey Bryant Wed, 01 May 2019 17:21:05 -0400 + nova (2:18.1.0-0ubuntu1) cosmic; urgency=medium * New stable point release for OpenStack Rocky (LP: #1818068). diff -Nru nova-18.1.0/debian/patches/bug_1825882.patch nova-18.1.0/debian/patches/bug_1825882.patch --- nova-18.1.0/debian/patches/bug_1825882.patch 1970-01-01 00:00:00.000000000 +0000 +++ nova-18.1.0/debian/patches/bug_1825882.patch 2019-05-16 08:58:45.000000000 +0000 @@ -0,0 +1,103 @@ +From 34b4220448395f10eb2fd39d68b3f527339ab414 Mon Sep 17 00:00:00 2001 +From: Lee Yarwood +Date: Thu, 25 Apr 2019 14:42:09 +0100 +Subject: [PATCH] libvirt: Stop ignoring unknown libvirtError exceptions during + volume attach + +Id346bce6e47431988cce7001abcf29a9faf2936a attempted to introduce a +simple breadcrumb in the logs to highlight a known Libvirt issue. +Unfortunately this change resulted in libvirtError exceptions that +didn't match the known issue being silently ignored. + +This change corrects this by using excutils.save_and_reraise_exception +to ensure all libvirtError exceptions are logged and raised regardless +of being linked to the known issue. + +Change-Id: Ib440f4f2e484312af5f393722363846f6c95b760 +Closes-Bug: #1825882 +(cherry picked from commit bc57ae50734fa6a70115b6369e867079fb5eb4b8) +(cherry picked from commit b3dedefcc58a1fc76ba37f9f8bb1ef7d238aaceb) +--- + nova/tests/unit/virt/libvirt/test_driver.py | 40 +++++++++++++++++++++ + nova/virt/libvirt/driver.py | 14 +++++--- + 2 files changed, 49 insertions(+), 5 deletions(-) + +diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py +index dfc85c2ec2..43451486e0 100644 +--- a/nova/tests/unit/virt/libvirt/test_driver.py ++++ b/nova/tests/unit/virt/libvirt/test_driver.py +@@ -7778,6 +7778,46 @@ class LibvirtConnTestCase(test.NoDBTestCase, + disk_bus=bdm['disk_bus'], device_type=bdm['device_type']) + mock_log.warning.assert_called_once() + ++ @mock.patch('nova.virt.libvirt.blockinfo.get_info_from_bdm') ++ def test_attach_volume_with_libvirt_exception(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, ++ "Target vdb already exists', device is busy", ++ 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.exception.assert_called_once_with(u'Failed to attach ' ++ 'volume at mountpoint: %s', '/dev/vdb', instance=instance) ++ + @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 b41f270e96..3e354105d1 100644 +--- a/nova/virt/libvirt/driver.py ++++ b/nova/virt/libvirt/driver.py +@@ -1468,11 +1468,15 @@ class LibvirtDriver(driver.ComputeDriver): + # 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 ++ with excutils.save_and_reraise_exception(): ++ 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/1447297')) ++ else: ++ LOG.exception(_('Failed to attach volume at mountpoint: ' ++ '%s'), mountpoint, instance=instance) + except Exception: + LOG.exception(_('Failed to attach volume at mountpoint: %s'), + mountpoint, instance=instance) +-- +2.20.1 + diff -Nru nova-18.1.0/debian/patches/bug_1826523.patch nova-18.1.0/debian/patches/bug_1826523.patch --- nova-18.1.0/debian/patches/bug_1826523.patch 1970-01-01 00:00:00.000000000 +0000 +++ nova-18.1.0/debian/patches/bug_1826523.patch 2019-05-16 08:58:45.000000000 +0000 @@ -0,0 +1,56 @@ +From 786083c91fa69ba9ff90bafe80d3b83b9f9bbc69 Mon Sep 17 00:00:00 2001 +From: Lee Yarwood +Date: Thu, 25 Apr 2019 15:34:41 +0100 +Subject: [PATCH] libvirt: Always disconnect volumes after libvirtError + exceptions + +Building on Ib440f4f2e484312af5f393722363846f6c95b760 we should always +attempt to disconnect volumes from the host when exceptions are thrown +while attempting to attach a volume to a domain. This was previously +done for generic exceptions but not for libvirtError exceptions. + +Closes-Bug: #1826523 +Change-Id: If21230869826c992e7d0398434b9a4b255940213 +(cherry picked from commit 091a910576d9b580678f1881fffa425ab4632f48) +(cherry picked from commit 048d5b790f3da2756a0a1bf2bc015812cb24d53a) +--- + nova/tests/unit/virt/libvirt/test_driver.py | 10 ++++++++-- + nova/virt/libvirt/driver.py | 2 ++ + 2 files changed, 10 insertions(+), 2 deletions(-) + +--- a/nova/tests/unit/virt/libvirt/test_driver.py ++++ b/nova/tests/unit/virt/libvirt/test_driver.py +@@ -7738,11 +7738,13 @@ + mock.patch.object(drvr._host, 'get_guest'), + mock.patch('nova.virt.libvirt.driver.LOG'), + mock.patch.object(drvr, '_connect_volume'), ++ mock.patch.object(drvr, '_disconnect_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_disconnect_volume, mock_get_volume_config, ++ mock_check_discard, mock_build_metadata): + + mock_conf = mock.MagicMock() + mock_guest = mock.MagicMock() +@@ -7757,6 +7759,7 @@ + disk_bus=bdm['disk_bus'], device_type=bdm['device_type']) + mock_log.exception.assert_called_once_with(u'Failed to attach ' + 'volume at mountpoint: %s', '/dev/vdb', instance=instance) ++ mock_disconnect_volume.assert_called_once() + + @mock.patch('nova.utils.get_image_from_system_metadata') + @mock.patch('nova.virt.libvirt.blockinfo.get_info_from_bdm') +--- a/nova/virt/libvirt/driver.py ++++ b/nova/virt/libvirt/driver.py +@@ -1461,6 +1461,8 @@ + else: + LOG.exception(_('Failed to attach volume at mountpoint: ' + '%s'), mountpoint, instance=instance) ++ self._disconnect_volume(context, connection_info, instance, ++ encryption=encryption) + except Exception: + LOG.exception(_('Failed to attach volume at mountpoint: %s'), + mountpoint, instance=instance) diff -Nru nova-18.1.0/debian/patches/series nova-18.1.0/debian/patches/series --- nova-18.1.0/debian/patches/series 2019-02-28 20:48:43.000000000 +0000 +++ nova-18.1.0/debian/patches/series 2019-05-16 08:58:45.000000000 +0000 @@ -7,3 +7,6 @@ skip-py3.7-tests.patch py3.7-get-context-manager-async.patch ensure-rbd-auth-fallback-uses-matching-credentials.patch +xenapi-agent-change-openssl-error-handling.patch +bug_1825882.patch +bug_1826523.patch diff -Nru nova-18.1.0/debian/patches/xenapi-agent-change-openssl-error-handling.patch nova-18.1.0/debian/patches/xenapi-agent-change-openssl-error-handling.patch --- nova-18.1.0/debian/patches/xenapi-agent-change-openssl-error-handling.patch 1970-01-01 00:00:00.000000000 +0000 +++ nova-18.1.0/debian/patches/xenapi-agent-change-openssl-error-handling.patch 2019-05-16 08:58:45.000000000 +0000 @@ -0,0 +1,98 @@ +From 8241b47967adb792a4254eeb58fda1fc55edf314 Mon Sep 17 00:00:00 2001 +From: Corey Bryant +Date: Thu, 07 Feb 2019 10:12:54 -0500 +Subject: [PATCH] xenapi/agent: Change openssl error handling + +Prior to this patch, if the openssl command returned a zero exit code +and wrote details to stderr, nova would raise a RuntimeError exception. +This patch changes the behavior to only raise a RuntimeError exception +when openssl returns a non-zero exit code. Regardless of the exit code +a warning will always be logged with stderr details if stderr is not +None. Note that processutils.execute will now raise a +processutils.ProcessExecutionError exception for any non-zero exit code +since we are passing check_exit_code=True, which we convert to a +Runtime error. + +Thanks to Dimitri John Ledkov and Eric Fried + for helping with this patch. + +Conflicts: + nova/virt/xenapi/agent.py + +NOTE(coreycb): The conflict is due to +Ibe2f478288db42f8168b52dfc14d85ab92ace74b not being in stable/rocky. + +Change-Id: I212ac2b5ccd93e00adb7b9fe102fcb70857c6073 +Partial-Bug: #1771506 +(cherry picked from commit 1da71fa4ab1d7d0f580cd5cbc97f2dfd2e1c378a) +(cherry picked from commit 64793cf6f77c5ba7c9ea51662d936c7545ffce8c) +--- + +diff --git a/nova/tests/unit/virt/xenapi/test_agent.py b/nova/tests/unit/virt/xenapi/test_agent.py +index 8c77445..2848fc2 100644 +--- a/nova/tests/unit/virt/xenapi/test_agent.py ++++ b/nova/tests/unit/virt/xenapi/test_agent.py +@@ -19,6 +19,7 @@ + import mock + from os_xenapi.client import host_agent + from os_xenapi.client import XenAPI ++from oslo_concurrency import processutils + from oslo_utils import uuidutils + + from nova import exception +@@ -311,6 +312,19 @@ + + mock_add_fault.assert_called_once_with(error, mock.ANY) + ++ @mock.patch('oslo_concurrency.processutils.execute') ++ def test_run_ssl_successful(self, mock_execute): ++ mock_execute.return_value = ('0', ++ '*** WARNING : deprecated key derivation used.' ++ 'Using -iter or -pbkdf2 would be better.') ++ agent.SimpleDH()._run_ssl('foo') ++ ++ @mock.patch('oslo_concurrency.processutils.execute', ++ side_effect=processutils.ProcessExecutionError( ++ exit_code=1, stderr=('ERROR: Something bad happened'))) ++ def test_run_ssl_failure(self, mock_execute): ++ self.assertRaises(RuntimeError, agent.SimpleDH()._run_ssl, 'foo') ++ + + class UpgradeRequiredTestCase(test.NoDBTestCase): + def test_less_than(self): +diff --git a/nova/virt/xenapi/agent.py b/nova/virt/xenapi/agent.py +index 9410f47..f0e9949 100644 +--- a/nova/virt/xenapi/agent.py ++++ b/nova/virt/xenapi/agent.py +@@ -21,6 +21,7 @@ + + from os_xenapi.client import host_agent + from os_xenapi.client import XenAPI ++from oslo_concurrency import processutils + from oslo_log import log as logging + from oslo_serialization import base64 + from oslo_serialization import jsonutils +@@ -422,11 +423,18 @@ + 'pass:%s' % self._shared, '-nosalt'] + if decrypt: + cmd.append('-d') +- out, err = utils.execute(*cmd, +- process_input=encodeutils.safe_encode(text)) +- if err: +- raise RuntimeError(_('OpenSSL error: %s') % err) +- return out ++ try: ++ out, err = utils.execute( ++ *cmd, ++ process_input=encodeutils.safe_encode(text), ++ check_exit_code=True) ++ if err: ++ LOG.warning("OpenSSL stderr: %s", err) ++ return out ++ except processutils.ProcessExecutionError as e: ++ raise RuntimeError( ++ _('OpenSSL errored with exit code %(exit_code)d: %(stderr)s') % ++ {'exit_code': e.exit_code, 'stderr': e.stderr}) + + def encrypt(self, text): + return self._run_ssl(text).strip('\n')