From c3d1beb4fc42a2747e8eda0e06ddc1c1f3178075 Mon Sep 17 00:00:00 2001 From: Michel Nederlof Date: Thu, 26 Sep 2024 12:37:56 +0000 Subject: [PATCH] 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 (cherry picked from commit 59ad44aca5fac502010914c547f40e7b0f201c29) --- .../openstack/watchers/nb_bgp_watcher.py | 14 ++++++++++- .../openstack/watchers/test_nb_bgp_watcher.py | 23 ++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/ovn_bgp_agent/drivers/openstack/watchers/nb_bgp_watcher.py b/ovn_bgp_agent/drivers/openstack/watchers/nb_bgp_watcher.py index e3889fe5..a2638cc2 100644 --- a/ovn_bgp_agent/drivers/openstack/watchers/nb_bgp_watcher.py +++ b/ovn_bgp_agent/drivers/openstack/watchers/nb_bgp_watcher.py @@ -168,6 +168,15 @@ class LogicalSwitchPortFIPCreateEvent(base_watcher.LSPChassisEvent): So for migration flow we are only interested in event 7. Otherwise the floating ip would be added upon event 2, deleted with 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): events = (self.ROW_UPDATE,) @@ -204,8 +213,11 @@ class LogicalSwitchPortFIPCreateEvent(base_watcher.LSPChassisEvent): # to something else) we need to process this update. # If nothing else changed in the external_ids, we do not care # 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) - return False + old_chassis = self._get_chassis(old) + return old_chassis != current_chassis # Check if the current port_fip has not been exposed yet return not self.agent.is_ip_exposed(self._get_network(row), diff --git a/ovn_bgp_agent/tests/unit/drivers/openstack/watchers/test_nb_bgp_watcher.py b/ovn_bgp_agent/tests/unit/drivers/openstack/watchers/test_nb_bgp_watcher.py index 82c204aa..5fc2578f 100644 --- a/ovn_bgp_agent/tests/unit/drivers/openstack/watchers/test_nb_bgp_watcher.py +++ b/ovn_bgp_agent/tests/unit/drivers/openstack/watchers/test_nb_bgp_watcher.py @@ -310,9 +310,30 @@ class TestLogicalSwitchPortFIPCreateEvent(test_base.TestCase): constants.OVN_HOST_ID_EXT_ID_KEY: self.chassis, constants.OVN_FIP_EXT_ID_KEY: 'fip-ip'}, 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)) + 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): row = utils.create_row(type=constants.OVN_VM_VIF_PORT_TYPE, addresses=['mac 192.168.0.1'],