]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Delete disassociated floating ips on external network deletion
authorOleg Bondarev <obondarev@mirantis.com>
Wed, 23 Oct 2013 08:54:38 +0000 (12:54 +0400)
committerOleg Bondarev <obondarev@mirantis.com>
Mon, 31 Mar 2014 09:16:58 +0000 (13:16 +0400)
Also remove redundant check for network in use in bigswitch plugin

Closes-Bug: #1238439
Closes-Bug: #1259144

Change-Id: I7586f43c2e99be9df491c68bf1e8658994ffd263

21 files changed:
neutron/db/external_net_db.py
neutron/db/l3_db.py
neutron/plugins/bigswitch/plugin.py
neutron/plugins/brocade/NeutronPlugin.py
neutron/plugins/cisco/n1kv/n1kv_neutron_plugin.py
neutron/plugins/hyperv/hyperv_neutron_plugin.py
neutron/plugins/ibm/sdnve_neutron_plugin.py
neutron/plugins/linuxbridge/lb_neutron_plugin.py
neutron/plugins/midonet/plugin.py
neutron/plugins/ml2/plugin.py
neutron/plugins/mlnx/mlnx_plugin.py
neutron/plugins/nec/nec_plugin.py
neutron/plugins/nuage/plugin.py
neutron/plugins/oneconvergence/plugin.py
neutron/plugins/openvswitch/ovs_neutron_plugin.py
neutron/plugins/plumgrid/plumgrid_plugin/plumgrid_plugin.py
neutron/plugins/ryu/ryu_neutron_plugin.py
neutron/plugins/vmware/plugins/base.py
neutron/tests/unit/metaplugin/fake_plugin.py
neutron/tests/unit/test_extension_ext_net.py
neutron/tests/unit/test_l3_plugin.py

index 96602eca63670778fe8509ebe128668f6f8797bc..8fe1b91a46934f79263ddf6c50962509ce4a57bc 100644 (file)
@@ -27,6 +27,8 @@ from neutron.db import db_base_plugin_v2
 from neutron.db import model_base
 from neutron.db import models_v2
 from neutron.extensions import external_net
+from neutron import manager
+from neutron.plugins.common import constants as service_constants
 
 
 DEVICE_OWNER_ROUTER_GW = l3_constants.DEVICE_OWNER_ROUTER_GW
@@ -137,6 +139,12 @@ class External_net_db_mixin(object):
                 network_id=net_id).delete()
             net_data[external_net.EXTERNAL] = False
 
+    def _process_l3_delete(self, context, network_id):
+        l3plugin = manager.NeutronManager.get_service_plugins().get(
+            service_constants.L3_ROUTER_NAT)
+        if l3plugin:
+            l3plugin.delete_disassociated_floatingips(context, network_id)
+
     def _filter_nets_l3(self, context, nets, filters):
         vals = filters and filters.get(external_net.EXTERNAL, [])
         if not vals:
index 6096b19d3c3d685e4248d2756aade6f18405ee98..40789817b1ed80a9605b9e4fed410e15c14329b4 100644 (file)
@@ -718,6 +718,14 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
                                     marker_obj=marker_obj,
                                     page_reverse=page_reverse)
 
+    def delete_disassociated_floatingips(self, context, network_id):
+        query = self._model_query(context, FloatingIP)
+        query = query.filter_by(floating_network_id=network_id,
+                                fixed_port_id=None,
+                                router_id=None)
+        for fip in query:
+            self.delete_floatingip(context, fip.id)
+
     def get_floatingips_count(self, context, filters=None):
         return self._get_collection_count(context, FloatingIP,
                                           filters=filters)
