From: Swaminathan Vasudevan Date: Wed, 16 Sep 2015 18:13:46 +0000 (-0700) Subject: Fixes SNAT port not found for internal port X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=e0664a4c2cd8ec5e24f67eac2b2c4e04464888d3;p=openstack-build%2Fneutron-build.git Fixes SNAT port not found for internal port For every router interface added to a router with a default gateway there will be an internal SNAT port generated and will be required by the L3 Agent to process the SNAT rules. This bug was introduced by the change ID below Icc099c1a97e3e68eeaf4690bc83167ba30d8099a. When the gateway is removed these ports have to be removed from the namespace. These ports are cached in the router_info and should be provided to the get_snat_port_for_internal_port function when called from external_gateway_removed or when called from _dvr_internal_network_removed. This patch fixes this problem. Closes-Bug: #1496578 Change-Id: Id5af4774ba246e24f343f5623af5ea9143bd5f6b --- diff --git a/neutron/agent/l3/dvr_local_router.py b/neutron/agent/l3/dvr_local_router.py index 7819438d2..1ecc79fc4 100644 --- a/neutron/agent/l3/dvr_local_router.py +++ b/neutron/agent/l3/dvr_local_router.py @@ -368,7 +368,9 @@ class DvrLocalRouter(dvr_router_base.DvrRouterBase): self.get_external_device_interface_name(ex_gw_port)) self.process_floating_ip_addresses(to_fip_interface_name) for p in self.internal_ports: - gateway = self.get_snat_port_for_internal_port(p) + # NOTE: When removing the gateway port, pass in the snat_port + # cache along with the current ports. + gateway = self.get_snat_port_for_internal_port(p, self.snat_ports) internal_interface = self.get_internal_device_name(p['id']) self._snat_redirect_remove(gateway, p, internal_interface) diff --git a/neutron/agent/l3/dvr_router_base.py b/neutron/agent/l3/dvr_router_base.py index 2fd1735e3..704be6ce6 100644 --- a/neutron/agent/l3/dvr_router_base.py +++ b/neutron/agent/l3/dvr_router_base.py @@ -40,13 +40,14 @@ class DvrRouterBase(router.RouterInfo): snat_ports = self.get_snat_interfaces() fixed_ip = int_port['fixed_ips'][0] subnet_id = fixed_ip['subnet_id'] - match_port = [p for p in snat_ports - if p['fixed_ips'][0]['subnet_id'] == subnet_id] - if match_port: - return match_port[0] - else: - LOG.error(_LE('DVR: SNAT port not found in the list ' - '%(snat_list)s for the given router ' - ' internal port %(int_p)s'), { - 'snat_list': snat_ports, - 'int_p': int_port}) + if snat_ports: + match_port = [p for p in snat_ports + if p['fixed_ips'][0]['subnet_id'] == subnet_id] + if match_port: + return match_port[0] + else: + LOG.error(_LE('DVR: SNAT port not found in the list ' + '%(snat_list)s for the given router ' + ' internal port %(int_p)s'), { + 'snat_list': snat_ports, + 'int_p': int_port}) diff --git a/neutron/tests/unit/agent/l3/test_agent.py b/neutron/tests/unit/agent/l3/test_agent.py index e2a5eb6b0..3be71f5c0 100644 --- a/neutron/tests/unit/agent/l3/test_agent.py +++ b/neutron/tests/unit/agent/l3/test_agent.py @@ -453,6 +453,7 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework): **self.ri_kwargs) ri._create_dvr_gateway = mock.Mock() ri.get_snat_interfaces = mock.Mock(return_value=self.snat_ports) + ri.snat_ports = self.snat_ports ri._create_snat_namespace() ri.fip_ns = agent.get_fip_ns(ex_net_id) ri.internal_ports = self.snat_ports @@ -535,6 +536,8 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework): ri._snat_redirect_remove.assert_called_with( sn_port, sn_port, ri.get_internal_device_name(sn_port['id'])) + ri.get_snat_port_for_internal_port.assert_called_with( + mock.ANY, ri.snat_ports) else: raise Exception("Invalid action %s" % action)