[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:
parent
e9a75a379e
commit
36b8c684b1
|
@ -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 constants as const
|
||||||
from neutron_lib import context as n_context
|
from neutron_lib import context as n_context
|
||||||
from neutron_lib import exceptions as n_exc
|
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 constants as plugin_constants
|
||||||
from neutron_lib.plugins import directory
|
from neutron_lib.plugins import directory
|
||||||
from neutron_lib.plugins import utils as p_utils
|
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(
|
router_id = router_id or ovn_port.external_ids.get(
|
||||||
ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY)
|
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_id = port.get('device_id')
|
||||||
|
|
||||||
router = None
|
router = None
|
||||||
if router_id:
|
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:
|
if port_removed:
|
||||||
self._delete_lrouter_port(context, port_id, router_id,
|
self._delete_lrouter_port(context, port_id, router_id,
|
||||||
txn=txn)
|
txn=txn)
|
||||||
|
@ -1506,12 +1511,15 @@ class OVNClient(object):
|
||||||
|
|
||||||
cidr = None
|
cidr = None
|
||||||
for sid in subnet_ids:
|
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:
|
if subnet['ip_version'] == 4:
|
||||||
cidr = subnet['cidr']
|
cidr = subnet['cidr']
|
||||||
break
|
break
|
||||||
|
|
||||||
if router and utils.is_snat_enabled(router) and cidr:
|
if utils.is_snat_enabled(router) and cidr:
|
||||||
self.update_nat_rules(
|
self.update_nat_rules(
|
||||||
router, networks=[cidr], enable_snat=False, txn=txn)
|
router, networks=[cidr], enable_snat=False, txn=txn)
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ from neutron_lib.callbacks import resources
|
||||||
from neutron_lib import constants
|
from neutron_lib import constants
|
||||||
from neutron_lib import exceptions as n_exc
|
from neutron_lib import exceptions as n_exc
|
||||||
from neutron_lib.exceptions import availability_zone as az_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 constants as plugin_constants
|
||||||
from neutron_lib.plugins import directory
|
from neutron_lib.plugins import directory
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
@ -389,6 +390,23 @@ class TestOVNL3RouterPlugin(test_mech_driver.Ml2PluginV2TestCase):
|
||||||
ovn_const.OVN_NETWORK_NAME_EXT_ID_KEY:
|
ovn_const.OVN_NETWORK_NAME_EXT_ID_KEY:
|
||||||
utils.ovn_name(self.fake_network['id'])})
|
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.'
|
@mock.patch('neutron.db.extraroute_db.ExtraRoute_dbonly_mixin.'
|
||||||
'update_router')
|
'update_router')
|
||||||
@mock.patch('neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb'
|
@mock.patch('neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb'
|
||||||
|
|
Loading…
Reference in New Issue