From 3c8b8ce1013c739f8ed34053dc36ab0705f05884 Mon Sep 17 00:00:00 2001 From: Gary Kotton Date: Mon, 27 Aug 2012 07:30:22 -0400 Subject: [PATCH] L3: make use of namespaces by agent configurable Fixes bug 1042104 The fix follows the patch that was done on the DHCP agent to enable the user to configure the usage of namespaces. In the event that namspaces are disabled the agent is limited to running only one router. The agent needs to define the router_id that is supported. The process in this case is: 1. create router 2. start agent with router id Change-Id: I2a71dc009c5aea285ff9f903b3faa99b0c9f820f --- etc/l3_agent.ini | 8 +++++++ quantum/agent/l3_agent.py | 34 +++++++++++++++++++++-------- quantum/tests/unit/test_l3_agent.py | 15 ++++++++----- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/etc/l3_agent.ini b/etc/l3_agent.ini index 121c4b47c..46cafa395 100644 --- a/etc/l3_agent.ini +++ b/etc/l3_agent.ini @@ -21,3 +21,11 @@ admin_password = %SERVICE_PASSWORD% # root filter facility. # Change to "sudo" to skip the filtering and just run the comand directly root_helper = sudo + +# Allow overlapping IP (Must have kernel build with CONFIG_NET_NS=y and +# iproute2 package that supports namespaces). +# use_namespaces = True + +# If use_namespaces is set as False then the agent can only configure one router. +# This is done by setting the specific router_id. +# router_id = diff --git a/quantum/agent/l3_agent.py b/quantum/agent/l3_agent.py index a93bf699c..fb634d051 100644 --- a/quantum/agent/l3_agent.py +++ b/quantum/agent/l3_agent.py @@ -43,12 +43,13 @@ EXTERNAL_DEV_PREFIX = 'qgw-' class RouterInfo(object): - def __init__(self, router_id, root_helper): + def __init__(self, router_id, root_helper, use_namespaces): self.router_id = router_id self.ex_gw_port = None self.internal_ports = [] self.floating_ips = [] self.root_helper = root_helper + self.use_namespaces = use_namespaces self.iptables_manager = iptables_manager.IptablesManager( root_helper=root_helper, @@ -56,7 +57,8 @@ class RouterInfo(object): namespace=self.ns_name()) def ns_name(self): - return NS_PREFIX + self.router_id + if self.use_namespaces: + return NS_PREFIX + self.router_id class L3NATAgent(object): @@ -84,7 +86,12 @@ class L3NATAgent(object): #FIXME(danwent): not currently used cfg.BoolOpt('send_arp_for_ha', default=True, - help="Send gratuitious ARP when router IP is configured") + help="Send gratuitious ARP when router IP is configured"), + cfg.BoolOpt('use_namespaces', default=True, + help="Allow overlapping IP."), + cfg.StrOpt('router_id', default='', + help="If namespaces is disabled, the l3 agent can only" + " confgure a router that has the matching router ID.") ] def __init__(self, conf): @@ -141,7 +148,8 @@ class L3NATAgent(object): elif d.name.startswith(EXTERNAL_DEV_PREFIX): self.driver.unplug(d.name, bridge=self.conf.external_network_bridge) - ns_ip.netns.delete(namespace) + if self.conf.use_namespaces: + ns_ip.netns.delete(namespace) def _create_router_namespace(self, ri): ip_wrapper_root = ip_lib.IPWrapper(self.conf.root_helper) @@ -172,11 +180,18 @@ class L3NATAgent(object): for r in self.qclient.list_routers()['routers']: #FIXME(danwent): handle admin state - cur_router_ids.add(r['id']) + # If namespaces are disabled, only process the router associated + # with the configured agent id. + if (self.conf.use_namespaces or + r['id'] == self.conf.router_id): + cur_router_ids.add(r['id']) + else: + continue if r['id'] not in self.router_info: - self.router_info[r['id']] = RouterInfo(r['id'], - self.conf.root_helper) - self._create_router_namespace(self.router_info[r['id']]) + self.router_info[r['id']] = RouterInfo( + r['id'], self.conf.root_helper, self.conf.use_namespaces) + if self.conf.use_namespaces: + self._create_router_namespace(self.router_info[r['id']]) ri = self.router_info[r['id']] self.process_router(ri) @@ -320,7 +335,8 @@ class L3NATAgent(object): cmd = ['route', 'add', 'default', 'gw', gw_ip] ip_wrapper = ip_lib.IPWrapper(self.conf.root_helper, namespace=ri.ns_name()) - ip_wrapper.netns.execute(cmd) + if self.conf.use_namespaces: + ip_wrapper.netns.execute(cmd) for (c, r) in self.external_gateway_filter_rules(): ri.iptables_manager.ipv4['filter'].add_rule(c, r) diff --git a/quantum/tests/unit/test_l3_agent.py b/quantum/tests/unit/test_l3_agent.py index 8b3fd4c9a..587f611fe 100644 --- a/quantum/tests/unit/test_l3_agent.py +++ b/quantum/tests/unit/test_l3_agent.py @@ -73,7 +73,8 @@ class TestBasicRouterOperations(unittest.TestCase): def testRouterInfoCreate(self): id = _uuid() - ri = l3_agent.RouterInfo(id, self.conf.root_helper) + ri = l3_agent.RouterInfo(id, self.conf.root_helper, + self.conf.use_namespaces) self.assertTrue(ri.ns_name().endswith(id)) @@ -87,7 +88,8 @@ class TestBasicRouterOperations(unittest.TestCase): port_id = _uuid() router_id = _uuid() network_id = _uuid() - ri = l3_agent.RouterInfo(router_id, self.conf.root_helper) + ri = l3_agent.RouterInfo(router_id, self.conf.root_helper, + self.conf.use_namespaces) agent = l3_agent.L3NATAgent(self.conf) interface_name = agent.get_internal_device_name(port_id) cidr = '99.0.1.9/24' @@ -115,7 +117,8 @@ class TestBasicRouterOperations(unittest.TestCase): def _test_external_gateway_action(self, action): router_id = _uuid() - ri = l3_agent.RouterInfo(router_id, self.conf.root_helper) + ri = l3_agent.RouterInfo(router_id, self.conf.root_helper, + self.conf.use_namespaces) agent = l3_agent.L3NATAgent(self.conf) internal_cidrs = ['100.0.1.0/24', '200.74.0.0/16'] ex_gw_port = {'fixed_ips': [{'ip_address': '20.0.0.30', @@ -148,7 +151,8 @@ class TestBasicRouterOperations(unittest.TestCase): def _test_floating_ip_action(self, action): router_id = _uuid() - ri = l3_agent.RouterInfo(router_id, self.conf.root_helper) + ri = l3_agent.RouterInfo(router_id, self.conf.root_helper, + self.conf.use_namespaces) agent = l3_agent.L3NATAgent(self.conf) floating_ip = '20.0.0.100' fixed_ip = '10.0.0.23' @@ -179,7 +183,8 @@ class TestBasicRouterOperations(unittest.TestCase): agent = l3_agent.L3NATAgent(self.conf) router_id = _uuid() - ri = l3_agent.RouterInfo(router_id, self.conf.root_helper) + ri = l3_agent.RouterInfo(router_id, self.conf.root_helper, + self.conf.use_namespaces) # return data so that state is built up ex_gw_port = {'id': _uuid(),