diff --git a/quantum/agent/l3_agent.py b/quantum/agent/l3_agent.py index 886b39b7af..129efcb942 100644 --- a/quantum/agent/l3_agent.py +++ b/quantum/agent/l3_agent.py @@ -165,16 +165,23 @@ class L3NATAgent(manager.Manager): self.fullsync = True self.sync_sem = semaphore.Semaphore(1) if self.conf.use_namespaces: - self._destroy_all_router_namespaces() + self._destroy_router_namespaces(self.conf.router_id) super(L3NATAgent, self).__init__(host=self.conf.host) - def _destroy_all_router_namespaces(self): - """Destroy all router namespaces on the host to eliminate - all stale linux devices, iptables rules, and namespaces. + def _destroy_router_namespaces(self, only_router_id=None): + """Destroy router namespaces on the host to eliminate all stale + linux devices, iptables rules, and namespaces. + + If only_router_id is passed, only destroy single namespace, to allow + for multiple l3 agents on the same host, without stepping on each + other's toes on init. This only makes sense if router_id is set. """ root_ip = ip_lib.IPWrapper(self.root_helper) for ns in root_ip.get_namespaces(self.root_helper): if ns.startswith(NS_PREFIX): + if only_router_id and not ns.endswith(only_router_id): + continue + try: self._destroy_router_namespace(ns) except: diff --git a/quantum/tests/unit/test_l3_agent.py b/quantum/tests/unit/test_l3_agent.py index d5dcf368c9..dcf3f46633 100644 --- a/quantum/tests/unit/test_l3_agent.py +++ b/quantum/tests/unit/test_l3_agent.py @@ -290,9 +290,35 @@ class TestBasicRouterOperations(unittest2.TestCase): def __init__(self, name): self.name = name - self.mock_ip.get_namespaces.return_value = ['qrouter-foo'] + self.mock_ip.get_namespaces.return_value = ['qrouter-foo', + 'qrouter-bar'] self.mock_ip.get_devices.return_value = [FakeDev('qr-aaaa'), FakeDev('qgw-aaaa')] agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) - agent._destroy_all_router_namespaces() + + agent._destroy_router_namespace = mock.MagicMock() + agent._destroy_router_namespaces() + + self.assertEqual(agent._destroy_router_namespace.call_count, 2) + + def testDestroyNamespaceWithRouterId(self): + + class FakeDev(object): + def __init__(self, name): + self.name = name + + self.conf.router_id = _uuid() + + namespaces = ['qrouter-foo', 'qrouter-' + self.conf.router_id] + + self.mock_ip.get_namespaces.return_value = namespaces + self.mock_ip.get_devices.return_value = [FakeDev('qr-aaaa'), + FakeDev('qgw-aaaa')] + + agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) + + agent._destroy_router_namespace = mock.MagicMock() + agent._destroy_router_namespaces(self.conf.router_id) + + self.assertEqual(agent._destroy_router_namespace.call_count, 1)