@@ -18589,6 +18589,7 @@ def _test_attach_detach_interface_get_config(self, method_name):
18589
18589
lambda self, instance: FakeVirtDomain())
18590
18590
18591
18591
instance = objects.Instance(**self.test_instance)
18592
+ instance.info_cache = None
18592
18593
network_info = _fake_network_info(self)
18593
18594
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
18594
18595
@@ -22957,23 +22958,20 @@ def _test_detach_interface(self, state, device_not_found=False):
22957
22958
# This will trigger _detach_with_retry to raise
22958
22959
# DeviceNotFound
22959
22960
get_interface_calls = [
22960
- expected_cfg, # detach_interface() itself gets the config
22961
22961
expected_cfg, # _detach_with_retry: persistent config
22962
22962
None, # _detach_with_retry: no device in live config
22963
22963
None, # _detach_with_retry: persistent config gone as detached
22964
22964
]
22965
22965
else:
22966
22966
if state in (power_state.RUNNING, power_state.PAUSED):
22967
22967
get_interface_calls = [
22968
- expected_cfg, # detach_interface() itself gets the config
22969
22968
expected_cfg, # _detach_with_retry: persistent config
22970
22969
expected_cfg, # _detach_with_retry: live config
22971
22970
None, # _detach_with_retry: persistent config gone
22972
22971
None # _detach_with_retry: live config gone
22973
22972
]
22974
22973
else:
22975
22974
get_interface_calls = [
22976
- expected_cfg, # detach_interface() itself gets the config
22977
22975
expected_cfg, # _detach_with_retry: persistent config
22978
22976
None, # _detach_with_retry: persistent config gone
22979
22977
]
@@ -23008,7 +23006,6 @@ def _test_detach_interface(self, state, device_not_found=False):
23008
23006
flags=fakelibvirt.VIR_DOMAIN_AFFECT_CONFIG)
23009
23007
mock_get_interface.assert_has_calls(
23010
23008
[
23011
- mock.call(expected_cfg),
23012
23009
mock.call(expected_cfg, from_persistent_config=True),
23013
23010
mock.call(expected_cfg),
23014
23011
mock.call(expected_cfg, from_persistent_config=True),
@@ -23026,7 +23023,6 @@ def _test_detach_interface(self, state, device_not_found=False):
23026
23023
])
23027
23024
mock_get_interface.assert_has_calls(
23028
23025
[
23029
- mock.call(expected_cfg),
23030
23026
mock.call(expected_cfg, from_persistent_config=True),
23031
23027
mock.call(expected_cfg),
23032
23028
mock.call(expected_cfg, from_persistent_config=True),
@@ -23038,7 +23034,6 @@ def _test_detach_interface(self, state, device_not_found=False):
23038
23034
flags=fakelibvirt.VIR_DOMAIN_AFFECT_CONFIG)
23039
23035
mock_get_interface.assert_has_calls(
23040
23036
[
23041
- mock.call(expected_cfg),
23042
23037
mock.call(expected_cfg, from_persistent_config=True),
23043
23038
mock.call(expected_cfg, from_persistent_config=True),
23044
23039
])
@@ -23064,6 +23059,7 @@ def test_detach_interface_device_not_found(self, mock_log):
23064
23059
# Asserts that we don't log an error when the interface device is not
23065
23060
# found on the guest after a libvirt error during detach.
23066
23061
instance = self._create_instance()
23062
+ instance.info_cache = None
23067
23063
vif = _fake_network_info(self)[0]
23068
23064
guest = mock.Mock(spec=libvirt_guest.Guest)
23069
23065
guest.get_power_state = mock.Mock()
@@ -23081,36 +23077,6 @@ def test_detach_interface_device_not_found(self, mock_log):
23081
23077
self.assertIn('the device is no longer found on the guest',
23082
23078
str(mock_log.warning.call_args[0]))
23083
23079
23084
- @mock.patch('nova.virt.libvirt.driver.LibvirtDriver.'
23085
- '_detach_with_retry')
23086
- @mock.patch('nova.virt.libvirt.driver.LOG')
23087
- def test_detach_interface_guest_not_found_after_detach(
23088
- self, mock_log, mock_detach_with_retry
23089
- ):
23090
- # Asserts that we don't raise an exception when the guest is gone
23091
- # after a libvirt error during detach.
23092
- instance = self._create_instance()
23093
- vif = _fake_network_info(self, 1)[0]
23094
- guest = mock.MagicMock()
23095
- guest.get_power_state.return_value = power_state.RUNNING
23096
- guest.get_interface_by_cfg.return_value = (
23097
- vconfig.LibvirtConfigGuestInterface())
23098
- get_guest_mock = mock.Mock()
23099
- # Host.get_guest should be called twice: the first time it is found,
23100
- # the second time it is gone.
23101
- get_guest_mock.side_effect = (
23102
- guest, exception.InstanceNotFound(instance_id=instance.uuid))
23103
- self.drvr._host.get_guest = get_guest_mock
23104
- error = fakelibvirt.libvirtError(
23105
- 'internal error: End of file from qemu monitor')
23106
- error.err = (fakelibvirt.VIR_ERR_OPERATION_FAILED,)
23107
- mock_detach_with_retry.side_effect = error
23108
- self.drvr.detach_interface(self.context, instance, vif)
23109
- self.assertEqual(1, mock_log.info.call_count)
23110
- self.assertIn('Instance disappeared while detaching interface',
23111
- mock_log.info.call_args[0][0])
23112
- get_guest_mock.assert_has_calls([mock.call(instance)] * 2)
23113
-
23114
23080
@mock.patch('threading.Event.wait', new=mock.Mock())
23115
23081
@mock.patch.object(FakeVirtDomain, 'info')
23116
23082
@mock.patch.object(FakeVirtDomain, 'detachDeviceFlags')
@@ -23154,7 +23120,6 @@ def test_detach_interface_device_with_same_mac_address(
23154
23120
mock.patch.object(
23155
23121
libvirt_guest.Guest, 'get_interface_by_cfg',
23156
23122
side_effect=[
23157
- expected, # detach_interface gets the config
23158
23123
expected, # _detach_with_retry: persistent config
23159
23124
expected, # _detach_with_retry: live config
23160
23125
None, # _detach_with_retry: persistent gone
@@ -23168,14 +23133,12 @@ def test_detach_interface_device_with_same_mac_address(
23168
23133
23169
23134
mock_get_interface.assert_has_calls(
23170
23135
[
23171
- mock.call(expected, ),
23172
23136
mock.call(expected, from_persistent_config=True),
23173
23137
mock.call(expected),
23174
23138
mock.call(expected, from_persistent_config=True),
23175
23139
mock.call(expected),
23176
23140
]
23177
23141
)
23178
- self.assertEqual(5, mock_get_interface.call_count)
23179
23142
mock_get_config.assert_called_once_with(
23180
23143
instance, network_info[0], test.MatchType(objects.ImageMeta),
23181
23144
test.MatchType(objects.Flavor), CONF.libvirt.virt_type)
@@ -23197,7 +23160,6 @@ def test_detach_interface_guest_set_metadata(self):
23197
23160
instance = self._create_instance()
23198
23161
network_info = _fake_network_info(self, num_networks=3)
23199
23162
vif = network_info[0]
23200
- interface = vconfig.LibvirtConfigGuestInterface()
23201
23163
image_meta = objects.ImageMeta.from_dict({})
23202
23164
disk_info = blockinfo.get_disk_info(
23203
23165
CONF.libvirt.virt_type, instance, image_meta)
@@ -23210,8 +23172,6 @@ def test_detach_interface_guest_set_metadata(self):
23210
23172
self.drvr._host, 'get_guest', return_value=guest),
23211
23173
mock.patch.object(
23212
23174
self.drvr.vif_driver, 'get_config', return_value=cfg),
23213
- mock.patch.object(
23214
- guest, 'get_interface_by_cfg', return_value=interface),
23215
23175
mock.patch.object(
23216
23176
instance, 'get_network_info', return_value=network_info),
23217
23177
mock.patch.object(
@@ -23220,16 +23180,15 @@ def test_detach_interface_guest_set_metadata(self):
23220
23180
self.drvr, '_get_guest_config_meta', return_value=config_meta),
23221
23181
mock.patch.object(guest, 'set_metadata')
23222
23182
) as (
23223
- mock_get_guest, mock_get_config, mock_get_interface_by_cfg ,
23224
- mock_get_network_info, mock_detach_with_retry ,
23225
- mock_get_guest_config_meta, mock_set_metadata
23183
+ mock_get_guest, mock_get_config, mock_get_network_info ,
23184
+ mock_detach_with_retry, mock_get_guest_config_meta ,
23185
+ mock_set_metadata
23226
23186
):
23227
23187
self.drvr.detach_interface(self.context, instance, vif)
23228
23188
mock_get_guest.assert_called_once_with(instance)
23229
23189
mock_get_config.assert_called_once_with(
23230
23190
instance, vif, test.MatchType(objects.ImageMeta),
23231
23191
test.MatchType(objects.Flavor), CONF.libvirt.virt_type)
23232
- mock_get_interface_by_cfg.assert_called_once_with(cfg)
23233
23192
mock_detach_with_retry.assert_called_once_with(
23234
23193
guest, instance.uuid, mock.ANY, device_name=None)
23235
23194
mock_get_network_info.assert_called_once_with()
@@ -23791,6 +23750,56 @@ def test__detach_with_retry_libvirt_reports_not_found_give_up(self):
23791
23750
mock_guest.detach_device.assert_called_once_with(
23792
23751
mock_dev, persistent=True, live=False)
23793
23752
23753
+ @mock.patch.object(libvirt_driver.LOG, 'warning')
23754
+ def test__detach_with_retry_libvirt_reports_domain_not_found(
23755
+ self, mock_warning
23756
+ ):
23757
+ """Test that libvirt reports that the domain is not found and assert
23758
+ that it is only logged.
23759
+ """
23760
+ drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
23761
+ mock_guest = mock.Mock(spec=libvirt_guest.Guest)
23762
+ mock_guest.get_power_state.return_value = power_state.SHUTDOWN
23763
+
23764
+ mock_dev = mock.Mock(spec=vconfig.LibvirtConfigGuestDisk)
23765
+ mock_dev.alias = 'virtio-disk1'
23766
+
23767
+ mock_get_device_conf_func = mock.Mock(
23768
+ # The first call is to get the device from the persistent domain
23769
+ # before the detach. The second calls to double check that the
23770
+ # device is gone after libvirt returned. This second call is
23771
+ # pointless in the current case as libvirt returned that the domain
23772
+ # does not exists. So the code could know that there is no device.
23773
+ # Still for simplicity the call is made and expected to return None
23774
+ side_effect=[
23775
+ mock_dev,
23776
+ None,
23777
+ ]
23778
+ )
23779
+
23780
+ mock_guest.detach_device.side_effect = fakelibvirt.make_libvirtError(
23781
+ fakelibvirt.libvirtError,
23782
+ msg='error',
23783
+ error_code=fakelibvirt.VIR_ERR_NO_DOMAIN)
23784
+
23785
+ drvr._detach_with_retry(
23786
+ mock_guest,
23787
+ uuids.instance_uuid,
23788
+ mock_get_device_conf_func,
23789
+ device_name='vdb',
23790
+ )
23791
+
23792
+ mock_guest.has_persistent_configuration.assert_called_once_with()
23793
+ mock_get_device_conf_func.assert_has_calls([
23794
+ mock.call(from_persistent_config=True),
23795
+ mock.call(from_persistent_config=True),
23796
+ ])
23797
+ mock_guest.detach_device.assert_called_once_with(
23798
+ mock_dev, persistent=True, live=False)
23799
+ mock_warning.assert_called_once_with(
23800
+ 'During device detach, instance disappeared.',
23801
+ instance_uuid=uuids.instance_uuid)
23802
+
23794
23803
@ddt.data(power_state.RUNNING, power_state.PAUSED)
23795
23804
def test__detach_with_retry_other_sync_libvirt_error(self, state):
23796
23805
"""Test that libvirt reports non device related error during detach
@@ -23809,7 +23818,7 @@ def test__detach_with_retry_other_sync_libvirt_error(self, state):
23809
23818
mock_guest.detach_device.side_effect = fakelibvirt.make_libvirtError(
23810
23819
fakelibvirt.libvirtError,
23811
23820
msg='error',
23812
- error_code=fakelibvirt.VIR_ERR_NO_DOMAIN )
23821
+ error_code=fakelibvirt.VIR_ERR_INTERNAL_ERROR )
23813
23822
23814
23823
self.assertRaises(
23815
23824
fakelibvirt.libvirtError,
0 commit comments