[OVN] Bump revision number after update_virtual_port_host

This patch adds bump revision after updating the hostname
of a virtual port (more specifically its associated port).
This way there is no misalignment between the revision number
of Neutron DB and OVN DB.

It also avoids the unnecessary execution of the maintenance
task to simply match the revision_number.

Closes-Bug: #2069046
Change-Id: I2734984f10341ab97ebbdee11389d214bb1150f3
(cherry picked from commit f210a90479)
This commit is contained in:
Fernando Royo 2024-06-11 14:22:18 +02:00
parent 5b61b842ad
commit 8d4eeee135
2 changed files with 38 additions and 3 deletions

View File

@ -1077,9 +1077,11 @@ class OVNMechanismDriver(api.MechanismDriver):
hostname = '' hostname = ''
# Updates neutron database with hostname for virtual port # Updates neutron database with hostname for virtual port
self._plugin.update_virtual_port_host(n_context.get_admin_context(), context = n_context.get_admin_context()
port_id, hostname) self._plugin.update_virtual_port_host(context, port_id, hostname)
db_port = self._plugin.get_port(context, port_id)
check_rev_cmd = self.nb_ovn.check_revision_number(
port_id, db_port, ovn_const.TYPE_PORTS)
# Updates OVN NB database with hostname for lsp virtual port # Updates OVN NB database with hostname for lsp virtual port
with self.nb_ovn.transaction(check_error=True) as txn: with self.nb_ovn.transaction(check_error=True) as txn:
ext_ids = ('external_ids', ext_ids = ('external_ids',
@ -1087,6 +1089,10 @@ class OVNMechanismDriver(api.MechanismDriver):
txn.add( txn.add(
self.nb_ovn.db_set( self.nb_ovn.db_set(
'Logical_Switch_Port', port_id, ext_ids)) 'Logical_Switch_Port', port_id, ext_ids))
txn.add(check_rev_cmd)
if check_rev_cmd.result == ovn_const.TXN_COMMITTED:
ovn_revision_numbers_db.bump_revision(context, db_port,
ovn_const.TYPE_PORTS)
def get_workers(self): def get_workers(self):
"""Get any worker instances that should have their own process """Get any worker instances that should have their own process

View File

@ -447,6 +447,30 @@ class TestNBDbMonitor(base.TestOVNFunctionalBase):
# Check that both neutron and ovn are the same as given host_id # Check that both neutron and ovn are the same as given host_id
return port[portbindings.HOST_ID] == host_id == ovn_host_id return port[portbindings.HOST_ID] == host_id == ovn_host_id
def _check_port_and_port_binding_revision_number(self, port_id):
def is_port_and_port_binding_same_revision_number(port_id):
# This function checks if given port matches the revision_number
# in the neutron DB as well as in the OVN DB for the port_binding
core_plugin = directory.get_plugin()
# Get port from neutron DB
port = core_plugin.get_ports(
self.context, filters={'id': [port_id]})[0]
# Get port binding from OVN DB
bp = self._find_port_binding(port_id)
ovn_port_binding_revision_number = bp.external_ids.get(
ovn_const.OVN_REV_NUM_EXT_ID_KEY, ovn_const.INITIAL_REV_NUM)
# Check that both neutron and ovn are the same as given host_id
return port['revision_number'] == int(
ovn_port_binding_revision_number)
check = functools.partial(
is_port_and_port_binding_same_revision_number, port_id)
n_utils.wait_until_true(check, timeout=10)
def test_virtual_port_host_update_upon_failover(self): def test_virtual_port_host_update_upon_failover(self):
# NOTE: we can't simulate traffic, but we can simulate the event that # NOTE: we can't simulate traffic, but we can simulate the event that
# would've been triggered by OVN, which is what we do. # would've been triggered by OVN, which is what we do.
@ -466,6 +490,7 @@ class TestNBDbMonitor(base.TestOVNFunctionalBase):
vip_address = vip['fixed_ips'][0]['ip_address'] vip_address = vip['fixed_ips'][0]['ip_address']
allowed_address_pairs = [{'ip_address': vip_address}] allowed_address_pairs = [{'ip_address': vip_address}]
self._check_port_binding_type(vip['id'], '') self._check_port_binding_type(vip['id'], '')
self._check_port_and_port_binding_revision_number(vip['id'])
# 3) Create two ports with the allowed address pairs set. # 3) Create two ports with the allowed address pairs set.
hosts = ('ovs-host1', second_chassis_name) hosts = ('ovs-host1', second_chassis_name)
@ -482,6 +507,7 @@ class TestNBDbMonitor(base.TestOVNFunctionalBase):
# have been assigned to the port binding # have been assigned to the port binding
self._check_port_binding_type(vip['id'], ovn_const.LSP_TYPE_VIRTUAL) self._check_port_binding_type(vip['id'], ovn_const.LSP_TYPE_VIRTUAL)
self._check_port_virtual_parents(vip['id'], ','.join(port_ids)) self._check_port_virtual_parents(vip['id'], ','.join(port_ids))
self._check_port_and_port_binding_revision_number(vip['id'])
# 5) Bind the ports to a host, so a chassis is bound, which is # 5) Bind the ports to a host, so a chassis is bound, which is
# required for the update_virtual_port_host method. Without this # required for the update_virtual_port_host method. Without this
@ -489,11 +515,13 @@ class TestNBDbMonitor(base.TestOVNFunctionalBase):
self._test_port_binding_and_status(ports[0]['id'], 'bind', 'ACTIVE') self._test_port_binding_and_status(ports[0]['id'], 'bind', 'ACTIVE')
self.chassis = second_chassis self.chassis = second_chassis
self._test_port_binding_and_status(ports[1]['id'], 'bind', 'ACTIVE') self._test_port_binding_and_status(ports[1]['id'], 'bind', 'ACTIVE')
self._check_port_and_port_binding_revision_number(vip['id'])
# 6) For both ports, bind vip on parent and check hostname in DBs # 6) For both ports, bind vip on parent and check hostname in DBs
for idx in range(len(ports)): for idx in range(len(ports)):
# Set port binding to the first port, and update the chassis # Set port binding to the first port, and update the chassis
self._set_port_binding_virtual_parent(vip['id'], ports[idx]['id']) self._set_port_binding_virtual_parent(vip['id'], ports[idx]['id'])
self._check_port_and_port_binding_revision_number(vip['id'])
# Check if the host_id has been updated in OVN and DB # Check if the host_id has been updated in OVN and DB
# by the event that eventually calls for method # by the event that eventually calls for method
@ -501,6 +529,7 @@ class TestNBDbMonitor(base.TestOVNFunctionalBase):
n_utils.wait_until_true( n_utils.wait_until_true(
lambda: self._check_port_host_set(vip['id'], hosts[idx]), lambda: self._check_port_host_set(vip['id'], hosts[idx]),
timeout=10) timeout=10)
self._check_port_and_port_binding_revision_number(vip['id'])
class TestNBDbMonitorOverTcp(TestNBDbMonitor): class TestNBDbMonitorOverTcp(TestNBDbMonitor):