From e6201b35bc0d83597e527cb3c3a4d5b800d85044 Mon Sep 17 00:00:00 2001 From: Fernando Royo Date: Tue, 16 Jan 2024 20:12:51 +0100 Subject: [PATCH] Fix OVN LB Delete events for NB driver When deleting an OVN LB with an attached FIP, the FIP is not withdrawn from the BGP interface where it was exposed. This patch corrects the behavior in accordance with the events received from the OVN NB DB, taking as main source the vips field provided in events to detect if added/removed entries. Closes-Bug: #2049535 Change-Id: If0bca4a39a857364582804b64140f9a36bfc422a --- .../drivers/openstack/utils/driver_utils.py | 13 ++ .../openstack/watchers/base_watcher.py | 30 ++- .../openstack/watchers/nb_bgp_watcher.py | 101 +++++----- .../openstack/watchers/test_base_watcher.py | 34 +++- .../openstack/watchers/test_nb_bgp_watcher.py | 187 +++++++++++------- 5 files changed, 245 insertions(+), 120 deletions(-) diff --git a/ovn_bgp_agent/drivers/openstack/utils/driver_utils.py b/ovn_bgp_agent/drivers/openstack/utils/driver_utils.py index e020f9ff..8e5cd756 100644 --- a/ovn_bgp_agent/drivers/openstack/utils/driver_utils.py +++ b/ovn_bgp_agent/drivers/openstack/utils/driver_utils.py @@ -59,3 +59,16 @@ def get_prefixes_from_ips(ips: 'list[str]') -> 'list[str]': return ['/'.join([ipaddress.ip_network(ip, strict=False)[0].compressed, ip.split('/')[-1]]) for ip in ips] + + +def remove_port_from_ip(ip_address): + last_colon_index = ip_address.rfind(':') + # no port + if last_colon_index == -1: + return ip_address + # check if right side from index is a digit, in positive case remove it. + # For IPv6 it will come on format [ipv6]:port, so will also remove + # correctly just only the port + if ip_address[last_colon_index + 1:].isdigit(): + return ip_address[:last_colon_index] + return ip_address diff --git a/ovn_bgp_agent/drivers/openstack/watchers/base_watcher.py b/ovn_bgp_agent/drivers/openstack/watchers/base_watcher.py index f1864e74..10e05de9 100644 --- a/ovn_bgp_agent/drivers/openstack/watchers/base_watcher.py +++ b/ovn_bgp_agent/drivers/openstack/watchers/base_watcher.py @@ -16,6 +16,7 @@ from oslo_log import log as logging from ovsdbapp.backend.ovs_idl import event as row_event from ovn_bgp_agent import constants +from ovn_bgp_agent.drivers.openstack.utils import driver_utils LOG = logging.getLogger(__name__) @@ -56,11 +57,32 @@ class OVNLBEvent(Event): except (AttributeError, KeyError): return - def _get_vip_fip(self, row): + def _get_ip_from_vips(self, row): + return [driver_utils.remove_port_from_ip(ipport) + for ipport in getattr(row, 'vips', {}).keys()] + + def _get_diff_ip_from_vips(self, new, old): + """Returns a list of IPs that are present in 'new' but not in 'old' + + Note: As LB VIP contains a port (e.g., '192.168.1.1:80'), the port part + is removed before comparison. + """ + return list(set(self._get_ip_from_vips(new)) - + set(self._get_ip_from_vips(old))) + + def _is_vip_or_fip(self, row, ip, key): try: - return row.external_ids[constants.OVN_LB_VIP_FIP_EXT_ID_KEY] - except (AttributeError, KeyError): - return + return ip == row.external_ids.get(key) + except AttributeError: + pass + + def _is_vip(self, row, ip): + return self._is_vip_or_fip(row, ip, constants.OVN_LB_VIP_IP_EXT_ID_KEY) + + def _is_fip(self, row, ip): + return self._is_vip_or_fip(row, + ip, + constants.OVN_LB_VIP_FIP_EXT_ID_KEY) class LSPChassisEvent(Event): 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 2f1c3851..59010031 100644 --- a/ovn_bgp_agent/drivers/openstack/watchers/nb_bgp_watcher.py +++ b/ovn_bgp_agent/drivers/openstack/watchers/nb_bgp_watcher.py @@ -632,10 +632,14 @@ class OVNLBCreateEvent(base_watcher.OVNLBEvent): if lb_router not in self.agent.ovn_local_cr_lrps.keys(): return False - # Only expose if there is a modification in the VIPS - # And only expose if it is the first item on VIPs + # Expose if there is a modification in the VIPS, first new item ( + # that could happend with and non existing vips on old event or + # empty one) or additional items because a bigger row.vips is + # including old.vips if hasattr(old, 'vips'): - if not old.vips and row.vips: + if ((not old.vips and row.vips) or + (old.vips != row.vips and + set(old.vips.keys()).issubset(set(row.vips.keys())))): return True if hasattr(old, 'external_ids'): @@ -643,25 +647,28 @@ class OVNLBCreateEvent(base_watcher.OVNLBEvent): old_lb_router = self._get_router(old) if lb_router != old_lb_router: return True - # Also check if there is a vip_fip addition to expose the FIP - vip_fip = self._get_vip_fip(row) - if not vip_fip: - return False - old_vip_fip = self._get_vip_fip(old) - if vip_fip != old_vip_fip: - return True - except (IndexError, AttributeError): + except AttributeError: return False return False def _run(self, event, row, old): - vip_fip = self._get_vip_fip(row) - old_vip_fip = self._get_vip_fip(old) - with _SYNC_STATE_LOCK.read_lock(): - if hasattr(old, 'external_ids') and vip_fip != old_vip_fip: - self.agent.expose_ovn_lb_fip(row) - else: - self.agent.expose_ovn_lb_vip(row) + # vips field grows + diff = self._get_diff_ip_from_vips(row, old) + for ip in diff: + with _SYNC_STATE_LOCK.read_lock(): + if self._is_vip(row, ip): + self.agent.expose_ovn_lb_vip(row) + elif self._is_fip(row, ip): + self.agent.expose_ovn_lb_fip(row) + + # router set ext-gw + # NOTE(froyo): Not needed to check/call to expose_ovn_lb_fip, since up + # to this point this LB could not have been associated with a FIP + # since the subnet did not have access to the public network + if hasattr(old, 'external_ids'): + with _SYNC_STATE_LOCK.read_lock(): + if self._get_router(old) != self._get_router(row): + self.agent.expose_ovn_lb_vip(row) class OVNLBDeleteEvent(base_watcher.OVNLBEvent): @@ -685,9 +692,7 @@ class OVNLBDeleteEvent(base_watcher.OVNLBEvent): # ROW UPDATE EVENT lb_router = self._get_router(row) - old_external_ids = False if hasattr(old, 'external_ids'): - old_external_ids = True old_lb_router = self._get_router(old) if not old_lb_router: return False @@ -697,40 +702,44 @@ class OVNLBDeleteEvent(base_watcher.OVNLBEvent): # Router should not be removed, but if that is the case we # should remove the loadbalancer return True - # Also check if the vip_fip is removed to withdraw the FIP - vip_fip = self._get_vip_fip(row) - old_vip_fip = self._get_vip_fip(old) - if old_vip_fip and old_vip_fip != vip_fip: - return True - # Withdraw IP if VIPs is removed + # Whatever the change removing any field from vips should be manage if hasattr(old, 'vips'): - if old.vips and not row.vips: - if old_external_ids: - old_lb_router = self._get_router(old) - return (old_lb_router in - self.agent.ovn_local_cr_lrps.keys()) - else: - return (lb_router in - self.agent.ovn_local_cr_lrps.keys()) - except (IndexError, AttributeError): + if ((old.vips != row.vips and + set(row.vips.keys()).issubset( + set(old.vips.keys())))): + return True + except AttributeError: return False return False def _run(self, event, row, old): - vip_fip = self._get_vip_fip(row) - old_vip_fip = self._get_vip_fip(old) - with _SYNC_STATE_LOCK.read_lock(): - if event == self.ROW_DELETE: - self.agent.withdraw_ovn_lb_vip(row) - if vip_fip: - self.agent.withdraw_ovn_lb_fip(row) - else: - if not vip_fip and vip_fip != old_vip_fip: + # DELETE event need drop all + if event == self.ROW_DELETE: + diff = self._get_ip_from_vips(row) + for ip in diff: + with _SYNC_STATE_LOCK.read_lock(): + if self._is_vip(row, ip): + self.agent.withdraw_ovn_lb_vip(row) + elif self._is_fip(row, ip): + self.agent.withdraw_ovn_lb_fip(row) + return + + # UPDATE event + # vips field decrease + diff = self._get_diff_ip_from_vips(old, row) + for ip in diff: + with _SYNC_STATE_LOCK.read_lock(): + if self._is_vip(old, ip): + self.agent.withdraw_ovn_lb_vip(old) + elif self._is_fip(old, ip): self.agent.withdraw_ovn_lb_fip(old) - if hasattr(old, 'vips'): - self.agent.withdraw_ovn_lb_vip(row) + # router unset ext-gw + if hasattr(old, 'external_ids'): + with _SYNC_STATE_LOCK.read_lock(): + if self._get_router(old) != self._get_router(row): + self.agent.withdraw_ovn_lb_vip(old) class OVNPFBaseEvent(base_watcher.OVNLBEvent): diff --git a/ovn_bgp_agent/tests/unit/drivers/openstack/watchers/test_base_watcher.py b/ovn_bgp_agent/tests/unit/drivers/openstack/watchers/test_base_watcher.py index 429941a9..955cd921 100644 --- a/ovn_bgp_agent/tests/unit/drivers/openstack/watchers/test_base_watcher.py +++ b/ovn_bgp_agent/tests/unit/drivers/openstack/watchers/test_base_watcher.py @@ -69,12 +69,38 @@ class TestOVNLBEvent(test_base.TestCase): row = utils.create_row(external_ids={}) self.assertEqual(None, self.ovnlb_event._get_router(row)) - def test__get_vip_fip(self): + def test__is_vip(self): row = utils.create_row( - external_ids={constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip'}) - self.assertEqual('fip', self.ovnlb_event._get_vip_fip(row)) + external_ids={constants.OVN_LB_VIP_IP_EXT_ID_KEY: '192.168.1.50', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5'}, + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) + self.assertFalse(self.ovnlb_event._is_vip(row, '172.24.4.5')) + self.assertTrue(self.ovnlb_event._is_vip(row, '192.168.1.50')) row = utils.create_row(external_ids={}) - self.assertEqual(None, self.ovnlb_event._get_vip_fip(row)) + self.assertFalse(self.ovnlb_event._is_vip(row, '172.24.4.5')) + self.assertFalse(self.ovnlb_event._is_vip(row, '192.168.1.50')) + + def test__is_fip(self): + row = utils.create_row( + external_ids={constants.OVN_LB_VIP_IP_EXT_ID_KEY: '192.168.1.50', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5'}, + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) + self.assertTrue(self.ovnlb_event._is_fip(row, '172.24.4.5')) + self.assertFalse(self.ovnlb_event._is_fip(row, '192.168.1.50')) + row = utils.create_row(external_ids={}) + self.assertFalse(self.ovnlb_event._is_fip(row, '172.24.4.5')) + self.assertFalse(self.ovnlb_event._is_fip(row, '192.168.1.50')) + + def test__get_ip_from_vips(self): + row = utils.create_row( + external_ids={constants.OVN_LB_VIP_IP_EXT_ID_KEY: '192.168.1.50', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5'}, + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) + self.assertEqual(self.ovnlb_event._get_ip_from_vips(row), + ['192.168.1.50', '172.24.4.5']) class FakeLSPChassisEvent(base_watcher.LSPChassisEvent): 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 3bc5deae..0166371a 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 @@ -1,4 +1,3 @@ - # Copyright 2023 Red Hat, Inc. # All Rights Reserved. # @@ -1189,9 +1188,10 @@ class TestOVNLBCreateEvent(test_base.TestCase): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, - vips={'vip': 'member', 'fip': 'member'}) + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) old = utils.create_row(vips={}) self.assertTrue(self.event.match_fn(mock.Mock(), row, old)) @@ -1199,9 +1199,10 @@ class TestOVNLBCreateEvent(test_base.TestCase): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, - vips={'vip': 'member', 'fip': 'member'}) + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) old = utils.create_row(external_ids={}) self.assertTrue(self.event.match_fn(mock.Mock(), row, old)) @@ -1209,18 +1210,34 @@ class TestOVNLBCreateEvent(test_base.TestCase): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, - vips={'vip': 'member', 'fip': 'member'}) - old = utils.create_row(external_ids={ - constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1'}) + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) + old = utils.create_row( + external_ids={ + constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1'}, + vips={'192.168.1.50:80': '192.168.1.100:80'}) self.assertTrue(self.event.match_fn(mock.Mock(), row, old)) + def test_match_fn_vips_no_change(self): + row = utils.create_row( + external_ids={ + constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', + constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) + old = utils.create_row( + external_ids={ + constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1'}) + self.assertFalse(self.event.match_fn(mock.Mock(), row, old)) + def test_match_fn_no_vips(self): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, vips={}) self.assertFalse(self.event.match_fn(mock.Mock(), row, mock.Mock())) @@ -1229,18 +1246,19 @@ class TestOVNLBCreateEvent(test_base.TestCase): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router2', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, - vips={'vip': 'member', 'fip': 'member'}) + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) self.assertFalse(self.event.match_fn(mock.Mock(), row, mock.Mock())) def test_run_vip(self): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_IP_EXT_ID_KEY: '192.168.1.50', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, - vips={'vip': 'member', 'fip': 'member'}) + vips={'192.168.1.50:80': '192.168.1.100:80'}) old = utils.create_row(vips={}) self.event.run(None, row, old) @@ -1248,19 +1266,37 @@ class TestOVNLBCreateEvent(test_base.TestCase): self.agent.expose_ovn_lb_vip.assert_called_once_with(row) self.agent.expose_ovn_lb_fip.assert_not_called() + def test_run_vip_and_fip(self): + row = utils.create_row( + external_ids={ + constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', + constants.OVN_LB_VIP_IP_EXT_ID_KEY: '192.168.1.50', + constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) + old = utils.create_row(vips={}) + + self.event.run(None, row, old) + + self.agent.expose_ovn_lb_vip.assert_called_once_with(row) + self.agent.expose_ovn_lb_fip.assert_called_once_with(row) + def test_run_vip_added_router(self): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1', 'other': 'info'}, - vips={'vip': 'member', 'fip': 'member'}) + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) old = utils.create_row( external_ids={ - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', - constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}) - + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', + constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) self.event.run(None, row, old) self.agent.expose_ovn_lb_vip.assert_called_once_with(row) @@ -1270,9 +1306,10 @@ class TestOVNLBCreateEvent(test_base.TestCase): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, - vips={'vip': 'member', 'fip': 'member'}) + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) old = utils.create_row(external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1'}) @@ -1300,10 +1337,12 @@ class TestOVNLBDeleteEvent(test_base.TestCase): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, vips={}) - old = utils.create_row(vips={'vip': 'member', 'fip': 'member'}) + old = utils.create_row( + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) self.assertTrue(self.event.match_fn(mock.Mock(), row, old)) def test_match_fn_delete(self): @@ -1311,9 +1350,10 @@ class TestOVNLBDeleteEvent(test_base.TestCase): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, - vips={'vip': 'member', 'fip': 'member'}) + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) self.assertTrue(self.event.match_fn(event, row, mock.Mock())) def test_match_fn_delete_no_vips(self): @@ -1321,7 +1361,7 @@ class TestOVNLBDeleteEvent(test_base.TestCase): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, vips={}) self.assertFalse(self.event.match_fn(event, row, mock.Mock())) @@ -1331,17 +1371,19 @@ class TestOVNLBDeleteEvent(test_base.TestCase): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router2', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, - vips={'vip': 'member', 'fip': 'member'}) + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) self.assertFalse(self.event.match_fn(event, row, mock.Mock())) def test_match_fn_router_deleted(self): row = utils.create_row( external_ids={ - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, - vips={'vip': 'member', 'fip': 'member'}) + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) old = utils.create_row(external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1' }) @@ -1351,18 +1393,20 @@ class TestOVNLBDeleteEvent(test_base.TestCase): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, - vips={'vip': 'member', 'fip': 'member'}) + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) old = utils.create_row(external_ids={}) self.assertFalse(self.event.match_fn(mock.Mock(), row, old)) def test_match_fn_old_router_non_local(self): row = utils.create_row( external_ids={ - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, - vips={'vip': 'member', 'fip': 'member'}) + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) old = utils.create_row(external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router2', }) @@ -1372,41 +1416,48 @@ class TestOVNLBDeleteEvent(test_base.TestCase): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, - vips={'vip': 'member', 'fip': 'member'}) - old = utils.create_row(external_ids={ - constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip'}) + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', + constants.OVN_LS_NAME_EXT_ID_KEY: 'net1', + constants.OVN_LB_VIP_IP_EXT_ID_KEY: '192.168.1.50'}, + vips={'192.168.1.50:80': '192.168.1.100:80'}) + old = utils.create_row( + external_ids={ + constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', + constants.OVN_LB_VIP_IP_EXT_ID_KEY: '192.168.1.50'}, + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) self.assertTrue(self.event.match_fn(mock.Mock(), row, old)) def test_match_fn_vip_deleted_with_ext_id_update(self): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, vips={}) old = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1', - 'other': 'info'}, - vips={'vip': 'member', 'fip': 'member'}) + constants.OVN_LB_VIP_IP_EXT_ID_KEY: '192.168.1.50'}, + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) self.assertTrue(self.event.match_fn(mock.Mock(), row, old)) - def test_run_vip(self): + def test_run_vip_delete_without_external_ids_on_old(self): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_IP_EXT_ID_KEY: '192.168.1.50', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, vips={}) - old = utils.create_row(vips={'vip': 'member'}) + old = utils.create_row(vips={'192.168.1.50:80': '192.168.1.100:80'}) self.event.run(None, row, old) - self.agent.withdraw_ovn_lb_vip.assert_called_once_with(row) + self.agent.withdraw_ovn_lb_vip.assert_not_called() self.agent.withdraw_ovn_lb_fip.assert_not_called() def test_run_vip_delete(self): @@ -1414,43 +1465,47 @@ class TestOVNLBDeleteEvent(test_base.TestCase): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', - constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, - vips={}) - + constants.OVN_LS_NAME_EXT_ID_KEY: 'net1', + constants.OVN_LB_VIP_IP_EXT_ID_KEY: '192.168.1.50'}, + vips={'192.168.1.50:80': '192.168.1.100:80'}) self.event.run(event, row, None) self.agent.withdraw_ovn_lb_vip.assert_called_once_with(row) - self.agent.withdraw_ovn_lb_fip.assert_called_once_with(row) def test_run_vip_deleted_extra_ext_id_info(self): - row = utils.create_row( - external_ids={ - constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', - constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, - vips={'vip': 'member', 'fip': 'member'}) old = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', + constants.OVN_LB_VIP_IP_EXT_ID_KEY: '192.168.1.50', + constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) + row = utils.create_row( + external_ids={ + constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1', - 'other': 'info'}) + 'other': 'info'}, + vips={}) self.event.run(None, row, old) - self.agent.withdraw_ovn_lb_vip.assert_not_called() - self.agent.withdraw_ovn_lb_fip.assert_not_called() + self.agent.withdraw_ovn_lb_vip.assert_called_once_with(old) + self.agent.withdraw_ovn_lb_fip.assert_called_once_with(old) def test_run_fip(self): row = utils.create_row( external_ids={ constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'}, - vips={'vip': 'member', 'fip': 'member'}) - old = utils.create_row(external_ids={ - constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', - constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip'}) + vips={'192.168.1.50:80': '192.168.1.100:80'}) + old = utils.create_row( + external_ids={ + constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1', + constants.OVN_LB_VIP_FIP_EXT_ID_KEY: '172.24.4.5'}, + vips={'192.168.1.50:80': '192.168.1.100:80', + '172.24.4.5:80': '192.168.1.100:80'}) self.event.run(None, row, old)