Fix live migrations and possibly also VIP failovers

When a live migration happens, another flow is happening,
so we need to take this into consideration.

Change-Id: Ib27bbc95a0853f32354f743dcec2bdb4bb797097
Closes-Bug: #2082085
This commit is contained in:
Michel Nederlof 2024-09-26 12:37:56 +00:00
parent f503911227
commit 59ad44aca5
2 changed files with 35 additions and 2 deletions

View File

@ -174,6 +174,15 @@ class LogicalSwitchPortFIPCreateEvent(base_watcher.LSPChassisEvent):
So for migration flow we are only interested in event 7. So for migration flow we are only interested in event 7.
Otherwise the floating ip would be added upon event 2, deleted with Otherwise the floating ip would be added upon event 2, deleted with
event 3 and re-added with event 7. event 3 and re-added with event 7.
For the live migration of a VIP (floating ip attached to virtual port),
the following events happen:
1. port is set down (by ovn-controller on source host)
2. external_ids update (neutron:host_id is removed)
3. port is set up (by ovn-controller on dest host)
4. external_ids update (neutron:host_id is added)
In this case we only need to catch event 4.
''' '''
def __init__(self, bgp_agent): def __init__(self, bgp_agent):
events = (self.ROW_UPDATE,) events = (self.ROW_UPDATE,)
@ -210,8 +219,11 @@ class LogicalSwitchPortFIPCreateEvent(base_watcher.LSPChassisEvent):
# to something else) we need to process this update. # to something else) we need to process this update.
# If nothing else changed in the external_ids, we do not care # If nothing else changed in the external_ids, we do not care
# as it would just cause unnecessary events during migrations. # as it would just cause unnecessary events during migrations.
# Only case we are interested in is if the chassis has changed
# with this event.
# (see the docstring of this class) # (see the docstring of this class)
return False old_chassis = self._get_chassis(old)
return old_chassis != current_chassis
# Check if the current port_fip has not been exposed yet # Check if the current port_fip has not been exposed yet
return not self.agent.is_ip_exposed( return not self.agent.is_ip_exposed(

View File

@ -310,9 +310,30 @@ class TestLogicalSwitchPortFIPCreateEvent(test_base.TestCase):
constants.OVN_HOST_ID_EXT_ID_KEY: self.chassis, constants.OVN_HOST_ID_EXT_ID_KEY: self.chassis,
constants.OVN_FIP_EXT_ID_KEY: 'fip-ip'}, constants.OVN_FIP_EXT_ID_KEY: 'fip-ip'},
up=[True]) up=[True])
old = utils.create_row(external_ids={}, up=[True]) old = utils.create_row(external_ids={
constants.OVN_FIP_EXT_ID_KEY: 'fip-ip',
}, up=[True])
self.assertTrue(self.event.match_fn(mock.Mock(), row, old)) self.assertTrue(self.event.match_fn(mock.Mock(), row, old))
def test_match_fn_no_change_external_ids(self):
row = utils.create_row(
type=constants.OVN_VM_VIF_PORT_TYPE,
addresses=['mac 192.168.0.1'],
external_ids={
constants.OVN_HOST_ID_EXT_ID_KEY: self.chassis,
constants.OVN_FIP_EXT_ID_KEY: 'fip-ip',
'neutron:revision_number': '416',
},
up=[True])
old = utils.create_row(
external_ids={
constants.OVN_FIP_EXT_ID_KEY: 'fip-ip',
constants.OVN_HOST_ID_EXT_ID_KEY: self.chassis,
'neutron:revision_number': '417',
},
up=[True])
self.assertFalse(self.event.match_fn(mock.Mock(), row, old))
def test_match_fn_status_change(self): def test_match_fn_status_change(self):
row = utils.create_row(type=constants.OVN_VM_VIF_PORT_TYPE, row = utils.create_row(type=constants.OVN_VM_VIF_PORT_TYPE,
addresses=['mac 192.168.0.1'], addresses=['mac 192.168.0.1'],