index a5ba320813118a397e192a8977dc749dd7c540cb..7377598a08bb319345e694386e39b8bd96d8ae30 100644 (file)
@@ -609,18 +609,8 @@ class NeutronRestProxyV2(NeutronRestProxyV2Base,
 
         # Validate args
         orig_net = super(NeutronRestProxyV2, self).get_network(context, net_id)
-
-        filter = {'network_id': [net_id]}
-        ports = self.get_ports(context, filters=filter)
-
-        # check if there are any tenant owned ports in-use
-        auto_delete_port_owners = db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS
-        only_auto_del = all(p['device_owner'] in auto_delete_port_owners
-                            for p in ports)
-
-        if not only_auto_del:
-            raise exceptions.NetworkInUse(net_id=net_id)
         with context.session.begin(subtransactions=True):
+            self._process_l3_delete(context, net_id)
             ret_val = super(NeutronRestProxyV2, self).delete_network(context,
                                                                      net_id)
             self._send_delete_network(orig_net, context)
@@ -1075,6 +1065,18 @@ class NeutronRestProxyV2(NeutronRestProxyV2Base,
                                                                  port_id)
         self._send_floatingip_update(context)
 
+    # overriding method from l3_db as original method calls
+    # self.delete_floatingip() which in turn calls self.delete_port() which
+    # is locked with 'bsn-port-barrier'
+    def delete_disassociated_floatingips(self, context, network_id):
+        query = self._model_query(context, l3_db.FloatingIP)
+        query = query.filter_by(floating_network_id=network_id,
+                                fixed_port_id=None,
+                                router_id=None)
+        for fip in query:
+            context.session.delete(fip)
+            self._delete_port(context.elevated(), fip['floating_port_id'])
+
     def _send_floatingip_update(self, context):
         try:
             ext_net_id = self.get_external_network_id(context)
index ed27f2881ac388dc1b9cba46a8329abee01c7024..3190c0ef3c1206421be774a8535482070ef4d4b3 100644 (file)
@@ -318,6 +318,7 @@ class BrocadePluginV2(db_base_plugin_v2.NeutronDbPluginV2,
         """
 
         with context.session.begin(subtransactions=True):
+            self._process_l3_delete(context, net_id)
             result = super(BrocadePluginV2, self).delete_network(context,
                                                                  net_id)
             # we must delete all ports in db first (foreign key constraint)
index 028808b9f278542dbb626e4e0c389576bb23faaf..a2004764d9175127e2efd8a130efcac31fb6af28 100644 (file)
@@ -1100,6 +1100,8 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
             # the network_binding record is deleted via cascade from
             # the network record, so explicit removal is not necessary
             self._send_delete_network_request(context, network)
+
+            self._process_l3_delete(context, id)
             super(N1kvNeutronPluginV2, self).delete_network(context, id)
             LOG.debug(_("Deleted network: %s"), id)
 
index b9ccca29440f454cc14925f5579591f0c24d7903..e18bad8c725f02ebe87d1ddb0f2321d9d135e475 100644 (file)
@@ -276,6 +276,7 @@ class HyperVNeutronPlugin(agents_db.AgentDbMixin,
         session = context.session
         with session.begin(subtransactions=True):
             binding = self._db.get_network_binding(session, id)
+            self._process_l3_delete(context, id)
             super(HyperVNeutronPlugin, self).delete_network(context, id)
             p = self._network_providers_map[binding.network_type]
             p.delete_network(session, binding)
index fda586eb7eafeb2405b2a6864e56b0c7dd9e07f0..6b2178001f5016d166e62556fd2be02ea51d790f 100644 (file)
@@ -236,7 +236,11 @@ class SdnvePluginV2(db_base_plugin_v2.NeutronDbPluginV2,
     @_ha
     def delete_network(self, context, id):
         LOG.debug(_("Delete network in progress: %s"), id)
-        super(SdnvePluginV2, self).delete_network(context, id)
+        session = context.session
+
+        with session.begin(subtransactions=True):
+            self._process_l3_delete(context, id)
+            super(SdnvePluginV2, self).delete_network(context, id)
 
         (res, data) = self.sdnve_client.sdnve_delete('network', id)
         if res not in constants.HTTP_ACCEPTABLE:
index 52fbdcaddd37be1cd1b6e8b88949f60ced40035b..1a9c7367edbfd160b5650f7f8c149d46d1329af4 100644 (file)
@@ -444,6 +444,7 @@ class LinuxBridgePluginV2(db_base_plugin_v2.NeutronDbPluginV2,
         session = context.session
         with session.begin(subtransactions=True):
             binding = db.get_network_binding(session, id)
+            self._process_l3_delete(context, id)
             super(LinuxBridgePluginV2, self).delete_network(context, id)
             if binding.vlan_id != constants.LOCAL_VLAN_ID:
                 db.release_network(session, binding.physical_network,
index 5188ba0363bcf5981139678bbe700d9c622e31bf..baa3da0f8054441142c84faa37e7a3e4d6448239 100644 (file)
@@ -516,7 +516,9 @@ class MidonetPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
         LOG.debug(_("MidonetPluginV2.delete_network called: id=%r"), id)
         self.client.delete_bridge(id)
         try:
-            super(MidonetPluginV2, self).delete_network(context, id)
+            with context.session.begin(subtransactions=True):
+                self._process_l3_delete(context, id)
+                super(MidonetPluginV2, self).delete_network(context, id)
         except Exception:
             with excutils.save_and_reraise_exception():
                 LOG.error(_('Failed to delete neutron db, while Midonet '
index 4080ea07e50c4509e5180ba7a24ef8602e9bad60..7284c4922453a436389d2e965a06790bf0c495f3 100644 (file)
@@ -444,6 +444,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
         while True:
             try:
                 with session.begin(subtransactions=True):
+                    self._process_l3_delete(context, id)
+
                     # Get ports to auto-delete.
                     ports = (session.query(models_v2.Port).
                              enable_eagerloads(False).
index 920038f5bc93c2b633473577cbe81d5a986d1b90..48e8ae79590b55b9d092927e733fec6b84577bdf 100644 (file)
@@ -379,6 +379,7 @@ class MellanoxEswitchPlugin(db_base_plugin_v2.NeutronDbPluginV2,
         session = context.session
         with session.begin(subtransactions=True):
             binding = db.get_network_binding(session, net_id)
+            self._process_l3_delete(context, net_id)
             super(MellanoxEswitchPlugin, self).delete_network(context,
                                                               net_id)
             if binding.segmentation_id != constants.LOCAL_VLAN_ID:
index 94220c4e427c261ae98bc507237f889bbcde1495..d0f45608c0b309e4d689eb1b990b6ab4fe2c0133 100644 (file)
@@ -373,17 +373,24 @@ class NECPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
         tenant_id = net_db['tenant_id']
         ports = self.get_ports(context, filters={'network_id': [id]})
 
-        # check if there are any tenant owned ports in-use
+        # check if there are any tenant owned ports in-use;
+        # consider ports owned by floating ips as auto_delete as if there are
+        # no other tenant owned ports, those floating ips are disassociated
+        # and will be auto deleted with self._process_l3_delete()
         only_auto_del = all(p['device_owner'] in
-                            db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS
+                            db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS or
+                            p['device_owner'] == const.DEVICE_OWNER_FLOATINGIP
                             for p in ports)
         if not only_auto_del:
             raise n_exc.NetworkInUse(net_id=id)
 
+        self._process_l3_delete(context, id)
+
         # Make sure auto-delete ports on OFC are deleted.
         # If an error occurs during port deletion,
         # delete_network will be aborted.
-        for port in ports:
+        for port in [p for p in ports if p['device_owner']
+                     in db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS]:
             port = self.deactivate_port(context, port)
 
         # delete all packet_filters of the network from the controller
index 9821048ab9324d8d1a927f829d8b50d9a53ca3e6..294cb17b16ad2b47ab867a47d903f2cd34ac6d58 100644 (file)
@@ -304,11 +304,13 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2,
         return net
 
     def delete_network(self, context, id):
-        filter = {'network_id': [id]}
-        subnets = self.get_subnets(context, filters=filter)
-        for subnet in subnets:
-            self.delete_subnet(context, subnet['id'])
-        super(NuagePlugin, self).delete_network(context, id)
+        with context.session.begin(subtransactions=True):
+            self._process_l3_delete(context, id)
+            filter = {'network_id': [id]}
+            subnets = self.get_subnets(context, filters=filter)
+            for subnet in subnets:
+                self.delete_subnet(context, subnet['id'])
+            super(NuagePlugin, self).delete_network(context, id)
 
     def _get_net_partition_for_subnet(self, context, subnet):
         subn = subnet['subnet']
index daf85ee6d9239835a30b3a1be1f829f54d835ea9..2b1b6edcef92e089909c5d21f372e36262c6f326 100644 (file)
@@ -219,6 +219,7 @@ class OneConvergencePluginV2(db_base_plugin_v2.NeutronDbPluginV2,
             #get all the subnets under the network to delete them
             subnets = self._get_subnets_by_network(context, net_id)
 
+            self._process_l3_delete(context, net_id)
             super(OneConvergencePluginV2, self).delete_network(context,
                                                                net_id)
 
index 2cfe2674b60670d17a8e940e2208caca81721427..5987e0d198cd2a69ad38c092edaea9f8d1dd8a02 100644 (file)
@@ -526,6 +526,7 @@ class OVSNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
         session = context.session
         with session.begin(subtransactions=True):
             binding = ovs_db_v2.get_network_binding(session, id)
+            self._process_l3_delete(context, id)
             super(OVSNeutronPluginV2, self).delete_network(context, id)
             if binding.network_type in constants.TUNNEL_NETWORK_TYPES:
                 ovs_db_v2.release_tunnel(session, binding.segmentation_id,
index 2e41aadae19ae38c786bcced938b7ea8b5d96684..619dd1e63d4f58457509204ee4d25afc9df3c0bf 100644 (file)
@@ -156,6 +156,7 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
                        self).get_network(context, net_id)
 
         with context.session.begin(subtransactions=True):
+            self._process_l3_delete(context, net_id)
             # Plugin DB - Network Delete
             super(NeutronPluginPLUMgridV2, self).delete_network(context,
                                                                 net_id)
index 9259d771ff6fcf2397cb830b1a8f31376ea5224a..2279abbc42e02d0dd590733929b835a782625b6b 100644 (file)
@@ -202,6 +202,7 @@ class RyuNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
         session = context.session
         with session.begin(subtransactions=True):
             self.tunnel_key.delete(session, id)
+            self._process_l3_delete(context, id)
             super(RyuNeutronPluginV2, self).delete_network(context, id)
 
     def create_port(self, context, port):
index 457fa8bc040bd6a3bdfd84f2817c004be188cd61..12a4cffa0a4b25b53a53c8919bc5e2ba67d2cf71 100644 (file)
@@ -1029,7 +1029,10 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
         if not external:
             lswitch_ids = nsx_utils.get_nsx_switch_ids(
                 context.session, self.cluster, id)
-        super(NsxPluginV2, self).delete_network(context, id)
+        with context.session.begin(subtransactions=True):
+            self._process_l3_delete(context, id)
+            super(NsxPluginV2, self).delete_network(context, id)
+
         # clean up network owned ports
         for port in router_iface_ports:
             try:
index 6653ea25b5f109a178f7c60e5a9b00096cd10979..1ba3c15609bc9035a04970b3a62c9768e0c898f8 100644 (file)
@@ -43,7 +43,10 @@ class Fake1(db_base_plugin_v2.NeutronDbPluginV2,
         return net
 
     def delete_network(self, context, id):
-        return super(Fake1, self).delete_network(context, id)
+        session = context.session
+        with session.begin(subtransactions=True):
+            self._process_l3_delete(context, id)
+            return super(Fake1, self).delete_network(context, id)
 
     def create_port(self, context, port):
         port = super(Fake1, self).create_port(context, port)
index 24578b8690f667361a35baf3d5c9d8759033a29d..1a8db1d2f0a8b13e1d3fd402ac97b2c06fee7582 100644 (file)
@@ -18,6 +18,7 @@
 import contextlib
 import itertools
 
+import mock
 import testtools
 from webob import exc
 
@@ -158,6 +159,18 @@ class ExtNetDBTestCase(test_db_plugin.NeutronDbPluginV2TestCase):
             self.assertEqual(ext_net['network'][external_net.EXTERNAL],
                              True)
 
+    def test_delete_network_check_disassociated_floatingips(self):
+        with mock.patch.object(NeutronManager,
+                               'get_service_plugins') as srv_plugins:
+            l3_mock = mock.Mock()
+            srv_plugins.return_value = {'L3_ROUTER_NAT': l3_mock}
+            with self.network(do_delete=False) as net:
+                req = self.new_delete_request('networks', net['network']['id'])
+                res = req.get_response(self.api)
+                self.assertEqual(res.status_int, exc.HTTPNoContent.code)
+                (l3_mock.delete_disassociated_floatingips
+                 .assert_called_once_with(mock.ANY, net['network']['id']))
+
 
 class ExtNetDBTestCaseXML(ExtNetDBTestCase):
     fmt = 'xml'
index 05aa3220ec31a142ac1f3d9b8c9fb89da86114ea..c968aa5518d143ad16403475cf21b9a802710f47 100644 (file)
@@ -234,6 +234,11 @@ class TestL3NatBasePlugin(db_base_plugin_v2.NeutronDbPluginV2,
             self._process_l3_update(context, net, network['network'])
         return net
 
+    def delete_network(self, context, id):
+        with context.session.begin(subtransactions=True):
+            self._process_l3_delete(context, id)
+            super(TestL3NatBasePlugin, self).delete_network(context, id)
+
     def delete_port(self, context, id, l3_port_check=True):
         plugin = NeutronManager.get_service_plugins().get(
             service_constants.L3_ROUTER_NAT)
@@ -1618,6 +1623,13 @@ class L3NatTestCaseBase(L3NatTestCaseMixin):
                                               s['subnet']['id'],
                                               None)
 
+    def test_delete_ext_net_with_disassociated_floating_ips(self):
+        with self.network() as net:
+            net_id = net['network']['id']
+            self._set_net_external(net_id)
+            with self.subnet(network=net, do_delete=False):
+                self._make_floatingip(self.fmt, net_id)
+
 
 class L3AgentDbTestCaseBase(L3NatTestCaseMixin):