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
This commit is contained in:
Gary Kotton 2012-08-27 07:30:22 -04:00
parent d03b79feaf
commit 3c8b8ce101
3 changed files with 43 additions and 14 deletions

View File

@ -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 =

View File

@ -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)

View File

@ -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(),