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 commit45ea2cf100
) (cherry picked from commit151b28cf1c
)
This commit is contained in:
parent
169cbd9164
commit
f0bb982bfc
|
@ -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 = []
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue