From 2396d4078edb7337ceedbc2f02f811370ee639b9 Mon Sep 17 00:00:00 2001 From: Lucas Alvares Gomes Date: Tue, 23 Mar 2021 16:29:46 +0000 Subject: [PATCH] [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 (cherry picked from commit 36b8c684b1c42a0733d0820bcd2e1fe217f23797) --- .../ovn/mech_driver/ovsdb/ovn_client.py | 18 +++++++++++++----- .../tests/unit/services/ovn_l3/test_plugin.py | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py index 4998eba6c00..e1cfe583509 100644 --- a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py +++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py @@ -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 @@ -1507,14 +1508,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) @@ -1529,12 +1534,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) diff --git a/neutron/tests/unit/services/ovn_l3/test_plugin.py b/neutron/tests/unit/services/ovn_l3/test_plugin.py index 9d061e82de1..064925c44f5 100644 --- a/neutron/tests/unit/services/ovn_l3/test_plugin.py +++ b/neutron/tests/unit/services/ovn_l3/test_plugin.py @@ -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 @@ -387,6 +388,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'