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
|
binding.vif_type == portbindings.VIF_TYPE_BINDING_FAILED or
|
||||||
router_id != device_id)
|
router_id != device_id)
|
||||||
if update_required:
|
if update_required:
|
||||||
with session.begin(subtransactions=True):
|
try:
|
||||||
try:
|
with session.begin(subtransactions=True):
|
||||||
orig_port = super(Ml2Plugin, self).get_port(context, id)
|
orig_port = self.get_port(context, id)
|
||||||
except exc.PortNotFound:
|
if not binding:
|
||||||
LOG.debug("DVR Port %s has been deleted concurrently", id)
|
binding = db.ensure_dvr_port_binding(
|
||||||
return
|
session, id, host, router_id=device_id)
|
||||||
if not binding:
|
network = self.get_network(context,
|
||||||
binding = db.ensure_dvr_port_binding(
|
orig_port['network_id'])
|
||||||
session, id, host, router_id=device_id)
|
levels = db.get_binding_levels(session, id, host)
|
||||||
network = self.get_network(context, orig_port['network_id'])
|
mech_context = driver_context.PortContext(self,
|
||||||
levels = db.get_binding_levels(session, id, host)
|
context, orig_port, network,
|
||||||
mech_context = driver_context.PortContext(self,
|
binding, levels, original_port=orig_port)
|
||||||
context, orig_port, network,
|
self._process_dvr_port_binding(mech_context, context,
|
||||||
binding, levels, original_port=orig_port)
|
attrs)
|
||||||
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)
|
self._bind_port_if_needed(mech_context)
|
||||||
|
|
||||||
def _pre_delete_port(self, context, port_id, port_check):
|
def _pre_delete_port(self, context, port_id, port_check):
|
||||||
|
|
|
@ -1171,6 +1171,18 @@ class TestMl2PortBinding(Ml2PluginV2TestCase,
|
||||||
mech_context._binding.router_id)
|
mech_context._binding.router_id)
|
||||||
self.assertEqual(host_id, mech_context._binding.host)
|
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):
|
def test_update_dvr_port_binding_on_non_existent_port(self):
|
||||||
plugin = manager.NeutronManager.get_plugin()
|
plugin = manager.NeutronManager.get_plugin()
|
||||||
port = {
|
port = {
|
||||||
|
|
Loading…
Reference in New Issue