@@ -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
@@ -23013,23 +23014,20 @@ def _test_detach_interface(self, state, device_not_found=False):
23013
23014
# This will trigger _detach_with_retry to raise
23014
23015
# DeviceNotFound
23015
23016
get_interface_calls = [
23016
- expected_cfg, # detach_interface() itself gets the config
23017
23017
expected_cfg, # _detach_with_retry: persistent config
23018
23018
None, # _detach_with_retry: no device in live config
23019
23019
None, # _detach_with_retry: persistent config gone as detached
23020
23020
]
23021
23021
else:
23022
23022
if state in (power_state.RUNNING, power_state.PAUSED):
23023
23023
get_interface_calls = [
23024
- expected_cfg, # detach_interface() itself gets the config
23025
23024
expected_cfg, # _detach_with_retry: persistent config
23026
23025
expected_cfg, # _detach_with_retry: live config
23027
23026
None, # _detach_with_retry: persistent config gone
23028
23027
None # _detach_with_retry: live config gone
23029
23028
]
23030
23029
else:
23031
23030
get_interface_calls = [
23032
- expected_cfg, # detach_interface() itself gets the config
23033
23031
expected_cfg, # _detach_with_retry: persistent config
23034
23032
None, # _detach_with_retry: persistent config gone
23035
23033
]
@@ -23064,7 +23062,6 @@ def _test_detach_interface(self, state, device_not_found=False):
23064
23062
flags=fakelibvirt.VIR_DOMAIN_AFFECT_CONFIG)
23065
23063
mock_get_interface.assert_has_calls(
23066
23064
[
23067
- mock.call(expected_cfg),
23068
23065
mock.call(expected_cfg, from_persistent_config=True),
23069
23066
mock.call(expected_cfg),
23070
23067
mock.call(expected_cfg, from_persistent_config=True),
@@ -23082,7 +23079,6 @@ def _test_detach_interface(self, state, device_not_found=False):
23082
23079
])
23083
23080
mock_get_interface.assert_has_calls(
23084
23081
[
23085
- mock.call(expected_cfg),
23086
23082
mock.call(expected_cfg, from_persistent_config=True),
23087
23083
mock.call(expected_cfg),
23088
23084
mock.call(expected_cfg, from_persistent_config=True),
@@ -23094,7 +23090,6 @@ def _test_detach_interface(self, state, device_not_found=False):
23094
23090
flags=fakelibvirt.VIR_DOMAIN_AFFECT_CONFIG)
23095
23091
mock_get_interface.assert_has_calls(
23096
23092
[
23097
- mock.call(expected_cfg),
23098
23093
mock.call(expected_cfg, from_persistent_config=True),
23099
23094
mock.call(expected_cfg, from_persistent_config=True),
23100
23095
])
@@ -23120,6 +23115,7 @@ def test_detach_interface_device_not_found(self, mock_log):
23120
23115
# Asserts that we don't log an error when the interface device is not
23121
23116
# found on the guest after a libvirt error during detach.
23122
23117
instance = self._create_instance()
23118
+ instance.info_cache = None
23123
23119
vif = _fake_network_info(self)[0]
23124
23120
guest = mock.Mock(spec=libvirt_guest.Guest)
23125
23121
guest.get_power_state = mock.Mock()
@@ -23137,36 +23133,6 @@ def test_detach_interface_device_not_found(self, mock_log):
23137
23133
self.assertIn('the device is no longer found on the guest',
23138
23134
str(mock_log.warning.call_args[0]))
23139
23135
23140
- @mock.patch('nova.virt.libvirt.driver.LibvirtDriver.'
23141
- '_detach_with_retry')
23142
- @mock.patch('nova.virt.libvirt.driver.LOG')
23143
- def test_detach_interface_guest_not_found_after_detach(
23144
- self, mock_log, mock_detach_with_retry
23145
- ):
23146
- # Asserts that we don't raise an exception when the guest is gone
23147
- # after a libvirt error during detach.
23148
- instance = self._create_instance()
23149
- vif = _fake_network_info(self, 1)[0]
23150
- guest = mock.MagicMock()
23151
- guest.get_power_state.return_value = power_state.RUNNING
23152
- guest.get_interface_by_cfg.return_value = (
23153
- vconfig.LibvirtConfigGuestInterface())
23154
- get_guest_mock = mock.Mock()
23155
- # Host.get_guest should be called twice: the first time it is found,
23156
- # the second time it is gone.
23157
- get_guest_mock.side_effect = (
23158
- guest, exception.InstanceNotFound(instance_id=instance.uuid))
23159
- self.drvr._host.get_guest = get_guest_mock
23160
- error = fakelibvirt.libvirtError(
23161
- 'internal error: End of file from qemu monitor')
23162
- error.err = (fakelibvirt.VIR_ERR_OPERATION_FAILED,)
23163
- mock_detach_with_retry.side_effect = error
23164
- self.drvr.detach_interface(self.context, instance, vif)
23165
- self.assertEqual(1, mock_log.info.call_count)
23166
- self.assertIn('Instance disappeared while detaching interface',
23167
- mock_log.info.call_args[0][0])
23168
- get_guest_mock.assert_has_calls([mock.call(instance)] * 2)
23169
-
23170
23136
@mock.patch('threading.Event.wait', new=mock.Mock())
23171
23137
@mock.patch.object(FakeVirtDomain, 'info')
23172
23138
@mock.patch.object(FakeVirtDomain, 'detachDeviceFlags')
@@ -23210,7 +23176,6 @@ def test_detach_interface_device_with_same_mac_address(
23210
23176
mock.patch.object(
23211
23177
libvirt_guest.Guest, 'get_interface_by_cfg',
23212
23178
side_effect=[
23213
- expected, # detach_interface gets the config
23214
23179
expected, # _detach_with_retry: persistent config
23215
23180
expected, # _detach_with_retry: live config
23216
23181
None, # _detach_with_retry: persistent gone
@@ -23224,14 +23189,12 @@ def test_detach_interface_device_with_same_mac_address(
23224
23189
23225
23190
mock_get_interface.assert_has_calls(
23226
23191
[
23227
- mock.call(expected, ),
23228
23192
mock.call(expected, from_persistent_config=True),
23229
23193
mock.call(expected),
23230
23194
mock.call(expected, from_persistent_config=True),
23231
23195
mock.call(expected),
23232
23196
]
23233
23197
)
23234
- self.assertEqual(5, mock_get_interface.call_count)
23235
23198
mock_get_config.assert_called_once_with(
23236
23199
instance, network_info[0], test.MatchType(objects.ImageMeta),
23237
23200
test.MatchType(objects.Flavor), CONF.libvirt.virt_type)
@@ -23253,7 +23216,6 @@ def test_detach_interface_guest_set_metadata(self):
23253
23216
instance = self._create_instance()
23254
23217
network_info = _fake_network_info(self, num_networks=3)
23255
23218
vif = network_info[0]
23256
- interface = vconfig.LibvirtConfigGuestInterface()
23257
23219
image_meta = objects.ImageMeta.from_dict({})
23258
23220
disk_info = blockinfo.get_disk_info(
23259
23221
CONF.libvirt.virt_type, instance, image_meta)
@@ -23266,8 +23228,6 @@ def test_detach_interface_guest_set_metadata(self):
23266
23228
self.drvr._host, 'get_guest', return_value=guest),
23267
23229
mock.patch.object(
23268
23230
self.drvr.vif_driver, 'get_config', return_value=cfg),
23269
- mock.patch.object(
23270
- guest, 'get_interface_by_cfg', return_value=interface),
23271
23231
mock.patch.object(
23272
23232
instance, 'get_network_info', return_value=network_info),
23273
23233
mock.patch.object(
@@ -23276,16 +23236,15 @@ def test_detach_interface_guest_set_metadata(self):
23276
23236
self.drvr, '_get_guest_config_meta', return_value=config_meta),
23277
23237
mock.patch.object(guest, 'set_metadata')
23278
23238
) as (
23279
- mock_get_guest, mock_get_config, mock_get_interface_by_cfg ,
23280
- mock_get_network_info, mock_detach_with_retry ,
23281
- mock_get_guest_config_meta, mock_set_metadata
23239
+ mock_get_guest, mock_get_config, mock_get_network_info ,
23240
+ mock_detach_with_retry, mock_get_guest_config_meta ,
23241
+ mock_set_metadata
23282
23242
):
23283
23243
self.drvr.detach_interface(self.context, instance, vif)
23284
23244
mock_get_guest.assert_called_once_with(instance)
23285
23245
mock_get_config.assert_called_once_with(
23286
23246
instance, vif, test.MatchType(objects.ImageMeta),
23287
23247
test.MatchType(objects.Flavor), CONF.libvirt.virt_type)
23288
- mock_get_interface_by_cfg.assert_called_once_with(cfg)
23289
23248
mock_detach_with_retry.assert_called_once_with(
23290
23249
guest, instance.uuid, mock.ANY, device_name=None)
23291
23250
mock_get_network_info.assert_called_once_with()
@@ -23847,6 +23806,56 @@ def test__detach_with_retry_libvirt_reports_not_found_give_up(self):
23847
23806
mock_guest.detach_device.assert_called_once_with(
23848
23807
mock_dev, persistent=True, live=False)
23849
23808
23809
+ @mock.patch.object(libvirt_driver.LOG, 'warning')
23810
+ def test__detach_with_retry_libvirt_reports_domain_not_found(
23811
+ self, mock_warning
23812
+ ):
23813
+ """Test that libvirt reports that the domain is not found and assert
23814
+ that it is only logged.
23815
+ """
23816
+ drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
23817
+ mock_guest = mock.Mock(spec=libvirt_guest.Guest)
23818
+ mock_guest.get_power_state.return_value = power_state.SHUTDOWN
23819
+
23820
+ mock_dev = mock.Mock(spec=vconfig.LibvirtConfigGuestDisk)
23821
+ mock_dev.alias = 'virtio-disk1'
23822
+
23823
+ mock_get_device_conf_func = mock.Mock(
23824
+ # The first call is to get the device from the persistent domain
23825
+ # before the detach. The second calls to double check that the
23826
+ # device is gone after libvirt returned. This second call is
23827
+ # pointless in the current case as libvirt returned that the domain
23828
+ # does not exists. So the code could know that there is no device.
23829
+ # Still for simplicity the call is made and expected to return None
23830
+ side_effect=[
23831
+ mock_dev,
23832
+ None,
23833
+ ]
23834
+ )
23835
+
23836
+ mock_guest.detach_device.side_effect = fakelibvirt.make_libvirtError(
23837
+ fakelibvirt.libvirtError,
23838
+ msg='error',
23839
+ error_code=fakelibvirt.VIR_ERR_NO_DOMAIN)
23840
+
23841
+ drvr._detach_with_retry(
23842
+ mock_guest,
23843
+ uuids.instance_uuid,
23844
+ mock_get_device_conf_func,
23845
+ device_name='vdb',
23846
+ )
23847
+
23848
+ mock_guest.has_persistent_configuration.assert_called_once_with()
23849
+ mock_get_device_conf_func.assert_has_calls([
23850
+ mock.call(from_persistent_config=True),
23851
+ mock.call(from_persistent_config=True),
23852
+ ])
23853
+ mock_guest.detach_device.assert_called_once_with(
23854
+ mock_dev, persistent=True, live=False)
23855
+ mock_warning.assert_called_once_with(
23856
+ 'During device detach, instance disappeared.',
23857
+ instance_uuid=uuids.instance_uuid)
23858
+
23850
23859
@ddt.data(power_state.RUNNING, power_state.PAUSED)
23851
23860
def test__detach_with_retry_other_sync_libvirt_error(self, state):
23852
23861
"""Test that libvirt reports non device related error during detach
@@ -23865,7 +23874,7 @@ def test__detach_with_retry_other_sync_libvirt_error(self, state):
23865
23874
mock_guest.detach_device.side_effect = fakelibvirt.make_libvirtError(
23866
23875
fakelibvirt.libvirtError,
23867
23876
msg='error',
23868
- error_code=fakelibvirt.VIR_ERR_NO_DOMAIN )
23877
+ error_code=fakelibvirt.VIR_ERR_INTERNAL_ERROR )
23869
23878
23870
23879
self.assertRaises(
23871
23880
fakelibvirt.libvirtError,
0 commit comments