allow multiple l3-agents to run, each with one external gateway net

bug #1042028

Allows user to invoke L3-agent in a way that limits the agent to
implementing only routers associated with a particular external network.
Thus, it is possible to have a deployment with multiple external networks,
since you can run one agent per external network.

Also makes l3-agent pay attention to router admin_state_up field.

Change-Id: Ia79d29301530718bc381c8e5a9d197de9452bce2
This commit is contained in:
Dan Wendlandt 2012-09-09 07:55:52 -07:00
parent 4d5db36558
commit 76df5b1dc1
3 changed files with 49 additions and 3 deletions

View File

@ -29,3 +29,15 @@ root_helper = sudo
# If use_namespaces is set as False then the agent can only configure one router. # If use_namespaces is set as False then the agent can only configure one router.
# This is done by setting the specific router_id. # This is done by setting the specific router_id.
# router_id = # router_id =
# Each L3 agent can be associated with at most one external network. This
# value should be set to the UUID of that external network. If empty,
# the agent will enforce that only a single external networks exists and
# use that external network id
# gateway_external_net_id =
# Indicates that this L3 agent should also handle routers that do not have
# an external network gateway configured. This option should be True only
# for a single agent in a Quantum deployment, and may be False for all agents
# if all routers must have an external network gateway
# handle_internal_only_routers = True

View File

@ -90,7 +90,13 @@ class L3NATAgent(object):
help="Allow overlapping IP."), help="Allow overlapping IP."),
cfg.StrOpt('router_id', default='', cfg.StrOpt('router_id', default='',
help="If namespaces is disabled, the l3 agent can only" help="If namespaces is disabled, the l3 agent can only"
" confgure a router that has the matching router ID.") " confgure a router that has the matching router ID."),
cfg.BoolOpt('handle_internal_only_routers',
default=True,
help="Agent should implement routers with no gateway"),
cfg.StrOpt('gateway_external_network_id', default='',
help="UUID of external network for routers implemented "
"by the agents."),
] ]
def __init__(self, conf): def __init__(self, conf):
@ -171,13 +177,37 @@ class L3NATAgent(object):
time.sleep(self.polling_interval) time.sleep(self.polling_interval)
def _fetch_external_net_id(self):
"""Find UUID of single external network for this agent"""
if self.conf.gateway_external_network_id:
return self.conf.gateway_external_network_id
params = {'router:external': True}
ex_nets = self.qclient.list_networks(**params)['networks']
if len(ex_nets) > 1:
raise Exception("must configure 'external_network_id' if "
"Quantum has more than one external network.")
if len(ex_nets) == 0:
return None
return ex_nets[0]['id']
def do_single_loop(self): def do_single_loop(self):
prev_router_ids = set(self.router_info) prev_router_ids = set(self.router_info)
cur_router_ids = set() cur_router_ids = set()
target_ex_net_id = self._fetch_external_net_id()
# identify and update new or modified routers # identify and update new or modified routers
for r in self.qclient.list_routers()['routers']: for r in self.qclient.list_routers()['routers']:
#FIXME(danwent): handle admin state if not r['admin_state_up']:
continue
ex_net_id = r['external_gateway_info'].get('network_id', None)
if not ex_net_id and not self.conf.handle_internal_only_routers:
continue
if ex_net_id and ex_net_id != target_ex_net_id:
continue
# If namespaces are disabled, only process the router associated # If namespaces are disabled, only process the router associated
# with the configured agent id. # with the configured agent id.

View File

@ -237,8 +237,12 @@ class TestBasicRouterOperations(unittest.TestCase):
self.client_inst.list_ports.return_value = {'ports': []} self.client_inst.list_ports.return_value = {'ports': []}
self.client_inst.list_networks.return_value = {'networks': []}
self.client_inst.list_routers.return_value = {'routers': [ self.client_inst.list_routers.return_value = {'routers': [
{'id': _uuid()}]} {'id': _uuid(),
'admin_state_up': True,
'external_gateway_info': {}}]}
agent.do_single_loop() agent.do_single_loop()
self.client_inst.list_routers.return_value = {'routers': []} self.client_inst.list_routers.return_value = {'routers': []}