|
| 1 | +Description: Prevent ghost OVN agents from orphaned Chassis_Private rows |
| 2 | + When a Chassis row is deleted but its Chassis_Private persists (e.g. |
| 3 | + ungraceful ovn-controller shutdown in containers), the ROW_CREATE path |
| 4 | + in ChassisAgentWriteEvent and ChassisOVNAgentWriteEvent would add an |
| 5 | + agent to the cache with the DeletedChassis sentinel hostname |
| 6 | + '("Chassis" register deleted)'. This patch gates ROW_CREATE on |
| 7 | + row.chassis being non-empty, consistent with the ROW_UPDATE path and |
| 8 | + the AgentCache.populate() method which already skips such rows. |
| 9 | +Author: Nicholas Kuechler |
| 10 | + |
| 11 | +--- a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovsdb_monitor.py |
| 12 | ++++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovsdb_monitor.py |
| 13 | +@@ -359,13 +359,17 @@ |
| 14 | + class ChassisAgentWriteEvent(ChassisAgentEvent): |
| 15 | + events = (BaseEvent.ROW_CREATE, BaseEvent.ROW_UPDATE) |
| 16 | + |
| 17 | + def match_fn(self, event, row, old=None): |
| 18 | + # On updates to Chassis_Private because the Chassis has been deleted, |
| 19 | + # don't update the AgentCache. We use chassis_private.chassis to return |
| 20 | +- # data about the agent. |
| 21 | +- return (event == self.ROW_CREATE or |
| 22 | +- (hasattr(old, 'nb_cfg') and row.chassis)) |
| 23 | ++ # data about the agent. Require a valid chassis reference for all |
| 24 | ++ # events including ROW_CREATE: an orphaned Chassis_Private (where the |
| 25 | ++ # Chassis row was already deleted) must not create a ghost agent entry. |
| 26 | ++ if not row.chassis: |
| 27 | ++ return False |
| 28 | ++ return (event == self.ROW_CREATE or |
| 29 | ++ (hasattr(old, 'nb_cfg') and row.chassis)) |
| 30 | + |
| 31 | + def run(self, event, row, old): |
| 32 | + n_agent.AgentCache().update(ovn_const.OVN_CONTROLLER_AGENT, row, |
| 33 | + clear_down=event == self.ROW_CREATE) |
| 34 | +@@ -427,14 +431,15 @@ |
| 35 | + def match_fn(self, event, row, old=None): |
| 36 | + if not self.agent_id(row): |
| 37 | + # Don't create a cached object with an agent_id of 'None' |
| 38 | + return False |
| 39 | +- if event == self.ROW_CREATE: |
| 40 | +- return True |
| 41 | + |
| 42 | +- # On updates to Chassis_Private because the Chassis has been |
| 43 | +- # deleted, don't update the AgentCache. We use |
| 44 | +- # chassis_private.chassis to return data about the agent. |
| 45 | ++ # Require a valid chassis reference for all events including |
| 46 | ++ # ROW_CREATE: an orphaned Chassis_Private (where the Chassis row |
| 47 | ++ # was already deleted) must not create a ghost agent entry. |
| 48 | + if not getattr(row, 'chassis', None): |
| 49 | + return False |
| 50 | + |
| 51 | ++ if event == self.ROW_CREATE: |
| 52 | ++ return True |
| 53 | ++ |
| 54 | + # Check if both rows have external_ids before comparing nb_cfg |
| 55 | + if not (hasattr(old, 'external_ids') and row.external_ids): |
| 56 | + return False |
0 commit comments