[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>
This commit is contained in:
Lucas Alvares Gomes 2021-02-03 14:00:13 +00:00
parent cbd72e2f48
commit b618d98541
3 changed files with 55 additions and 1 deletions

View File

@ -824,7 +824,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

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

View File

@ -807,3 +807,51 @@ class TestNBImplIdlOvn(TestDBImplIdlOvn):
lb_row = self._find_ovsdb_fake_row(self.lb_table, 'name', 'lb_2')
lb = self.nb_ovn_idl.get_floatingip_in_nat_or_lb(fip_id)
self.assertEqual(lb['_uuid'], lb_row.uuid)
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)