diff --git a/neutron/agent/l3/extensions/port_forwarding.py b/neutron/agent/l3/extensions/port_forwarding.py index 5fed22d2d13..840ced5ca33 100644 --- a/neutron/agent/l3/extensions/port_forwarding.py +++ b/neutron/agent/l3/extensions/port_forwarding.py @@ -97,6 +97,14 @@ class RouterFipPortForwardingMapping(object): old_pf = self.get_port_forwarding(new_pf.id) return old_pf != new_pf + @lockutils.synchronized('port-forwarding-cache') + def clean_port_forwardings_by_router_id(self, router_id): + router_fips = self.router_fip_mapping.pop(router_id, []) + for fip_id in router_fips: + pf_ids = self.fip_port_forwarding.pop(fip_id, []) + for pf_id in pf_ids: + self.managed_port_forwardings.pop(pf_id, None) + class PortForwardingAgentExtension(l3_extension.L3AgentExtension): SUPPORTED_RESOURCE_TYPES = [resources.PORTFORWARDING] @@ -455,7 +463,7 @@ class PortForwardingAgentExtension(l3_extension.L3AgentExtension): :param context: RPC context. :param data: Router data. """ - pass + self.mapping.clean_port_forwardings_by_router_id(data['id']) def ha_state_change(self, context, data): pass diff --git a/neutron/tests/unit/agent/l3/extensions/test_port_forwarding.py b/neutron/tests/unit/agent/l3/extensions/test_port_forwarding.py index d7b599c03ce..67e0e7d3f6f 100644 --- a/neutron/tests/unit/agent/l3/extensions/test_port_forwarding.py +++ b/neutron/tests/unit/agent/l3/extensions/test_port_forwarding.py @@ -281,6 +281,38 @@ class FipPortForwardingExtensionTestCase(PortForwardingExtensionBaseTestCase): lib_const.FLOATINGIP_STATUS_DOWN} mock_send_fip_status.assert_called_once_with(mock.ANY, fip_status) + @mock.patch.object(pf.PortForwardingAgentExtension, + '_sending_port_forwarding_fip_status') + @mock.patch.object(iptables_manager.IptablesTable, 'add_rule') + @mock.patch.object(iptables_manager.IptablesTable, 'add_chain') + @mock.patch.object(l3router.RouterInfo, 'add_floating_ip') + def test_add_delete_router(self, mock_add_fip, + mock_add_chain, mock_add_rule, + mock_send_fip_status): + # simulate the router add and already there is a port forwarding + # resource association. + mock_add_fip.return_value = lib_const.FLOATINGIP_STATUS_ACTIVE + self.fip_pf_ext.add_router(self.context, self.router) + self._assert_called_iptables_process( + mock_add_chain, mock_add_rule, mock_add_fip, mock_send_fip_status, + target_obj=self.portforwarding1) + + router_fip_ids = self.fip_pf_ext.mapping.router_fip_mapping.get( + self.router['id']) + self.assertIsNotNone(router_fip_ids) + for fip_id in router_fip_ids: + pf_ids = self.fip_pf_ext.mapping.fip_port_forwarding.get(fip_id) + self.assertIsNotNone(pf_ids) + for pf_id in pf_ids: + pf = self.fip_pf_ext.mapping.managed_port_forwardings.get( + pf_id) + self.assertIsNotNone(pf) + + self.fip_pf_ext.delete_router(self.context, self.router) + + self.assertIsNone( + self.fip_pf_ext.mapping.router_fip_mapping.get(self.router['id'])) + def test_check_if_need_process_no_snat_ns(self): ex_gw_port = {'id': _uuid()} router_id = _uuid()