Catch DB reference errors in binding DVR ports
A port can be deleted right after get_port is called but before
the binding is created. So we need to catch both PortNotFound
from the get_port and DBReferenceError from the binding creation.
Co-Authored-By: Adolfo Duarte <adolfo.duarte@hpe.com>
Closes-Bug: #1501515
Change-Id: Ieddcb10bb019fe6dd7079255124e48305f406614
(cherry picked from commit 06569179ae
)
This commit is contained in:
parent
e9622b0bb0
commit
362896a7cf
@ -1282,21 +1282,23 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
binding.vif_type == portbindings.VIF_TYPE_BINDING_FAILED or
|
||||
router_id != device_id)
|
||||
if update_required:
|
||||
with session.begin(subtransactions=True):
|
||||
try:
|
||||
orig_port = super(Ml2Plugin, self).get_port(context, id)
|
||||
except exc.PortNotFound:
|
||||
LOG.debug("DVR Port %s has been deleted concurrently", id)
|
||||
return
|
||||
if not binding:
|
||||
binding = db.ensure_dvr_port_binding(
|
||||
session, id, host, router_id=device_id)
|
||||
network = self.get_network(context, orig_port['network_id'])
|
||||
levels = db.get_binding_levels(session, id, host)
|
||||
mech_context = driver_context.PortContext(self,
|
||||
context, orig_port, network,
|
||||
binding, levels, original_port=orig_port)
|
||||
self._process_dvr_port_binding(mech_context, context, attrs)
|
||||
try:
|
||||
with session.begin(subtransactions=True):
|
||||
orig_port = self.get_port(context, id)
|
||||
if not binding:
|
||||
binding = db.ensure_dvr_port_binding(
|
||||
session, id, host, router_id=device_id)
|
||||
network = self.get_network(context,
|
||||
orig_port['network_id'])
|
||||
levels = db.get_binding_levels(session, id, host)
|
||||
mech_context = driver_context.PortContext(self,
|
||||
context, orig_port, network,
|
||||
binding, levels, original_port=orig_port)
|
||||
self._process_dvr_port_binding(mech_context, context,
|
||||
attrs)
|
||||
except (os_db_exception.DBReferenceError, exc.PortNotFound):
|
||||
LOG.debug("DVR Port %s has been deleted concurrently", id)
|
||||
return
|
||||
self._bind_port_if_needed(mech_context)
|
||||
|
||||
def _pre_delete_port(self, context, port_id, port_check):
|
||||
|
@ -1171,6 +1171,18 @@ class TestMl2PortBinding(Ml2PluginV2TestCase,
|
||||
mech_context._binding.router_id)
|
||||
self.assertEqual(host_id, mech_context._binding.host)
|
||||
|
||||
def test_update_dvr_port_binding_on_concurrent_port_delete(self):
|
||||
plugin = manager.NeutronManager.get_plugin()
|
||||
with self.port() as port:
|
||||
port = {
|
||||
'id': port['port']['id'],
|
||||
portbindings.HOST_ID: 'foo_host',
|
||||
}
|
||||
with mock.patch.object(plugin, 'get_port', new=plugin.delete_port):
|
||||
res = plugin.update_dvr_port_binding(
|
||||
self.context, 'foo_port_id', {'port': port})
|
||||
self.assertIsNone(res)
|
||||
|
||||
def test_update_dvr_port_binding_on_non_existent_port(self):
|
||||
plugin = manager.NeutronManager.get_plugin()
|
||||
port = {
|
||||
|
Loading…
Reference in New Issue
Block a user