From b27ea5fe2da47d134ac9b4a50341a0ecc0934eb3 Mon Sep 17 00:00:00 2001 From: Slawek Kaplonski Date: Wed, 7 Sep 2022 12:07:38 +0200 Subject: [PATCH] Reset device namespace when adding to the namespace fails In case when during adding device to the namespace, device will be "shy" and will disappear for a moment and NetworkInterfaceNotFound exception will be raised, we need to reset device.namespace to be None. Otherwise, in the next attempt of adding interface to namespace, when it will be added back to ovs (and will be in global scope), Neutron will already look for it in the "namespace" and that will always be failing. Closes-bug: #1961740 Change-Id: Ie9331c72c44084b0a382598c3359214cce2f2ebd (cherry picked from commit 76578393ab401a33084921c4355af8e82c5d02ee) --- neutron/agent/linux/interface.py | 5 +++++ neutron/tests/unit/agent/linux/test_interface.py | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/neutron/agent/linux/interface.py b/neutron/agent/linux/interface.py index 36222db49e0..ec13236c7ca 100644 --- a/neutron/agent/linux/interface.py +++ b/neutron/agent/linux/interface.py @@ -377,6 +377,11 @@ class OVSInterfaceDriver(LinuxInterfaceDriver): LOG.warning("Failed to set interface %s into namespace %s. " "Interface not found, attempt: %s, retrying.", device, namespace, i + 1) + # NOTE(slaweq) In such case it's required to reset device's + # namespace as it was already set to the "namespace" + # and after retry neutron will look for it in that namespace + # which is wrong + device.namespace = None time.sleep(1) except utils.WaitTimeout: # NOTE(slaweq): if the exception was WaitTimeout then it means diff --git a/neutron/tests/unit/agent/linux/test_interface.py b/neutron/tests/unit/agent/linux/test_interface.py index 9e13000f50f..ab8488b2b06 100644 --- a/neutron/tests/unit/agent/linux/test_interface.py +++ b/neutron/tests/unit/agent/linux/test_interface.py @@ -529,6 +529,20 @@ class TestOVSInterfaceDriver(TestBase): ovs_br.assert_has_calls([mock.call('br-int'), mock.call().delete_port('tap0')]) + def test__add_device_to_namespace_retries(self): + ovs = interface.OVSInterfaceDriver(self.conf) + namespace_obj = self.ip.return_value.ensure_namespace.return_value + self.ip.ensure_namespace.return_value = namespace_obj + namespace_obj.add_device_to_namespace.side_effect = ( + ip_lib.NetworkInterfaceNotFound) + device = mock.MagicMock() + self.assertRaises( + ip_lib.NetworkInterfaceNotFound, + ovs._add_device_to_namespace, + self.ip, device, "test-ns") + self.assertEqual(10, namespace_obj.add_device_to_namespace.call_count) + self.assertIsNone(device.namespace) + class TestOVSInterfaceDriverWithVeth(TestOVSInterfaceDriver):