[OVN] Fix RowNotFound exception while waiting for metadata networks

In the set_port_status_up() the OVN driver waits for the metadata to be
provisioned (15 seconds) [0] prior to sending the event to Nova notifying
that the provisioning of the port is done (network-vif-plugged). But
there could be a race condition while trying to get that information
which results in a RowNotFound being raise in the waiting loop.

Once that happens, the exception is bubbled up and the OVN driver end up
not sending the event to Nova and the instance will fail to deploy (it
will be stuck in BUILD state until it times out).

This patch changes the logic of the method looking for the metadata
network information to not raise RowNotFound so that the waiting loop
can iteract again [0] until the information is available.

[0]
cbd72e2f48/neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py (L1124)

Change-Id: I3c106ace74b5c6e4ed0cb7e827baf5d6595ec5d0
Closes-Bug: #1914394
Signed-off-by: Lucas Alvares Gomes <lucasagomes@gmail.com>
(cherry picked from commit b618d98541)
(cherry picked from commit cbf3fe098b)
Conflicts cleanly resolved by removing not relevant code added before
the addittion of the TestSBImplIdlOvn class.  Also added missing
ovsdbapp.backend import:
    neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_impl_idl_ovn.py
This commit is contained in:
Lucas Alvares Gomes 2021-02-03 14:00:13 +00:00 committed by Frode Nordahl
parent 7bca2cc526
commit 7699feb4a6
No known key found for this signature in database
GPG Key ID: 6A5D59A3BA48373F
3 changed files with 57 additions and 1 deletions

View File

@ -849,7 +849,12 @@ class OvsdbSbOvnIdl(sb_impl_idl.OvnSbApiIdlImpl, Backend):
def get_chassis_metadata_networks(self, chassis_name):
"""Return a list with the metadata networks the chassis is hosting."""
chassis = self.lookup('Chassis', chassis_name)
try:
chassis = self.lookup('Chassis', chassis_name)
except idlutils.RowNotFound:
LOG.warning("Couldn't find Chassis named %s in OVN while looking "
"for metadata networks", chassis_name)
return []
proxy_networks = chassis.external_ids.get(
'neutron-metadata-proxy-networks', None)
return proxy_networks.split(',') if proxy_networks else []

View File

@ -410,6 +410,7 @@ class FakeOvsdbTable(FakeResource):
ovsdb_table_attrs = {
'rows': {},
'columns': {},
'indexes': [],
}
# Overwrite default attributes.

View File

@ -17,6 +17,8 @@ import uuid
import mock
from ovsdbapp.backend import ovs_idl
from neutron.common.ovn import constants as ovn_const
from neutron.common.ovn import utils
from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb import impl_idl_ovn
@ -758,3 +760,51 @@ class TestNBImplIdlOvn(TestDBImplIdlOvn):
self._tables.pop('Port_Group', None)
port_groups = self.nb_ovn_idl.get_port_groups()
self.assertEqual({}, port_groups)
class TestSBImplIdlOvn(TestDBImplIdlOvn):
fake_set = {
'chassis': [
{'name': 'fake-chassis',
'external_ids': {'neutron-metadata-proxy-networks': 'fake-id'}}],
}
def setUp(self):
super(TestSBImplIdlOvn, self).setUp()
self.chassis_table = fakes.FakeOvsdbTable.create_one_ovsdb_table()
self._tables = {}
self._tables['Chassis'] = self.chassis_table
with mock.patch.object(impl_idl_ovn.OvsdbSbOvnIdl, 'from_worker',
return_value=mock.Mock()):
with mock.patch.object(ovs_idl.Backend, 'autocreate_indices',
create=True):
impl_idl_ovn.OvsdbSbOvnIdl.ovsdb_connection = None
self.sb_ovn_idl = impl_idl_ovn.OvsdbSbOvnIdl(mock.MagicMock())
self.sb_ovn_idl.idl.tables = self._tables
def _load_sb_db(self):
fake_chassis = TestSBImplIdlOvn.fake_set['chassis']
self._load_ovsdb_fake_rows(self.chassis_table, fake_chassis)
@mock.patch.object(impl_idl_ovn.LOG, 'warning')
def test_get_chassis_metadata_networks_chassis_empty(self, mock_log):
chassis_name = 'fake-chassis'
result = self.sb_ovn_idl.get_chassis_metadata_networks(chassis_name)
mock_log.assert_called_once_with(
"Couldn't find Chassis named %s in OVN while looking "
"for metadata networks", chassis_name)
self.assertEqual([], result)
@mock.patch.object(impl_idl_ovn.LOG, 'warning')
def test_get_chassis_metadata_networks(self, mock_log):
chassis_name = 'fake-chassis'
self._load_sb_db()
result = self.sb_ovn_idl.get_chassis_metadata_networks(chassis_name)
self.assertFalse(mock_log.called)
self.assertEqual(['fake-id'], result)