[OVN] Make delete_router_port() less error prone

This commit makes the delete_router_port() method from OVNClient more
resilient to NotFound errors. Apart from the L3 plugin, this method is
also invoked by the maintenance task to fix stale/not-up-to-date objects
in the OVN database, and since the maintenance task runs every 5 minutes
only it could happen that some objects fetched by delete_router_port()
are gone by the moment that method is invoked.

Change-Id: I0d78278797beb2af42ec38462e2b2edc8e2a4ae6
Closes-Bug: #1920968
Signed-off-by: Lucas Alvares Gomes <lucasagomes@gmail.com>
This commit is contained in:
Lucas Alvares Gomes 2021-03-23 16:29:46 +00:00
parent e9a75a379e
commit 36b8c684b1
2 changed files with 31 additions and 5 deletions

View File

@ -25,6 +25,7 @@ from neutron_lib.api.definitions import segment as segment_def
from neutron_lib import constants as const
from neutron_lib import context as n_context
from neutron_lib import exceptions as n_exc
from neutron_lib.exceptions import l3 as l3_exc
from neutron_lib.plugins import constants as plugin_constants
from neutron_lib.plugins import directory
from neutron_lib.plugins import utils as p_utils
@ -1484,14 +1485,18 @@ class OVNClient(object):
router_id = router_id or ovn_port.external_ids.get(
ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY)
if not router_id:
if port and not router_id:
router_id = port.get('device_id')
router = None
if router_id:
router = self._l3_plugin.get_router(context, router_id)
try:
router = self._l3_plugin.get_router(context, router_id)
except l3_exc.RouterNotFound:
# If the router is gone, the router port is also gone
port_removed = True
if not router.get(l3.EXTERNAL_GW_INFO):
if not router or not router.get(l3.EXTERNAL_GW_INFO):
if port_removed:
self._delete_lrouter_port(context, port_id, router_id,
txn=txn)
@ -1506,12 +1511,15 @@ class OVNClient(object):
cidr = None
for sid in subnet_ids:
subnet = self._plugin.get_subnet(context, sid)
try:
subnet = self._plugin.get_subnet(context, sid)
except n_exc.SubnetNotFound:
continue
if subnet['ip_version'] == 4:
cidr = subnet['cidr']
break
if router and utils.is_snat_enabled(router) and cidr:
if utils.is_snat_enabled(router) and cidr:
self.update_nat_rules(
router, networks=[cidr], enable_snat=False, txn=txn)

View File

@ -23,6 +23,7 @@ from neutron_lib.callbacks import resources
from neutron_lib import constants
from neutron_lib import exceptions as n_exc
from neutron_lib.exceptions import availability_zone as az_exc
from neutron_lib.exceptions import l3 as l3_exc
from neutron_lib.plugins import constants as plugin_constants
from neutron_lib.plugins import directory
from oslo_config import cfg
@ -389,6 +390,23 @@ class TestOVNL3RouterPlugin(test_mech_driver.Ml2PluginV2TestCase):
ovn_const.OVN_NETWORK_NAME_EXT_ID_KEY:
utils.ovn_name(self.fake_network['id'])})
def test_remove_router_interface_router_not_found(self):
router_id = 'router-id'
interface_info = {'port_id': 'router-port-id'}
self.get_port.side_effect = n_exc.PortNotFound(
port_id='router-port-id')
self.get_router.side_effect = l3_exc.RouterNotFound(
router_id='router-id')
self.l3_inst.remove_router_interface(
self.context, router_id, interface_info)
self.get_router.assert_called_once_with(self.context, 'router-id')
self.l3_inst._ovn.lrp_del.assert_called_once_with(
'lrp-router-port-id', 'neutron-router-id', if_exists=True)
self.del_rev_p.assert_called_once_with(
self.context, 'router-port-id', ovn_const.TYPE_ROUTER_PORTS)
@mock.patch('neutron.db.extraroute_db.ExtraRoute_dbonly_mixin.'
'update_router')
@mock.patch('neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb'