# 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
# 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
"""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:
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:
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
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: