Handle creation of Port_Binding with chassis set

When there is a backlog of notifications to be sent, it is possible
that ovsdb-server will merge insert and update notifications. Due
to this, we need to handle the situation where we see a Port_Binding
created with the chassis set.

Closes-Bug: #2017748

Change-Id: Idfae87cf6c60e9e18ede91ea20857cea5322738c
This commit is contained in:
Terry Wilson 2023-12-15 21:00:43 +00:00
parent 2a4dbb63f5
commit a641e8aec0
2 changed files with 19 additions and 6 deletions

View File

@ -158,13 +158,13 @@ class PortBindingChassisCreatedEvent(_PortBindingChassisEvent):
LOG_MSG = 'Port ID %s, datapath %s, OVS port name: %s (event: %s)' LOG_MSG = 'Port ID %s, datapath %s, OVS port name: %s (event: %s)'
def __init__(self, ovn_agent): def __init__(self, ovn_agent):
events = (self.ROW_UPDATE,) events = (self.ROW_CREATE, self.ROW_UPDATE,)
super().__init__(ovn_agent, events) super().__init__(ovn_agent, events)
def match_fn(self, event, row, old): def match_fn(self, event, row, old):
try: try:
return (row.chassis[0].name == self.ovn_agent.chassis and return (row.chassis[0].name == self.ovn_agent.chassis and
not old.chassis) (event == self.ROW_CREATE or not old.chassis))
except (IndexError, AttributeError): except (IndexError, AttributeError):
return False return False

View File

@ -118,6 +118,16 @@ class PortBindingEvent(row_event.RowEvent):
self.agent.resync() self.agent.resync()
class PortBindingCreateWithChassis(PortBindingEvent):
EVENT = PortBindingEvent.ROW_CREATE
def match_fn(self, event, row, old):
self._log_msg = "Port %s in datapath %s bound to our chassis on insert"
if not (super().match_fn(event, row, old) and row.chassis):
return False
return row.chassis[0].name == self.agent.chassis
class PortBindingUpdatedEvent(PortBindingEvent): class PortBindingUpdatedEvent(PortBindingEvent):
EVENT = PortBindingEvent.ROW_UPDATE EVENT = PortBindingEvent.ROW_UPDATE
@ -384,6 +394,7 @@ class MetadataAgent(object):
tables = ('Encap', 'Port_Binding', 'Datapath_Binding', 'SB_Global', tables = ('Encap', 'Port_Binding', 'Datapath_Binding', 'SB_Global',
'Chassis', 'Chassis_Private') 'Chassis', 'Chassis_Private')
events = (PortBindingUpdatedEvent(self), events = (PortBindingUpdatedEvent(self),
PortBindingCreateWithChassis(self),
PortBindingDeletedEvent(self), PortBindingDeletedEvent(self),
SbGlobalUpdateEvent(self), SbGlobalUpdateEvent(self),
ChassisPrivateCreateEvent(self), ChassisPrivateCreateEvent(self),
@ -402,7 +413,8 @@ class MetadataAgent(object):
self._proxy.run() self._proxy.run()
# Do the initial sync. # Do the initial sync.
self.sync() # Provisioning handled by PortBindingCreateWithChassis
self.sync(provision=False)
# Register the agent with its corresponding Chassis # Register the agent with its corresponding Chassis
self.register_metadata_agent() self.register_metadata_agent()
@ -453,7 +465,7 @@ class MetadataAgent(object):
return set(p.datapath for p in self._vif_ports(ports)) return set(p.datapath for p in self._vif_ports(ports))
@_sync_lock @_sync_lock
def sync(self): def sync(self, provision=True):
"""Agent sync. """Agent sync.
This function will make sure that all networks with ports in our This function will make sure that all networks with ports in our
@ -480,8 +492,9 @@ class MetadataAgent(object):
# resync all network namespaces based on the associated datapaths, # resync all network namespaces based on the associated datapaths,
# even those that are already running. This is to make sure # even those that are already running. This is to make sure
# everything within each namespace is up to date. # everything within each namespace is up to date.
for datapath in net_datapaths: if provision:
self.provision_datapath(datapath) for datapath in net_datapaths:
self.provision_datapath(datapath)
@staticmethod @staticmethod
def _get_veth_name(datapath): def _get_veth_name(datapath):