From e74b85f854e248919299fd875066903eba0a37c9 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Mon, 25 Aug 2014 10:33:40 -0700 Subject: [PATCH] ext-gw update on dvr router improperly handled by l3-agent The recently added external_gateway method does not check the agent mode or host binding before adding an external gateway to a particular node/agent. This fix adds the required checks in the update path. Change-Id: Idbb76eea1faec1c5d6b7615d23d74760cc327bb2 Closes-bug: #1356734 --- neutron/agent/l3_agent.py | 8 ++++- neutron/tests/unit/test_l3_agent.py | 49 ++++++++++++++++++++++++++--- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/neutron/agent/l3_agent.py b/neutron/agent/l3_agent.py index f20fee878..d044d083d 100644 --- a/neutron/agent/l3_agent.py +++ b/neutron/agent/l3_agent.py @@ -1233,7 +1233,13 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager): def external_gateway_updated(self, ri, ex_gw_port, interface_name): preserve_ips = [] if ri.router['distributed']: - ns_name = self.get_snat_ns_name(ri.router['id']) + if (self.conf.agent_mode == 'dvr_snat' and + ri.router['gw_port_host'] == self.host): + ns_name = self.get_snat_ns_name(ri.router['id']) + else: + # no centralized SNAT gateway for this node/agent + LOG.debug("not hosting snat for router: %", ri.router['id']) + return else: ns_name = ri.ns_name floating_ips = self.get_floating_ips(ri) diff --git a/neutron/tests/unit/test_l3_agent.py b/neutron/tests/unit/test_l3_agent.py index 6f15e9c02..da998ecd7 100644 --- a/neutron/tests/unit/test_l3_agent.py +++ b/neutron/tests/unit/test_l3_agent.py @@ -488,11 +488,7 @@ class TestBasicRouterOperations(base.BaseTestCase): else: raise Exception("Invalid action %s" % action) - def test_external_gateway_updated(self): - router = prepare_router_data(num_internal_ports=2) - ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper, - self.conf.use_namespaces, router=router) - agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) + def _prepare_ext_gw_test(self, agent): ex_gw_port = {'fixed_ips': [{'ip_address': '20.0.0.30', 'subnet_id': _uuid()}], 'subnet': {'gateway_ip': '20.0.0.1'}, @@ -504,6 +500,16 @@ class TestBasicRouterOperations(base.BaseTestCase): interface_name = agent.get_external_device_name(ex_gw_port['id']) self.device_exists.return_value = True + + return interface_name, ex_gw_port + + def test_external_gateway_updated(self): + router = prepare_router_data(num_internal_ports=2) + ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper, + self.conf.use_namespaces, router=router) + agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) + interface_name, ex_gw_port = self._prepare_ext_gw_test(agent) + fake_fip = {'floatingips': [{'id': _uuid(), 'floating_ip_address': '192.168.1.34', 'fixed_ip_address': '192.168.0.1', @@ -523,6 +529,39 @@ class TestBasicRouterOperations(base.BaseTestCase): ['20.0.0.30/24'], **kwargs) + def _test_ext_gw_updated_dvr_agent_mode(self, host, + agent_mode, expected_call_count): + router = prepare_router_data(num_internal_ports=2) + ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper, + self.conf.use_namespaces, router=router) + agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) + interface_name, ex_gw_port = self._prepare_ext_gw_test(agent) + agent._external_gateway_added = mock.Mock() + + # test agent mode = dvr (compute node) + router['distributed'] = True + router['gw_port_host'] = host + agent.conf.agent_mode = agent_mode + + agent.external_gateway_updated(ri, ex_gw_port, + interface_name) + # no gateway should be added on dvr node + self.assertEqual(expected_call_count, + agent._external_gateway_added.call_count) + + def test_ext_gw_updated_dvr_agent_mode(self): + # no gateway should be added on dvr node + self._test_ext_gw_updated_dvr_agent_mode('any-foo', 'dvr', 0) + + def test_ext_gw_updated_dvr_snat_agent_mode_no_host(self): + # no gateway should be added on dvr_snat node without host match + self._test_ext_gw_updated_dvr_agent_mode('any-foo', 'dvr_snat', 0) + + def test_ext_gw_updated_dvr_snat_agent_mode_host(self): + # gateway should be added on dvr_snat node + self._test_ext_gw_updated_dvr_agent_mode(self.conf.host, + 'dvr_snat', 1) + def test_agent_add_external_gateway(self): self._test_external_gateway_action('add') -- 2.45.2