Skip to content

Commit 79bcb4e

Browse files
yenaimriedem
authored andcommitted
libvirt: disconnect volume when encryption fails
The compute node has left the attachment information after the encryption fails. This patch fixes this by ensuring the volume is disconnected when an exception occurs. Change-Id: I9d652f182d83a2557ff6ed0b21c69a735c3f9840 Closes-Bug: #1812945
1 parent 7491de2 commit 79bcb4e

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

nova/tests/unit/virt/libvirt/test_driver.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7507,6 +7507,66 @@ def test_get_volume_config(self, _set_cache_mode, get_config):
75077507
_set_cache_mode.assert_called_once_with(config)
75087508
self.assertEqual(config_guest_disk.to_xml(), config.to_xml())
75097509

7510+
@mock.patch.object(libvirt_driver.LibvirtDriver, '_get_volume_driver')
7511+
@mock.patch.object(libvirt_driver.LibvirtDriver, '_attach_encryptor')
7512+
def test_connect_volume_encryption_success(
7513+
self, mock_attach_encryptor, mock_get_volume_driver):
7514+
7515+
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
7516+
mock_volume_driver = mock.MagicMock(
7517+
spec=volume_drivers.LibvirtBaseVolumeDriver)
7518+
mock_get_volume_driver.return_value = mock_volume_driver
7519+
7520+
connection_info = {'driver_volume_type': 'fake',
7521+
'data': {'device_path': '/fake',
7522+
'access_mode': 'rw',
7523+
'volume_id': uuids.volume_id}}
7524+
encryption = {'provider': encryptors.LUKS,
7525+
'encryption_key_id': uuids.encryption_key_id}
7526+
instance = mock.sentinel.instance
7527+
7528+
drvr._connect_volume(self.context, connection_info, instance,
7529+
encryption=encryption)
7530+
7531+
mock_get_volume_driver.assert_called_once_with(connection_info)
7532+
mock_volume_driver.connect_volume.assert_called_once_with(
7533+
connection_info, instance)
7534+
mock_attach_encryptor.assert_called_once_with(
7535+
self.context, connection_info, encryption, True)
7536+
mock_volume_driver.disconnect_volume.assert_not_called()
7537+
7538+
@mock.patch.object(libvirt_driver.LibvirtDriver, '_get_volume_driver')
7539+
@mock.patch.object(libvirt_driver.LibvirtDriver, '_attach_encryptor')
7540+
def test_connect_volume_encryption_fail(
7541+
self, mock_attach_encryptor, mock_get_volume_driver):
7542+
7543+
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
7544+
mock_volume_driver = mock.MagicMock(
7545+
spec=volume_drivers.LibvirtBaseVolumeDriver)
7546+
mock_get_volume_driver.return_value = mock_volume_driver
7547+
7548+
connection_info = {'driver_volume_type': 'fake',
7549+
'data': {'device_path': '/fake',
7550+
'access_mode': 'rw',
7551+
'volume_id': uuids.volume_id}}
7552+
encryption = {'provider': encryptors.LUKS,
7553+
'encryption_key_id': uuids.encryption_key_id}
7554+
instance = mock.sentinel.instance
7555+
mock_attach_encryptor.side_effect = processutils.ProcessExecutionError
7556+
7557+
self.assertRaises(processutils.ProcessExecutionError,
7558+
drvr._connect_volume,
7559+
self.context, connection_info, instance,
7560+
encryption=encryption)
7561+
7562+
mock_get_volume_driver.assert_called_once_with(connection_info)
7563+
mock_volume_driver.connect_volume.assert_called_once_with(
7564+
connection_info, instance)
7565+
mock_attach_encryptor.assert_called_once_with(
7566+
self.context, connection_info, encryption, True)
7567+
mock_volume_driver.disconnect_volume.assert_called_once_with(
7568+
connection_info, instance)
7569+
75107570
@mock.patch.object(key_manager, 'API')
75117571
@mock.patch.object(libvirt_driver.LibvirtDriver, '_get_volume_encryption')
75127572
@mock.patch.object(libvirt_driver.LibvirtDriver, '_use_native_luks')

nova/virt/libvirt/driver.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,8 +1256,15 @@ def _connect_volume(self, context, connection_info, instance,
12561256
encryption=None, allow_native_luks=True):
12571257
vol_driver = self._get_volume_driver(connection_info)
12581258
vol_driver.connect_volume(connection_info, instance)
1259-
self._attach_encryptor(context, connection_info, encryption,
1260-
allow_native_luks)
1259+
try:
1260+
self._attach_encryptor(
1261+
context, connection_info, encryption, allow_native_luks)
1262+
except Exception:
1263+
# Encryption failed so rollback the volume connection.
1264+
with excutils.save_and_reraise_exception(logger=LOG):
1265+
LOG.exception("Failure attaching encryptor; rolling back "
1266+
"volume connection", instance=instance)
1267+
vol_driver.disconnect_volume(connection_info, instance)
12611268

12621269
def _should_disconnect_target(self, context, connection_info, instance):
12631270
connection_count = 0

0 commit comments

Comments
 (0)