From 702e1fbf7ad5dd961dfd35cd6a0e54d4d6da5e34 Mon Sep 17 00:00:00 2001 From: Carl Baldwin Date: Wed, 15 Jan 2014 18:46:17 +0000 Subject: [PATCH] L3 agent fetches the external network id once 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 | 16 +++++++++++--- neutron/tests/unit/test_l3_agent.py | 33 +++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/neutron/agent/l3_agent.py b/neutron/agent/l3_agent.py index 01132cc79..575d7129a 100644 --- a/neutron/agent/l3_agent.py +++ b/neutron/agent/l3_agent.py @@ -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) diff --git a/neutron/tests/unit/test_l3_agent.py b/neutron/tests/unit/test_l3_agent.py index 6b81ac8e7..decf39b9f 100644 --- a/neutron/tests/unit/test_l3_agent.py +++ b/neutron/tests/unit/test_l3_agent.py @@ -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) -- 2.45.2