summaryrefslogtreecommitdiff
path: root/nova/tests/unit/virt/libvirt
diff options
context:
space:
mode:
Diffstat (limited to 'nova/tests/unit/virt/libvirt')
-rw-r--r--nova/tests/unit/virt/libvirt/test_driver.py61
-rw-r--r--nova/tests/unit/virt/libvirt/volume/test_fibrechannel.py20
-rw-r--r--nova/tests/unit/virt/libvirt/volume/test_iscsi.py9
-rw-r--r--nova/tests/unit/virt/libvirt/volume/test_lightos.py8
-rw-r--r--nova/tests/unit/virt/libvirt/volume/test_nvme.py8
-rw-r--r--nova/tests/unit/virt/libvirt/volume/test_scaleio.py8
-rw-r--r--nova/tests/unit/virt/libvirt/volume/test_storpool.py16
-rw-r--r--nova/tests/unit/virt/libvirt/volume/test_vzstorage.py8
8 files changed, 129 insertions, 9 deletions
diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py
index 66dbf795d8..774498b69f 100644
--- a/nova/tests/unit/virt/libvirt/test_driver.py
+++ b/nova/tests/unit/virt/libvirt/test_driver.py
@@ -9722,7 +9722,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
drvr._disconnect_volume(
self.context, fake_connection_info, fake_instance_1)
mock_volume_driver.disconnect_volume.assert_called_once_with(
- fake_connection_info, fake_instance_1)
+ fake_connection_info, fake_instance_1, force=False)
@mock.patch.object(libvirt_driver.LibvirtDriver, '_detach_encryptor')
@mock.patch('nova.objects.InstanceList.get_uuids_by_host')
@@ -10096,7 +10096,12 @@ class LibvirtConnTestCase(test.NoDBTestCase,
device_name='vdc',
),
mock.call.detach_encryptor(**encryption),
- mock.call.disconnect_volume(connection_info, instance)])
+ mock.call.disconnect_volume(
+ connection_info,
+ instance,
+ force=False,
+ )
+ ])
get_device_conf_func = mock_detach_with_retry.mock_calls[0][1][2]
self.assertEqual(mock_guest.get_disk, get_device_conf_func.func)
self.assertEqual(('vdc',), get_device_conf_func.args)
@@ -20474,16 +20479,64 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.context,
mock.sentinel.connection_info,
instance,
- destroy_secrets=False
+ destroy_secrets=False,
+ force=True
),
mock.call(
self.context,
mock.sentinel.connection_info,
instance,
- destroy_secrets=True
+ destroy_secrets=True,
+ force=True
)
])
+ @mock.patch('nova.virt.libvirt.driver.LibvirtDriver._get_volume_driver')
+ @mock.patch(
+ 'nova.virt.libvirt.driver.LibvirtDriver._should_disconnect_target',
+ new=mock.Mock(return_value=True))
+ @mock.patch('nova.virt.libvirt.driver.LibvirtDriver._detach_encryptor',
+ new=mock.Mock())
+ @mock.patch('nova.virt.libvirt.driver.LibvirtDriver._undefine_domain',
+ new=mock.Mock())
+ @mock.patch('nova.virt.libvirt.driver.LibvirtDriver._get_vpmems',
+ new=mock.Mock(return_value=None))
+ def test_cleanup_disconnect_volume(self, mock_vol_driver):
+ """Verify that we call disconnect_volume() with force=True
+
+ cleanup() is called by destroy() when an instance is being deleted and
+ force=True should be passed down to os-brick's disconnect_volume()
+ call, which will ensure removal of devices regardless of errors.
+
+ We need to ensure that devices are removed when an instance is being
+ deleted to avoid leaving leftover devices that could later be
+ erroneously connected by external entities (example: multipathd) to
+ instances that should not have access to the volumes.
+
+ See https://bugs.launchpad.net/nova/+bug/2004555 for details.
+ """
+ connection_info = mock.MagicMock()
+ block_device_info = {
+ 'block_device_mapping': [
+ {
+ 'connection_info': connection_info
+ }
+ ]
+ }
+ instance = objects.Instance(self.context, **self.test_instance)
+ drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI())
+
+ drvr.cleanup(
+ self.context,
+ instance,
+ network_info={},
+ block_device_info=block_device_info,
+ destroy_vifs=False,
+ destroy_disks=False,
+ )
+ mock_vol_driver.return_value.disconnect_volume.assert_called_once_with(
+ connection_info, instance, force=True)
+
@mock.patch.object(libvirt_driver.LibvirtDriver, '_get_volume_encryption')
@mock.patch.object(libvirt_driver.LibvirtDriver, '_allow_native_luksv1')
def test_swap_volume_native_luks_blocked(self, mock_allow_native_luksv1,
diff --git a/nova/tests/unit/virt/libvirt/volume/test_fibrechannel.py b/nova/tests/unit/virt/libvirt/volume/test_fibrechannel.py
index 06065322f6..55054652c3 100644
--- a/nova/tests/unit/virt/libvirt/volume/test_fibrechannel.py
+++ b/nova/tests/unit/virt/libvirt/volume/test_fibrechannel.py
@@ -81,3 +81,23 @@ class LibvirtFibreChannelVolumeDriverTestCase(
self.assertEqual(requested_size, new_size)
libvirt_driver.connector.extend_volume.assert_called_once_with(
connection_info['data'])
+
+ def test_disconnect_volume(self):
+ device_path = '/dev/fake-dev'
+ connection_info = {'data': {'device_path': device_path}}
+
+ libvirt_driver = fibrechannel.LibvirtFibreChannelVolumeDriver(
+ self.fake_host)
+ libvirt_driver.connector.disconnect_volume = mock.MagicMock()
+ libvirt_driver.disconnect_volume(
+ connection_info, mock.sentinel.instance)
+
+ libvirt_driver.connector.disconnect_volume.assert_called_once_with(
+ connection_info['data'], connection_info['data'], force=False)
+
+ # Verify force=True
+ libvirt_driver.connector.disconnect_volume.reset_mock()
+ libvirt_driver.disconnect_volume(
+ connection_info, mock.sentinel.instance, force=True)
+ libvirt_driver.connector.disconnect_volume.assert_called_once_with(
+ connection_info['data'], connection_info['data'], force=True)
diff --git a/nova/tests/unit/virt/libvirt/volume/test_iscsi.py b/nova/tests/unit/virt/libvirt/volume/test_iscsi.py
index bd516b1dd6..a1111e0d12 100644
--- a/nova/tests/unit/virt/libvirt/volume/test_iscsi.py
+++ b/nova/tests/unit/virt/libvirt/volume/test_iscsi.py
@@ -57,10 +57,19 @@ class LibvirtISCSIVolumeDriverTestCase(
device=device_path))
libvirt_driver.disconnect_volume(connection_info,
mock.sentinel.instance)
+ libvirt_driver.connector.disconnect_volume.assert_called_once_with(
+ connection_info['data'], None, force=False)
msg = mock_LOG_warning.call_args_list[0]
self.assertIn('Ignoring VolumeDeviceNotFound', msg[0][0])
+ # Verify force=True
+ libvirt_driver.connector.disconnect_volume.reset_mock()
+ libvirt_driver.disconnect_volume(
+ connection_info, mock.sentinel.instance, force=True)
+ libvirt_driver.connector.disconnect_volume.assert_called_once_with(
+ connection_info['data'], None, force=True)
+
def test_extend_volume(self):
device_path = '/dev/fake-dev'
connection_info = {'data': {'device_path': device_path}}
diff --git a/nova/tests/unit/virt/libvirt/volume/test_lightos.py b/nova/tests/unit/virt/libvirt/volume/test_lightos.py
index 8a85d73059..f97a696a53 100644
--- a/nova/tests/unit/virt/libvirt/volume/test_lightos.py
+++ b/nova/tests/unit/virt/libvirt/volume/test_lightos.py
@@ -62,7 +62,13 @@ class LibvirtLightVolumeDriverTestCase(test_volume.LibvirtVolumeBaseTestCase):
connection_info = {'data': disk_info}
lightos_driver.disconnect_volume(connection_info, None)
lightos_driver.connector.disconnect_volume.assert_called_once_with(
- disk_info, None)
+ disk_info, None, force=False)
+
+ # Verify force=True
+ lightos_driver.connector.disconnect_volume.reset_mock()
+ lightos_driver.disconnect_volume(connection_info, None, force=True)
+ lightos_driver.connector.disconnect_volume.assert_called_once_with(
+ disk_info, None, force=True)
@mock.patch('os_brick.initiator.connector.InitiatorConnector.factory',
new=mock.Mock(return_value=mock.Mock()))
diff --git a/nova/tests/unit/virt/libvirt/volume/test_nvme.py b/nova/tests/unit/virt/libvirt/volume/test_nvme.py
index 3f593841fa..42ef0adc8d 100644
--- a/nova/tests/unit/virt/libvirt/volume/test_nvme.py
+++ b/nova/tests/unit/virt/libvirt/volume/test_nvme.py
@@ -77,7 +77,13 @@ class LibvirtNVMEVolumeDriverTestCase(test_volume.LibvirtVolumeBaseTestCase):
connection_info = {'data': disk_info}
nvme_driver.disconnect_volume(connection_info, None)
nvme_driver.connector.disconnect_volume.assert_called_once_with(
- disk_info, None)
+ disk_info, None, force=False)
+
+ # Verify force=True
+ nvme_driver.connector.disconnect_volume.reset_mock()
+ nvme_driver.disconnect_volume(connection_info, None, force=True)
+ nvme_driver.connector.disconnect_volume.assert_called_once_with(
+ disk_info, None, force=True)
@mock.patch('os_brick.initiator.connector.InitiatorConnector.factory',
new=mock.Mock(return_value=mock.Mock()))
diff --git a/nova/tests/unit/virt/libvirt/volume/test_scaleio.py b/nova/tests/unit/virt/libvirt/volume/test_scaleio.py
index f0fcba1deb..7d93691d9d 100644
--- a/nova/tests/unit/virt/libvirt/volume/test_scaleio.py
+++ b/nova/tests/unit/virt/libvirt/volume/test_scaleio.py
@@ -49,7 +49,13 @@ class LibvirtScaleIOVolumeDriverTestCase(
conn = {'data': mock.sentinel.conn_data}
sio.disconnect_volume(conn, mock.sentinel.instance)
sio.connector.disconnect_volume.assert_called_once_with(
- mock.sentinel.conn_data, None)
+ mock.sentinel.conn_data, None, force=False)
+
+ # Verify force=True
+ sio.connector.disconnect_volume.reset_mock()
+ sio.disconnect_volume(conn, mock.sentinel.instance, force=True)
+ sio.connector.disconnect_volume.assert_called_once_with(
+ mock.sentinel.conn_data, None, force=True)
@mock.patch('os_brick.initiator.connector.InitiatorConnector.factory',
new=mock.Mock(return_value=mock.Mock()))
diff --git a/nova/tests/unit/virt/libvirt/volume/test_storpool.py b/nova/tests/unit/virt/libvirt/volume/test_storpool.py
index 678d4f8eb4..a3252b8525 100644
--- a/nova/tests/unit/virt/libvirt/volume/test_storpool.py
+++ b/nova/tests/unit/virt/libvirt/volume/test_storpool.py
@@ -53,9 +53,11 @@ class MockStorPoolConnector(object):
}
return {'type': 'block', 'path': test_attached[v]['path']}
- def disconnect_volume(self, connection_info, device_info):
+ def disconnect_volume(self, connection_info, device_info, **kwargs):
self.inst.assertIn('client_id', connection_info)
self.inst.assertIn('volume', connection_info)
+ self.inst.assertIn('force', kwargs)
+ self.inst.assertEqual(self.inst.force, kwargs.get('force'))
v = connection_info['volume']
if v not in test_attached:
@@ -86,6 +88,11 @@ class MockStorPoolInitiator(object):
class LibvirtStorPoolVolumeDriverTestCase(
test_volume.LibvirtVolumeBaseTestCase):
+ def setUp(self):
+ super().setUp()
+ # This is for testing the force flag of disconnect_volume()
+ self.force = False
+
def mock_storpool(f):
def _config_inner_inner1(inst, *args, **kwargs):
@mock.patch(
@@ -175,3 +182,10 @@ class LibvirtStorPoolVolumeDriverTestCase(
libvirt_driver.disconnect_volume(ci_2, mock.sentinel.instance)
self.assertDictEqual({}, test_attached)
+
+ # Connect the volume again so we can detach it again
+ libvirt_driver.connect_volume(ci_2, mock.sentinel.instance)
+ # Verify force=True
+ self.force = True
+ libvirt_driver.disconnect_volume(
+ ci_2, mock.sentinel.instance, force=True)
diff --git a/nova/tests/unit/virt/libvirt/volume/test_vzstorage.py b/nova/tests/unit/virt/libvirt/volume/test_vzstorage.py
index 168efee944..c9e455b193 100644
--- a/nova/tests/unit/virt/libvirt/volume/test_vzstorage.py
+++ b/nova/tests/unit/virt/libvirt/volume/test_vzstorage.py
@@ -95,7 +95,13 @@ class LibvirtVZStorageTestCase(test_volume.LibvirtVolumeBaseTestCase):
conn = {'data': mock.sentinel.conn_data}
drv.disconnect_volume(conn, mock.sentinel.instance)
drv.connector.disconnect_volume.assert_called_once_with(
- mock.sentinel.conn_data, None)
+ mock.sentinel.conn_data, None, force=False)
+
+ # Verify force=True
+ drv.connector.disconnect_volume.reset_mock()
+ drv.disconnect_volume(conn, mock.sentinel.instance, force=True)
+ drv.connector.disconnect_volume.assert_called_once_with(
+ mock.sentinel.conn_data, None, force=True)
def test_libvirt_vzstorage_driver_get_config(self):
libvirt_driver = vzstorage.LibvirtVZStorageVolumeDriver(self.fake_host)