]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
L3 agent fetches the external network id once
authorCarl Baldwin <carl.baldwin@hp.com>
Wed, 15 Jan 2014 18:46:17 +0000 (18:46 +0000)
committerCarl Baldwin <carl.baldwin@hp.com>
Fri, 14 Feb 2014 00:27:17 +0000 (00:27 +0000)
Rather than fetching the id of the external network each time that
_process_routers is called, get it once and remember it.  If the agent
is ever requested to connect to a different ext-net then it will fetch
the current ext-net to double check for the unlikely event that the
ext-net has changed.  If it has then it will remember the new ext-net.

This is only applicable in the case where there is only one ext-net
that has not been configured explicitly in the config file.  That was
the only case that would cause an RPC message in the first place.

Change-Id: I40bbbf6233131ea5d40122ef9495fd3cb7dc823a
Closes-Bug: #1269567

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

index 01132cc79467f0e72105bc9361cb73c27aabd525..575d7129aa96cc8a6dc7beae94032322cc9d9379 100644 (file)
@@ -225,6 +225,8 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
         self.rpc_loop.start(interval=RPC_LOOP_INTERVAL)
         super(L3NATAgent, self).__init__(conf=self.conf)
 
+        self.target_ex_net_id = None
+
     def _check_config_params(self):
         """Check items in configuration files.
 
@@ -289,7 +291,7 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
             ip_wrapper = ip_wrapper_root.ensure_namespace(ri.ns_name())
             ip_wrapper.netns.execute(['sysctl', '-w', 'net.ipv4.ip_forward=1'])
 
-    def _fetch_external_net_id(self):
+    def _fetch_external_net_id(self, force=False):
         """Find UUID of single external network for this agent."""
         if self.conf.gateway_external_network_id:
             return self.conf.gateway_external_network_id
@@ -300,8 +302,13 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
         if not self.conf.external_network_bridge:
             return
 
+        if not force and self.target_ex_net_id:
+            return self.target_ex_net_id
+
         try:
-            return self.plugin_rpc.get_external_network_id(self.context)
+            self.target_ex_net_id = self.plugin_rpc.get_external_network_id(
+                self.context)
+            return self.target_ex_net_id
         except rpc_common.RemoteError as e:
             with excutils.save_and_reraise_exception():
                 if e.exc_type == 'TooManyExternalNetworks':
@@ -706,7 +713,10 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
                 continue
             if (target_ex_net_id and ex_net_id and
                 ex_net_id != target_ex_net_id):
-                continue
+                # Double check that our single external_net_id has not changed
+                # by forcing a check by RPC.
+                if (ex_net_id != self._fetch_external_net_id(force=True)):
+                    continue
             cur_router_ids.add(r['id'])
             if r['id'] not in self.router_info:
                 self._router_added(r['id'], r)
index 6b81ac8e7c9e9b5629ddd69e1e068bad969f39ab..decf39b9fa9d6eec2b7aa03ccfb68cecf1fa7474 100644 (file)
@@ -903,6 +903,39 @@ class TestBasicRouterOperations(base.BaseTestCase):
 
         agent._process_routers(routers)
         self.assertIn(routers[0]['id'], agent.router_info)
+        self.plugin_api.get_external_network_id.assert_called_with(
+            agent.context)
+
+    def test_process_routers_with_cached_ext_net(self):
+        agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
+        self.plugin_api.get_external_network_id.return_value = 'aaa'
+        agent.target_ex_net_id = '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)
+        self.assertFalse(self.plugin_api.get_external_network_id.called)
+
+    def test_process_routers_with_stale_cached_ext_net(self):
+        agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
+        self.plugin_api.get_external_network_id.return_value = 'aaa'
+        agent.target_ex_net_id = 'bbb'
+
+        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)
+        self.plugin_api.get_external_network_id.assert_called_with(
+            agent.context)
 
     def test_process_routers_with_no_ext_net_in_conf_and_two_net_plugin(self):
         agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)