Merge "libvirt: disconnect volume when encryption fails"

This commit is contained in:
Zuul 2019-04-06 15:23:04 +00:00 committed by Gerrit Code Review
commit a777384697
2 changed files with 69 additions and 2 deletions

View File

@ -7450,6 +7450,66 @@ class LibvirtConnTestCase(test.NoDBTestCase,
_set_cache_mode.assert_called_once_with(config)
self.assertEqual(config_guest_disk.to_xml(), config.to_xml())
@mock.patch.object(libvirt_driver.LibvirtDriver, '_get_volume_driver')
@mock.patch.object(libvirt_driver.LibvirtDriver, '_attach_encryptor')
def test_connect_volume_encryption_success(
self, mock_attach_encryptor, mock_get_volume_driver):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
mock_volume_driver = mock.MagicMock(
spec=volume_drivers.LibvirtBaseVolumeDriver)
mock_get_volume_driver.return_value = mock_volume_driver
connection_info = {'driver_volume_type': 'fake',
'data': {'device_path': '/fake',
'access_mode': 'rw',
'volume_id': uuids.volume_id}}
encryption = {'provider': encryptors.LUKS,
'encryption_key_id': uuids.encryption_key_id}
instance = mock.sentinel.instance
drvr._connect_volume(self.context, connection_info, instance,
encryption=encryption)
mock_get_volume_driver.assert_called_once_with(connection_info)
mock_volume_driver.connect_volume.assert_called_once_with(
connection_info, instance)
mock_attach_encryptor.assert_called_once_with(
self.context, connection_info, encryption, True)
mock_volume_driver.disconnect_volume.assert_not_called()
@mock.patch.object(libvirt_driver.LibvirtDriver, '_get_volume_driver')
@mock.patch.object(libvirt_driver.LibvirtDriver, '_attach_encryptor')
def test_connect_volume_encryption_fail(
self, mock_attach_encryptor, mock_get_volume_driver):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
mock_volume_driver = mock.MagicMock(
spec=volume_drivers.LibvirtBaseVolumeDriver)
mock_get_volume_driver.return_value = mock_volume_driver
connection_info = {'driver_volume_type': 'fake',
'data': {'device_path': '/fake',
'access_mode': 'rw',
'volume_id': uuids.volume_id}}
encryption = {'provider': encryptors.LUKS,
'encryption_key_id': uuids.encryption_key_id}
instance = mock.sentinel.instance
mock_attach_encryptor.side_effect = processutils.ProcessExecutionError
self.assertRaises(processutils.ProcessExecutionError,
drvr._connect_volume,
self.context, connection_info, instance,
encryption=encryption)
mock_get_volume_driver.assert_called_once_with(connection_info)
mock_volume_driver.connect_volume.assert_called_once_with(
connection_info, instance)
mock_attach_encryptor.assert_called_once_with(
self.context, connection_info, encryption, True)
mock_volume_driver.disconnect_volume.assert_called_once_with(
connection_info, instance)
@mock.patch.object(key_manager, 'API')
@mock.patch.object(libvirt_driver.LibvirtDriver, '_get_volume_encryption')
@mock.patch.object(libvirt_driver.LibvirtDriver, '_use_native_luks')

View File

@ -1301,8 +1301,15 @@ class LibvirtDriver(driver.ComputeDriver):
encryption=None, allow_native_luks=True):
vol_driver = self._get_volume_driver(connection_info)
vol_driver.connect_volume(connection_info, instance)
self._attach_encryptor(context, connection_info, encryption,
allow_native_luks)
try:
self._attach_encryptor(
context, connection_info, encryption, allow_native_luks)
except Exception:
# Encryption failed so rollback the volume connection.
with excutils.save_and_reraise_exception(logger=LOG):
LOG.exception("Failure attaching encryptor; rolling back "
"volume connection", instance=instance)
vol_driver.disconnect_volume(connection_info, instance)
def _should_disconnect_target(self, context, connection_info, instance):
connection_count = 0