]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Catch PortNotFound and SubnetNotFound during network_delete
authorEugene Nikanorov <enikanorov@mirantis.com>
Tue, 23 Dec 2014 17:28:12 +0000 (20:28 +0300)
committerEugene Nikanorov <enikanorov@mirantis.com>
Wed, 7 Jan 2015 07:45:47 +0000 (10:45 +0300)
In some cases PortNotFound exception during network_delete
could be caused by concurrent port deletion by DHCP agent.
This condition should not prevent network from deleting.

Change-Id: Ie6eae4cecb64120c41de9823d9e72066094ad2ce
Closes-Bug: #1405197

neutron/plugins/ml2/plugin.py
neutron/tests/unit/ml2/test_ml2_plugin.py

index 18b044ea429240ed170141595c1ffcd264653972..a5c9d68b6cd09dc7ded6d6556750d93ce5d52cf5 100644 (file)
@@ -564,6 +564,31 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
 
         return [self._fields(net, fields) for net in nets]
 
+    def _delete_ports(self, context, ports):
+        for port in ports:
+            try:
+                self.delete_port(context, port.id)
+            except exc.PortNotFound:
+                # concurrent port deletion can be performed by
+                # release_dhcp_port caused by concurrent subnet_delete
+                LOG.info(_LI("Port %s was deleted concurrently"), port.id)
+            except Exception:
+                with excutils.save_and_reraise_exception():
+                    LOG.exception(_LE("Exception auto-deleting port %s"),
+                                  port.id)
+
+    def _delete_subnets(self, context, subnets):
+        for subnet in subnets:
+            try:
+                self.delete_subnet(context, subnet.id)
+            except exc.SubnetNotFound:
+                LOG.info(_LI("Subnet %s was deleted concurrently"),
+                         subnet.id)
+            except Exception:
+                with excutils.save_and_reraise_exception():
+                    LOG.exception(_LE("Exception auto-deleting subnet %s"),
+                                  subnet.id)
+
     def delete_network(self, context, id):
         # REVISIT(rkukura) The super(Ml2Plugin, self).delete_network()
         # function is not used because it auto-deletes ports and
@@ -634,22 +659,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
                         LOG.warning(_LW("A concurrent port creation has "
                                         "occurred"))
                         continue
-
-            for port in ports:
-                try:
-                    self.delete_port(context, port.id)
-                except Exception:
-                    with excutils.save_and_reraise_exception():
-                        LOG.exception(_LE("Exception auto-deleting port %s"),
-                                      port.id)
-
-            for subnet in subnets:
-                try:
-                    self.delete_subnet(context, subnet.id)
-                except Exception:
-                    with excutils.save_and_reraise_exception():
-                        LOG.exception(_LE("Exception auto-deleting subnet %s"),
-                                      subnet.id)
+            self._delete_ports(context, ports)
+            self._delete_subnets(context, subnets)
 
         try:
             self.mechanism_manager.delete_network_postcommit(mech_context)
index 4bf311598109b9106e6785f6588b99d81047aa30..d457cff5f7afbc99721ef693c07ba01948f5a3ec 100644 (file)
@@ -118,7 +118,17 @@ class TestMl2V2HTTPResponse(test_plugin.TestV2HTTPResponse,
 
 class TestMl2NetworksV2(test_plugin.TestNetworksV2,
                         Ml2PluginV2TestCase):
-    pass
+    def test_port_delete_helper_tolerates_failure(self):
+        plugin = manager.NeutronManager.get_plugin()
+        with mock.patch.object(plugin, "delete_port",
+                               side_effect=exc.PortNotFound(port_id="123")):
+            plugin._delete_ports(None, [mock.MagicMock()])
+
+    def test_subnet_delete_helper_tolerates_failure(self):
+        plugin = manager.NeutronManager.get_plugin()
+        with mock.patch.object(plugin, "delete_subnet",
+                               side_effect=exc.SubnetNotFound(subnet_id="1")):
+            plugin._delete_subnets(None, [mock.MagicMock()])
 
 
 class TestMl2SubnetsV2(test_plugin.TestSubnetsV2,