Skip to content

Commit 7e8a978

Browse files
author
Balazs Gibizer
committed
Only unplug vif after the device is detached from libvirt
There is a potential race between unplugging a vif and removing the related device from the domain XML. During macvtap (hw_veb) unplug nova tries to reset the MAC and VLAN config of the VF used for the macvtap. However as it is done before the macvtap device is removed from the domain, libvirt still feels responsible to the VF too and restores the configuration. This leads to a situation where the macvtap is removed successfully but the VF behind it left configured with the MAC address and VLAN id of the neutron port. This patch changes the order of the operations. First the device is detached from libvirt and then the vif is unplugged. Part of blueprint sriov-interface-attach-detach Change-Id: Iea126857725502dc2eef6e53894d8755d0e2e7f4
1 parent c21f08f commit 7e8a978

File tree

2 files changed

+13
-3
lines changed

2 files changed

+13
-3
lines changed

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23480,11 +23480,12 @@ def _test_detach_interface(self, power_state, expected_flags,
2348023480
mock.patch.object(guest, 'get_interface_by_cfg',
2348123481
side_effect=get_interface_calls),
2348223482
mock.patch.object(domain, 'detachDeviceFlags'),
23483-
mock.patch('nova.virt.libvirt.driver.LOG.warning')
23483+
mock.patch('nova.virt.libvirt.driver.LOG.warning'),
23484+
mock.patch.object(self.drvr.vif_driver, 'unplug')
2348423485
) as (
2348523486
mock_get_guest, mock_get_config,
2348623487
mock_get_interface, mock_detach_device_flags,
23487-
mock_warning
23488+
mock_warning, mock_unplug
2348823489
):
2348923490
# run the detach method
2349023491
self.drvr.detach_interface(self.context, instance, network_info[0])
@@ -23506,6 +23507,8 @@ def _test_detach_interface(self, power_state, expected_flags,
2350623507
expected_cfg.to_xml(), flags=expected_flags)
2350723508
mock_warning.assert_not_called()
2350823509

23510+
mock_unplug.assert_called_once_with(instance, network_info[0])
23511+
2350923512
def test_detach_interface_with_running_instance(self):
2351023513
self._test_detach_interface(
2351123514
power_state.RUNNING,

nova/virt/libvirt/driver.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2240,7 +2240,6 @@ def detach_interface(self, context, instance, vif):
22402240
CONF.libvirt.virt_type, self._host)
22412241
interface = guest.get_interface_by_cfg(cfg)
22422242
try:
2243-
self.vif_driver.unplug(instance, vif)
22442243
# NOTE(mriedem): When deleting an instance and using Neutron,
22452244
# we can be racing against Neutron deleting the port and
22462245
# sending the vif-deleted event which then triggers a call to
@@ -2320,6 +2319,14 @@ def detach_interface(self, context, instance, vif):
23202319
LOG.warning('Detaching interface %(mac)s failed because '
23212320
'the device is no longer found on the guest.',
23222321
{'mac': mac}, instance=instance)
2322+
finally:
2323+
# NOTE(gibi): we need to unplug the vif _after_ the detach is done
2324+
# on the libvirt side as otherwise libvirt will still manage the
2325+
# device that our unplug code trying to reset. This can cause a
2326+
# race and leave the detached device configured. Also even if we
2327+
# are failed to detach due to race conditions the unplug is
2328+
# necessary for the same reason
2329+
self.vif_driver.unplug(instance, vif)
23232330

23242331
def _create_snapshot_metadata(self, image_meta, instance,
23252332
img_fmt, snp_name):

0 commit comments

Comments
 (0)