diff --git a/neutron/common/_constants.py b/neutron/common/_constants.py index 05dc54861ed..bb1da44e264 100644 --- a/neutron/common/_constants.py +++ b/neutron/common/_constants.py @@ -76,4 +76,5 @@ IDPOOL_SELECT_SIZE = 100 # with these owners, it will allow subnet deletion to proceed with the # IP allocations being cleaned up by cascade. AUTO_DELETE_PORT_OWNERS = [constants.DEVICE_OWNER_DHCP, - constants.DEVICE_OWNER_DISTRIBUTED] + constants.DEVICE_OWNER_DISTRIBUTED, + constants.DEVICE_OWNER_AGENT_GW] diff --git a/neutron/db/l3_dvr_db.py b/neutron/db/l3_dvr_db.py index f5df0244a82..140bdf3823a 100644 --- a/neutron/db/l3_dvr_db.py +++ b/neutron/db/l3_dvr_db.py @@ -13,6 +13,7 @@ # under the License. import collections +from neutron_lib.api.definitions import external_net as extnet_apidef from neutron_lib.api.definitions import l3 as l3_apidef from neutron_lib.api.definitions import portbindings from neutron_lib.api.definitions import portbindings_extended @@ -409,6 +410,15 @@ class DVRResourceOperationHandler(object): if host_id: return + @registry.receives(resources.NETWORK, [events.AFTER_DELETE]) + def delete_fip_namespaces_for_ext_net(self, rtype, event, trigger, + context, network, **kwargs): + if network.get(extnet_apidef.EXTERNAL): + # Send the information to all the L3 Agent hosts + # to clean up the fip namespace as it is no longer required. + self.l3plugin.l3_rpc_notifier.delete_fipnamespace_for_ext_net( + context, network['id']) + def _get_ports_for_allowed_address_pair_ip(self, context, network_id, fixed_ip): """Return all active ports associated with the allowed_addr_pair ip.""" diff --git a/neutron/tests/unit/db/test_db_base_plugin_v2.py b/neutron/tests/unit/db/test_db_base_plugin_v2.py index 10746ffbeb7..0363d593f47 100644 --- a/neutron/tests/unit/db/test_db_base_plugin_v2.py +++ b/neutron/tests/unit/db/test_db_base_plugin_v2.py @@ -1611,17 +1611,25 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s res = req.get_response(self.api) self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) - def test_delete_network_port_exists_owned_by_network(self): + def _test_delete_network_port_exists_owned_by_network(self, device_owner): res = self._create_network(fmt=self.fmt, name='net', admin_state_up=True) network = self.deserialize(self.fmt, res) network_id = network['network']['id'] self._create_port(self.fmt, network_id, - device_owner=constants.DEVICE_OWNER_DHCP) + device_owner=device_owner) req = self.new_delete_request('networks', network_id) res = req.get_response(self.api) self.assertEqual(webob.exc.HTTPNoContent.code, res.status_int) + def test_test_delete_network_port_exists_dhcp(self): + self._test_delete_network_port_exists_owned_by_network( + constants.DEVICE_OWNER_DHCP) + + def test_test_delete_network_port_exists_fip_gw(self): + self._test_delete_network_port_exists_owned_by_network( + constants.DEVICE_OWNER_AGENT_GW) + def test_delete_network_port_exists_owned_by_network_race(self): res = self._create_network(fmt=self.fmt, name='net', admin_state_up=True)