diff --git a/ovn_bgp_agent/drivers/openstack/ovn_bgp_driver.py b/ovn_bgp_agent/drivers/openstack/ovn_bgp_driver.py index 3d5cef32..d71dd6a0 100644 --- a/ovn_bgp_agent/drivers/openstack/ovn_bgp_driver.py +++ b/ovn_bgp_agent/drivers/openstack/ovn_bgp_driver.py @@ -342,7 +342,13 @@ class OVNBGPDriver(driver_api.AgentDriverBase): return try: - port_ips = port.mac[0].split(' ')[1:] + if port.mac == ['unknown']: + # Handling the case for unknown MACs when configdrive is used + # instead of dhcp + n_cidrs = port.external_ids.get(constants.OVN_CIDRS_EXT_ID_KEY) + port_ips = [ip.split("/")[0] for ip in n_cidrs.split(" ")] + else: + port_ips = port.mac[0].split(' ')[1:] except IndexError: return diff --git a/ovn_bgp_agent/drivers/openstack/watchers/bgp_watcher.py b/ovn_bgp_agent/drivers/openstack/watchers/bgp_watcher.py index ed605793..c888c6ec 100644 --- a/ovn_bgp_agent/drivers/openstack/watchers/bgp_watcher.py +++ b/ovn_bgp_agent/drivers/openstack/watchers/bgp_watcher.py @@ -242,8 +242,14 @@ class TenantPortCreatedEvent(base_watcher.PortBindingChassisEvent): def match_fn(self, event, row, old): try: + # Handling the case for unknown MACs when configdrive is used + # instead of dhcp + if row.mac == ['unknown']: + n_cidrs = row.external_ids.get(constants.OVN_CIDRS_EXT_ID_KEY) + if not n_cidrs: + return False # single and dual-stack format - if not self._check_ip_associated(row.mac[0]): + elif not self._check_ip_associated(row.mac[0]): return False return (not old.chassis and row.chassis and self.agent.ovn_local_lrps != []) @@ -255,7 +261,13 @@ class TenantPortCreatedEvent(base_watcher.PortBindingChassisEvent): constants.OVN_VIRTUAL_VIF_PORT_TYPE): return with _SYNC_STATE_LOCK.read_lock(): - ips = row.mac[0].split(' ')[1:] + if row.mac == ['unknown']: + # Handling the case for unknown MACs when configdrive is used + # instead of dhcp + n_cidrs = row.external_ids.get(constants.OVN_CIDRS_EXT_ID_KEY) + ips = [ip.split("/")[0] for ip in n_cidrs.split(" ")] + else: + ips = row.mac[0].split(' ')[1:] self.agent.expose_remote_ip(ips, row) @@ -267,8 +279,14 @@ class TenantPortDeletedEvent(base_watcher.PortBindingChassisEvent): def match_fn(self, event, row, old): try: + if row.mac == ['unknown']: + # Handling the case for unknown MACs when configdrive is used + # instead of dhcp + n_cidrs = row.external_ids.get(constants.OVN_CIDRS_EXT_ID_KEY) + if not n_cidrs: + return False # single and dual-stack format - if not self._check_ip_associated(row.mac[0]): + elif not self._check_ip_associated(row.mac[0]): return False if event == self.ROW_UPDATE: return (old.chassis and not row.chassis and @@ -287,7 +305,13 @@ class TenantPortDeletedEvent(base_watcher.PortBindingChassisEvent): else: chassis = row.chassis with _SYNC_STATE_LOCK.read_lock(): - ips = row.mac[0].split(' ')[1:] + if row.mac == ['unknown']: + # Handling the case for unknown MACs when configdrive is used + # instead of dhcp + n_cidrs = row.external_ids.get(constants.OVN_CIDRS_EXT_ID_KEY) + ips = [ip.split("/")[0] for ip in n_cidrs.split(" ")] + else: + ips = row.mac[0].split(' ')[1:] self.agent.withdraw_remote_ip(ips, row, chassis) diff --git a/ovn_bgp_agent/tests/unit/drivers/openstack/test_ovn_bgp_driver.py b/ovn_bgp_agent/tests/unit/drivers/openstack/test_ovn_bgp_driver.py index 887b5dab..d5e0aa78 100644 --- a/ovn_bgp_agent/tests/unit/drivers/openstack/test_ovn_bgp_driver.py +++ b/ovn_bgp_agent/tests/unit/drivers/openstack/test_ovn_bgp_driver.py @@ -400,6 +400,26 @@ class TestOVNBGPDriver(test_base.TestCase): mock_ip_version.assert_not_called() mock_add_ips_dev.assert_not_called() + @mock.patch.object(linux_net, 'add_ips_to_dev') + @mock.patch.object(linux_net, 'get_ip_version') + def test__expose_tenant_port_unknown_mac(self, mock_ip_version, + mock_add_ips_dev): + tenant_port = fakes.create_object({ + 'name': 'fake-port', + 'type': constants.OVN_VM_VIF_PORT_TYPE, + 'mac': ['unknown'], + 'chassis': 'fake-chassis1', + 'external_ids': {'neutron:cidrs': '192.168.1.10/24'}, + 'up': [False]}) + ip_version = constants.IP_VERSION_4 + + mock_ip_version.return_value = constants.IP_VERSION_4 + + self.bgp_driver._expose_tenant_port(tenant_port, ip_version) + + mock_add_ips_dev.assert_called_once_with(CONF.bgp_nic, + ['192.168.1.10']) + @mock.patch.object(linux_net, 'add_ips_to_dev') @mock.patch.object(linux_net, 'get_ip_version') def test__expose_tenant_port_wrong_type(self, mock_ip_version, diff --git a/ovn_bgp_agent/tests/unit/drivers/openstack/watchers/test_bgp_watcher.py b/ovn_bgp_agent/tests/unit/drivers/openstack/watchers/test_bgp_watcher.py index 1fc54bfd..5a9ce886 100644 --- a/ovn_bgp_agent/tests/unit/drivers/openstack/watchers/test_bgp_watcher.py +++ b/ovn_bgp_agent/tests/unit/drivers/openstack/watchers/test_bgp_watcher.py @@ -575,6 +575,18 @@ class TestTenantPortCreatedEvent(test_base.TestCase): old = utils.create_row(chassis=[]) self.assertTrue(self.event.match_fn(mock.Mock(), row, old)) + def test_match_fn_unknown_mac(self): + event = self.event.ROW_UPDATE + row = utils.create_row(chassis=[mock.Mock()], + mac=['unknown'], + external_ids={ + 'neutron:cidrs': '10.10.1.16/24'}) + old = utils.create_row(chassis=[], + mac=['unknown'], + external_ids={ + 'neutron:cidrs': '10.10.1.16/24'}) + self.assertTrue(self.event.match_fn(event, row, old)) + def test_match_fn_no_chassis(self): row = utils.create_row(mac=['aa:bb:cc:dd:ee:ff 10.10.1.16']) old = utils.create_row(chassis=[]) @@ -608,6 +620,15 @@ class TestTenantPortCreatedEvent(test_base.TestCase): self.agent.expose_remote_ip.assert_called_once_with( ['10.10.1.16'], row) + def test_run_unknown_mac(self): + row = utils.create_row(type=constants.OVN_VM_VIF_PORT_TYPE, + mac=['unknown'], + external_ids={ + 'neutron:cidrs': '10.10.1.16/24'}) + self.event.run(mock.Mock(), row, mock.Mock()) + self.agent.expose_remote_ip.assert_called_once_with( + ['10.10.1.16'], row) + def test_run_dual_stack(self): row = utils.create_row( type=constants.OVN_VM_VIF_PORT_TYPE, @@ -639,6 +660,18 @@ class TestTenantPortDeletedEvent(test_base.TestCase): mac=['aa:bb:cc:dd:ee:ff 10.10.1.16']) self.assertTrue(self.event.match_fn(event, row, old)) + def test_match_fn_unknown_mac(self): + event = self.event.ROW_UPDATE + row = utils.create_row(chassis=[], + mac=['unknown'], + external_ids={ + 'neutron:cidrs': '192.168.1.10/24'}) + old = utils.create_row(chassis=[mock.Mock()], + mac=['unknown'], + external_ids={ + 'neutron:cidrs': '192.168.1.10/24'}) + self.assertTrue(self.event.match_fn(event, row, old)) + def test_match_fn_delete(self): event = self.event.ROW_DELETE row = utils.create_row(chassis=[], @@ -669,6 +702,16 @@ class TestTenantPortDeletedEvent(test_base.TestCase): self.agent.withdraw_remote_ip.assert_called_once_with( ['10.10.1.16'], row, mock.ANY) + def test_run_unknown_mac(self): + row = utils.create_row(type=constants.OVN_VM_VIF_PORT_TYPE, + chassis=[mock.Mock()], + mac=['unknown'], + external_ids={ + 'neutron:cidrs': '10.10.1.16/24'}) + self.event.run(mock.Mock(), row, mock.Mock()) + self.agent.withdraw_remote_ip.assert_called_once_with( + ['10.10.1.16'], row, mock.ANY) + def test_run_dual_stack(self): row = utils.create_row( type=constants.OVN_VM_VIF_PORT_TYPE,