[OVN] Handle RouterNotFound exception in set_gateway_mtu
When handling multiple router update/delete petitions, if they are executed at the same time, there is a chance that the set_gateway_mtu tries to update a no-longer-existing router, triggering a RouterNotFound error from the _get_router_ports function. Now, if there is not a router, the _get_router_ports function will return an empty list instead of raising the error. Closes-Bug: #1961967 Signed-off-by: Elvira García <egarciar@redhat.com> Change-Id: Ic54214ca4965274cd58c1d3a278d8f3ffcda0a64
This commit is contained in:
parent
6613d40fcb
commit
b2421b01e5
neutron
@ -1242,6 +1242,8 @@ class OVNClient(object):
|
|||||||
self._transaction(commands, txn=txn)
|
self._transaction(commands, txn=txn)
|
||||||
|
|
||||||
def _get_router_ports(self, context, router_id, get_gw_port=False):
|
def _get_router_ports(self, context, router_id, get_gw_port=False):
|
||||||
|
# _get_router() will raise a RouterNotFound error if there's no router
|
||||||
|
# with the router_id
|
||||||
router_db = self._l3_plugin._get_router(context, router_id)
|
router_db = self._l3_plugin._get_router(context, router_id)
|
||||||
if get_gw_port:
|
if get_gw_port:
|
||||||
return [p.port for p in router_db.attached_ports]
|
return [p.port for p in router_db.attached_ports]
|
||||||
@ -1489,15 +1491,18 @@ class OVNClient(object):
|
|||||||
is_gw_port = const.DEVICE_OWNER_ROUTER_GW == port.get(
|
is_gw_port = const.DEVICE_OWNER_ROUTER_GW == port.get(
|
||||||
'device_owner')
|
'device_owner')
|
||||||
if is_gw_port and ovn_conf.is_ovn_emit_need_to_frag_enabled():
|
if is_gw_port and ovn_conf.is_ovn_emit_need_to_frag_enabled():
|
||||||
network_ids = set([port['network_id'] for port in
|
try:
|
||||||
self._get_router_ports(admin_context,
|
network_ids = set([port['network_id'] for port in
|
||||||
port['device_id'])])
|
self._get_router_ports(admin_context, port['device_id'])])
|
||||||
for net in self._plugin.get_networks(admin_context,
|
for net in self._plugin.get_networks(admin_context,
|
||||||
filters={'id': network_ids}):
|
filters={'id': network_ids}):
|
||||||
if net['mtu'] > network['mtu']:
|
if net['mtu'] > network['mtu']:
|
||||||
options[ovn_const.OVN_ROUTER_PORT_GW_MTU_OPTION] = str(
|
options[ovn_const.OVN_ROUTER_PORT_GW_MTU_OPTION] = str(
|
||||||
network['mtu'])
|
network['mtu'])
|
||||||
break
|
break
|
||||||
|
except l3_exc.RouterNotFound:
|
||||||
|
# Don't add any mtu info if the router no longer exists
|
||||||
|
pass
|
||||||
return options
|
return options
|
||||||
|
|
||||||
def _create_lrouter_port(self, context, router, port, txn=None):
|
def _create_lrouter_port(self, context, router, port, txn=None):
|
||||||
|
@ -1620,6 +1620,52 @@ class TestOVNL3RouterPlugin(test_mech_driver.Ml2PluginV2TestCase):
|
|||||||
mock.ANY, self.fake_router_port,
|
mock.ANY, self.fake_router_port,
|
||||||
ovn_const.TYPE_ROUTER_PORTS)
|
ovn_const.TYPE_ROUTER_PORTS)
|
||||||
|
|
||||||
|
@mock.patch('neutron.plugins.ml2.plugin.Ml2Plugin.get_network')
|
||||||
|
@mock.patch('neutron.plugins.ml2.plugin.Ml2Plugin.get_networks')
|
||||||
|
@mock.patch('neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb.'
|
||||||
|
'ovn_client.OVNClient._get_router_ports')
|
||||||
|
@mock.patch('neutron.db.l3_db.L3_NAT_dbonly_mixin.add_router_interface')
|
||||||
|
def test_add_router_interface_need_to_frag_enabled_then_remove(
|
||||||
|
self, ari, grps, gns, gn):
|
||||||
|
config.cfg.CONF.set_override(
|
||||||
|
'ovn_emit_need_to_frag', True, group='ovn')
|
||||||
|
router_id = 'router-id'
|
||||||
|
interface_info = {'port_id': 'router-port-id',
|
||||||
|
'network_id': 'priv-net'}
|
||||||
|
ari.return_value = self.fake_router_interface_info
|
||||||
|
# If we remove the router halfway the return value of
|
||||||
|
# _get_routers_ports will be []
|
||||||
|
grps.side_effect = l3_exc.RouterNotFound(router_id=router_id)
|
||||||
|
self.get_router.return_value = self.fake_router_with_ext_gw
|
||||||
|
network_attrs = {'id': 'prov-net', 'mtu': 1200}
|
||||||
|
prov_net = fake_resources.FakeNetwork.create_one_network(
|
||||||
|
attrs=network_attrs).info()
|
||||||
|
self.fake_router_port['device_owner'] = (
|
||||||
|
constants.DEVICE_OWNER_ROUTER_GW)
|
||||||
|
gn.return_value = prov_net
|
||||||
|
gns.return_value = [self.fake_network]
|
||||||
|
|
||||||
|
self.l3_inst.add_router_interface(self.context, router_id,
|
||||||
|
interface_info)
|
||||||
|
|
||||||
|
# Make sure that the "gateway_mtu" option was set to the router port
|
||||||
|
fake_router_port_assert = self.fake_router_port_assert
|
||||||
|
fake_router_port_assert['gateway_chassis'] = mock.ANY
|
||||||
|
fake_router_port_assert['options'] = {}
|
||||||
|
|
||||||
|
self.l3_inst._nb_ovn.add_lrouter_port.assert_called_once_with(
|
||||||
|
**fake_router_port_assert)
|
||||||
|
# Since if_exists = True it will safely return
|
||||||
|
self.l3_inst._nb_ovn.lrp_set_options(
|
||||||
|
name='lrp-router-port-id', if_exists=True,
|
||||||
|
options=fake_router_port_assert)
|
||||||
|
# If no if_exists is provided, it is defaulted to true, so this
|
||||||
|
# operation is safe.
|
||||||
|
self.l3_inst._nb_ovn.set_lrouter_port_in_lswitch_port.\
|
||||||
|
assert_called_once_with(
|
||||||
|
'router-port-id', 'lrp-router-port-id', is_gw_port=True,
|
||||||
|
lsp_address=ovn_const.DEFAULT_ADDR_FOR_LSP_WITH_PEER)
|
||||||
|
|
||||||
def _test_get_router_availability_zones(self, azs, expected):
|
def _test_get_router_availability_zones(self, azs, expected):
|
||||||
lr = fake_resources.FakeOvsdbRow.create_one_ovsdb_row(
|
lr = fake_resources.FakeOvsdbRow.create_one_ovsdb_row(
|
||||||
attrs={'id': 'fake-router', 'external_ids': {
|
attrs={'id': 'fake-router', 'external_ids': {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user