]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Ignore PortNotFound exceptions on lockless delete
authorKevin Benton <blak111@gmail.com>
Mon, 17 Mar 2014 15:46:39 +0000 (08:46 -0700)
committerKevin Benton <blak111@gmail.com>
Tue, 18 Mar 2014 05:10:55 +0000 (22:10 -0700)
Modifies the delete_ports_by_device_id method to
ignore PortNotFound exceptions because it has no
protection against concurrent operations deleting
the same ports that it's trying to delete.

Closes-Bug: #1293657
Change-Id: Icbcded149364a0e231ae811a440a691518bf20ad

neutron/db/db_base_plugin_v2.py
neutron/tests/unit/cisco/test_network_plugin.py
neutron/tests/unit/test_db_plugin.py

index b7ad1ecff602fd250e614cb868c69d1fa257de31..3bb3205d30b02b111cf82f8808ebcb7ffd5ea83a 100644 (file)
@@ -1357,7 +1357,13 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
             query = query.filter(models_v2.Port.network_id == network_id)
         port_ids = [p[0] for p in query]
         for port_id in port_ids:
-            self.delete_port(context, port_id)
+            try:
+                self.delete_port(context, port_id)
+            except n_exc.PortNotFound:
+                # Don't raise if something else concurrently deleted the port
+                LOG.debug(_("Ignoring PortNotFound when deleting port '%s'. "
+                            "The port has already been deleted."),
+                          port_id)
 
     def _delete_port(self, context, id):
         query = (context.session.query(models_v2.Port).
index fd3fac03106990f412bbabdfe89a27f3ffdef45f..a3ccc8c65087e4764786d3f7c8e9f42e06a51a76 100644 (file)
@@ -863,6 +863,10 @@ class TestCiscoPortsV2(CiscoNetworkPluginV2TestCase,
         plugin_ref = self._get_plugin_ref()
         self._test_delete_ports_by_device_id_second_call_failure(plugin_ref)
 
+    def test_delete_ports_ignores_port_not_found(self):
+        plugin_ref = self._get_plugin_ref()
+        self._test_delete_ports_ignores_port_not_found(plugin_ref)
+
 
 class TestCiscoNetworksV2(CiscoNetworkPluginV2TestCase,
                           test_db_plugin.TestNetworksV2):
index c7e780ac069df913a53db0a7aa463f2661274d1b..0dd19874941bf6f6cb7185a801458e5abccbfbcf 100644 (file)
@@ -1705,6 +1705,31 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s
         plugin = NeutronManager.get_plugin()
         self._test_delete_ports_by_device_id_second_call_failure(plugin)
 
+    def _test_delete_ports_ignores_port_not_found(self, plugin):
+        ctx = context.get_admin_context()
+        with self.subnet() as subnet:
+            with contextlib.nested(
+                self.port(subnet=subnet, device_id='owner1'),
+                mock.patch.object(plugin, 'delete_port')
+            ) as (p, del_port):
+                del_port.side_effect = n_exc.PortNotFound(
+                    port_id=p['port']['id']
+                )
+                network_id = subnet['subnet']['network_id']
+                try:
+                    plugin.delete_ports_by_device_id(ctx, 'owner1',
+                                                     network_id)
+                except n_exc.PortNotFound:
+                    self.fail("delete_ports_by_device_id unexpectedly raised "
+                              "a PortNotFound exception. It should ignore "
+                              "this exception because it is often called at "
+                              "the same time other concurrent operations are "
+                              "deleting some of the same ports.")
+
+    def test_delete_ports_ignores_port_not_found(self):
+        plugin = NeutronManager.get_plugin()
+        self._test_delete_ports_ignores_port_not_found(plugin)
+
 
 class TestNetworksV2(NeutronDbPluginV2TestCase):
     # NOTE(cerberus): successful network update and delete are