only destroy single namespace if router_id is set

Fixes bug 1122206

If multiple instances of l3_agent are running on the same host, all qrouter-
namespaces will be destroyed as new l3_agents are started.  This fix allows
for multiple l3_agents to be running on the same host when router_id is set
for each agent.

Change-Id: I879cdc6faba94900f831232232d67e471c70d778
This commit is contained in:
Christoph Thiel 2013-02-11 17:46:59 +01:00
parent 33b6f8a2be
commit 2df5424361
2 changed files with 39 additions and 6 deletions

View File

@ -165,16 +165,23 @@ class L3NATAgent(manager.Manager):
self.fullsync = True self.fullsync = True
self.sync_sem = semaphore.Semaphore(1) self.sync_sem = semaphore.Semaphore(1)
if self.conf.use_namespaces: 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) super(L3NATAgent, self).__init__(host=self.conf.host)
def _destroy_all_router_namespaces(self): def _destroy_router_namespaces(self, only_router_id=None):
"""Destroy all router namespaces on the host to eliminate """Destroy router namespaces on the host to eliminate all stale
all stale linux devices, iptables rules, and namespaces. 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) root_ip = ip_lib.IPWrapper(self.root_helper)
for ns in root_ip.get_namespaces(self.root_helper): for ns in root_ip.get_namespaces(self.root_helper):
if ns.startswith(NS_PREFIX): if ns.startswith(NS_PREFIX):
if only_router_id and not ns.endswith(only_router_id):
continue
try: try:
self._destroy_router_namespace(ns) self._destroy_router_namespace(ns)
except: except:

View File

@ -290,9 +290,35 @@ class TestBasicRouterOperations(unittest2.TestCase):
def __init__(self, name): def __init__(self, name):
self.name = 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'), self.mock_ip.get_devices.return_value = [FakeDev('qr-aaaa'),
FakeDev('qgw-aaaa')] FakeDev('qgw-aaaa')]
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) 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)