Browse Source

[OVN] Do not delete port's revision on RowNotFound

The delete_port() method from OVNClient has a potential problem of
leaving stale ports when RowNotFound is raised from the process to
delete the port from the OVN database. Since the exception is not
granular enough, the RowNotFound could be raised from other objects that
are part of the same transaction (such as ACLs, DNS entries, etc...)
resulting in the revision for the port being deleted even tho the port
is still in the database.

Instead of giving a pass on the RowNotFound exception, this patch is
logging the error and re-raising it without deleting the revision.

(cherry-picked from Neutron I25b93b7c080403fc38365b638e4e03298b447d0f)

Change-Id: Ic0d1234b032a58ce370e1703edc259b584099238
Partial-Bug: #1874733
Signed-off-by: Lucas Alvares Gomes <lucasagomes@gmail.com>
tags/6.1.0
Lucas Alvares Gomes 2 months ago
parent
commit
b46df7aca9
2 changed files with 17 additions and 2 deletions
  1. +4
    -2
      networking_ovn/common/ovn_client.py
  2. +13
    -0
      networking_ovn/tests/unit/ml2/test_mech_driver.py

+ 4
- 2
networking_ovn/common/ovn_client.py View File

@@ -614,8 +614,10 @@ class OVNClient(object):
def delete_port(self, port_id, port_object=None):
try:
self._delete_port(port_id, port_object=port_object)
except idlutils.RowNotFound:
pass
except Exception as e:
with excutils.save_and_reraise_exception():
LOG.error('Failed to delete port %(port)s. Error: '
'%(error)s', {'port': port_id, 'error': e})
db_rev.delete_revision(port_id, ovn_const.TYPE_PORTS)

def _create_or_update_floatingip(self, floatingip, txn=None):


+ 13
- 0
networking_ovn/tests/unit/ml2/test_mech_driver.py View File

@@ -780,6 +780,19 @@ class TestOVNMechanismDriver(test_plugin.Ml2PluginV2TestCase):
self.assertEqual(
1, self.nb_ovn.update_address_set.call_count)

@mock.patch.object(db_rev, 'delete_revision')
@mock.patch.object(ovn_client.OVNClient, '_delete_port')
def test_delete_port_exception_delete_revision(self, mock_del_port,
mock_del_rev):
mock_del_port.side_effect = Exception('BoOoOoOoOmmmmm!!!')
with self.network(set_context=True, tenant_id='test') as net:
with self.subnet(network=net) as subnet:
with self.port(subnet=subnet,
set_context=True, tenant_id='test') as port:
self._delete('ports', port['port']['id'])
# Assert that delete_revision wasn't invoked
mock_del_rev.assert_not_called()

def _test_set_port_status_up(self, is_compute_port=False):
port_device_owner = 'compute:nova' if is_compute_port else ''
self.mech_driver._plugin.nova_notifier = mock.Mock()


Loading…
Cancel
Save