L3 Agent can handle many external networks

With this patch a l3 agent can handle
any networks by setting the neutron
parameter external_network_bridge
and gateway_external_network_id to
empty.

Related-Bug: #1234750
Related-Bug: #1194350

Change-Id: Id260a239df23951da730513f40cda490002effc3
This commit is contained in:
Sylvain Afchain 2013-11-30 00:49:02 +01:00
parent bf8bf46cbb
commit b5092af696
3 changed files with 87 additions and 6 deletions

View File

@ -27,10 +27,11 @@
# This is done by setting the specific 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
# When external_network_bridge is set, each L3 agent can be associated
# with no more than one external network. This value should be set to the UUID
# of that external network. To allow L3 agent support multiple external
# networks, both the external_network_bridge and gateway_external_network_id
# must be left empty.
# gateway_external_network_id =
# Indicates that this L3 agent should also handle routers that do not have
@ -40,7 +41,8 @@
# handle_internal_only_routers = True
# Name of bridge used for external network traffic. This should be set to
# empty value for the linux bridge
# empty value for the linux bridge. when this parameter is set, each L3 agent
# can be associated with no more than one external network.
# external_network_bridge = br-ex
# TCP Port used by Neutron metadata server

View File

@ -291,6 +291,13 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
"""Find UUID of single external network for this agent."""
if self.conf.gateway_external_network_id:
return self.conf.gateway_external_network_id
# L3 agent doesn't use external_network_bridge to handle external
# networks, so bridge_mappings with provider networks will be used
# and the L3 agent is able to handle any external networks.
if not self.conf.external_network_bridge:
return
try:
return self.plugin_rpc.get_external_network_id(self.context)
except rpc_common.RemoteError as e:
@ -686,7 +693,8 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
ex_net_id = (r['external_gateway_info'] or {}).get('network_id')
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:
if (target_ex_net_id and ex_net_id and
ex_net_id != target_ex_net_id):
continue
cur_router_ids.add(r['id'])
if r['id'] not in self.router_info:

View File

@ -26,6 +26,7 @@ from neutron.agent import l3_agent
from neutron.agent.linux import interface
from neutron.common import config as base_config
from neutron.common import constants as l3_constants
from neutron.common import exceptions as n_exc
from neutron.openstack.common import uuidutils
from neutron.tests import base
@ -842,6 +843,76 @@ class TestBasicRouterOperations(base.BaseTestCase):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
self.assertEqual(['1234'], agent._router_ids())
def test_process_routers_with_no_ext_net_in_conf(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
self.plugin_api.get_external_network_id.return_value = 'aaa'
routers = [
{'id': _uuid(),
'routes': [],
'admin_state_up': True,
'external_gateway_info': {'network_id': 'aaa'}}]
agent._process_routers(routers)
self.assertIn(routers[0]['id'], agent.router_info)
def test_process_routers_with_no_ext_net_in_conf_and_two_net_plugin(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
routers = [
{'id': _uuid(),
'routes': [],
'admin_state_up': True,
'external_gateway_info': {'network_id': 'aaa'}}]
agent.router_info = {}
self.plugin_api.get_external_network_id.side_effect = (
n_exc.TooManyExternalNetworks())
self.assertRaises(n_exc.TooManyExternalNetworks,
agent._process_routers,
routers)
self.assertNotIn(routers[0]['id'], agent.router_info)
def test_process_routers_with_ext_net_in_conf(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
self.plugin_api.get_external_network_id.return_value = 'aaa'
routers = [
{'id': _uuid(),
'routes': [],
'admin_state_up': True,
'external_gateway_info': {'network_id': 'aaa'}},
{'id': _uuid(),
'routes': [],
'admin_state_up': True,
'external_gateway_info': {'network_id': 'bbb'}}]
agent.router_info = {}
self.conf.set_override('gateway_external_network_id', 'aaa')
agent._process_routers(routers)
self.assertIn(routers[0]['id'], agent.router_info)
self.assertNotIn(routers[1]['id'], agent.router_info)
def test_process_routers_with_no_bridge_no_ext_net_in_conf(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
self.plugin_api.get_external_network_id.return_value = 'aaa'
routers = [
{'id': _uuid(),
'routes': [],
'admin_state_up': True,
'external_gateway_info': {'network_id': 'aaa'}},
{'id': _uuid(),
'routes': [],
'admin_state_up': True,
'external_gateway_info': {'network_id': 'bbb'}}]
agent.router_info = {}
self.conf.set_override('external_network_bridge', '')
agent._process_routers(routers)
self.assertIn(routers[0]['id'], agent.router_info)
self.assertIn(routers[1]['id'], agent.router_info)
def test_nonexistent_interface_driver(self):
self.conf.set_override('interface_driver', None)
with mock.patch.object(l3_agent, 'LOG') as log: