]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
L3 Agent can handle many external networks
authorSylvain Afchain <sylvain.afchain@enovance.com>
Fri, 29 Nov 2013 23:49:02 +0000 (00:49 +0100)
committerSylvain Afchain <sylvain.afchain@enovance.com>
Thu, 9 Jan 2014 13:47:24 +0000 (14:47 +0100)
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

etc/l3_agent.ini
neutron/agent/l3_agent.py
neutron/tests/unit/test_l3_agent.py

index 777e10ad7fcc69d53518ee98cf33342f42a28cc8..c9913aaa628de5690cc9cfef5668563bf60ee0d6 100644 (file)
 # 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
index 8853fb2c68510a67baa1840f533e7c212461d737..87fa481439e78ae7c12d81c888d54c881e7c2029 100644 (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:
index fa48e71f041c3cb317b816d43f6abe1aca080207..17bd83da1b15a253183fed8a99677ac7547c4058 100644 (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: