summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleg Bondarev <obondarev@mirantis.com>2015-05-06 12:50:11 +0300
committerJakub Libosvar <libosvar@redhat.com>2015-10-07 15:14:20 +0200
commitf0bb982bfc81bb7c5bafde1430c51bea8f8ab9c9 (patch)
tree92dc4e4894bf9c341c61c99046b773fc4aae63f1
parent169cbd9164fce1ff83856821e55bdfac9b8dddec (diff)
downloadneutron-f0bb982bfc81bb7c5bafde1430c51bea8f8ab9c9.tar.gz
Wrap ML2 delete_port with db retry decorator
ML2 delete_port operation currently involves locking ports and bindings tables which may lead to DBDeadlock errors in certain cases when several ports are deleted concurrently. That may happen due to specifics of Galera working in active-active mode: it may throw deadlock errors when it fails to validate a change with other members of the cluster. The fix adds retries to delete port operation to overcome such deadlocks Conflicts: neutron/plugins/ml2/plugin.py neutron/tests/unit/ml2/test_ml2_plugin.py Closes-Bug: #1422504 Change-Id: I684691d59c5ac370d74314c3c91857dc709b2d9b (cherry picked from commit 45ea2cf10033e12c63b8ce2cd78b04755d0aba64) (cherry picked from commit 151b28cf1ce697f481d65b8d5bee1e3a4becbbc5)
-rw-r--r--neutron/plugins/ml2/plugin.py2
-rw-r--r--neutron/tests/unit/ml2/test_ml2_plugin.py17
2 files changed, 19 insertions, 0 deletions
diff --git a/neutron/plugins/ml2/plugin.py b/neutron/plugins/ml2/plugin.py
index 9dcf6f8452..49e40bf03a 100644
--- a/neutron/plugins/ml2/plugin.py
+++ b/neutron/plugins/ml2/plugin.py
@@ -991,6 +991,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
cur_binding.driver = new_binding.driver
cur_binding.segment = new_binding.segment
+ @db_api.wrap_db_retry(max_retries=db_api.MAX_RETRIES,
+ retry_on_deadlock=True)
def delete_port(self, context, id, l3_port_check=True):
LOG.debug(_("Deleting port %s"), id)
removed_routers = []
diff --git a/neutron/tests/unit/ml2/test_ml2_plugin.py b/neutron/tests/unit/ml2/test_ml2_plugin.py
index 28e38c7223..5510d48a28 100644
--- a/neutron/tests/unit/ml2/test_ml2_plugin.py
+++ b/neutron/tests/unit/ml2/test_ml2_plugin.py
@@ -19,6 +19,8 @@ import testtools
import uuid
import webob
+from oslo.db import exception as db_exc
+
from neutron.common import constants
from neutron.common import exceptions as exc
from neutron.common import utils
@@ -239,6 +241,21 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase):
# by the called method
self.assertIsNone(l3plugin.disassociate_floatingips(ctx, port_id))
+ def test_delete_port_tolerates_db_deadlock(self):
+ ctx = context.get_admin_context()
+ plugin = manager.NeutronManager.get_plugin()
+ with self.port() as port:
+ port_db, binding = ml2_db.get_locked_port_and_binding(
+ ctx.session, port['port']['id'])
+ with mock.patch('neutron.plugins.ml2.plugin.'
+ 'db.get_locked_port_and_binding') as lock:
+ lock.side_effect = [db_exc.DBDeadlock,
+ (port_db, binding)]
+ plugin.delete_port(ctx, port['port']['id'])
+ self.assertEqual(2, lock.call_count)
+ self.assertRaises(
+ exc.PortNotFound, plugin.get_port, ctx, port['port']['id'])
+
class TestMl2DvrPortsV2(TestMl2PortsV2):
def setUp(self):