From 3af8e2719c772097c579c65fe088fea6a1f56a4d Mon Sep 17 00:00:00 2001 From: Slawek Kaplonski Date: Thu, 14 Feb 2019 14:35:25 +0100 Subject: [PATCH] Fix notification about arp entries for dvr routers In method _generate_arp_table_and_notify_agent in neutron.db.l3_dvr_db module notifiations about arp table was send only to one router connected to subnet. Now it will check if subnet is connected to more than one dvr router and will send same notification to all such routers. Closes-Bug: #1815913 Change-Id: I6a7d7f6645a8a7b5219788d51e17d54844d145bc (cherry picked from commit 1f104a093c1f27ddb1967e72cd452d43120b4cc2) --- neutron/db/l3_dvr_db.py | 13 ++++++------- neutron/tests/unit/db/test_l3_dvr_db.py | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/neutron/db/l3_dvr_db.py b/neutron/db/l3_dvr_db.py index e56f75ca73e..35991a43d3c 100644 --- a/neutron/db/l3_dvr_db.py +++ b/neutron/db/l3_dvr_db.py @@ -1023,16 +1023,15 @@ class _DVRAgentInterfaceMixin(object): """Generates the arp table entry and notifies the l3 agent.""" ip_address = fixed_ip['ip_address'] subnet = fixed_ip['subnet_id'] - filters = {'fixed_ips': {'subnet_id': [subnet]}, - 'device_owner': [const.DEVICE_OWNER_DVR_INTERFACE]} - ports = self._core_plugin.get_ports(context, filters=filters) - router_id = next((port['device_id'] for port in ports), None) - if not router_id: - return arp_table = {'ip_address': ip_address, 'mac_address': mac_address, 'subnet_id': subnet} - notifier(context, router_id, arp_table) + filters = {'fixed_ips': {'subnet_id': [subnet]}, + 'device_owner': [const.DEVICE_OWNER_DVR_INTERFACE]} + ports = self._core_plugin.get_ports(context, filters=filters) + routers = [port['device_id'] for port in ports] + for router_id in routers: + notifier(context, router_id, arp_table) def _get_subnet_id_for_given_fixed_ip( self, context, fixed_ip, port_dict): diff --git a/neutron/tests/unit/db/test_l3_dvr_db.py b/neutron/tests/unit/db/test_l3_dvr_db.py index 492207a58a9..94fd05e182b 100644 --- a/neutron/tests/unit/db/test_l3_dvr_db.py +++ b/neutron/tests/unit/db/test_l3_dvr_db.py @@ -826,6 +826,26 @@ class L3DvrTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): port=mock.ANY, interface_info=interface_info) + def test__generate_arp_table_and_notify_agent(self): + fixed_ip = { + 'ip_address': '1.2.3.4', + 'subnet_id': _uuid()} + mac_address = "00:11:22:33:44:55" + expected_arp_table = { + 'ip_address': fixed_ip['ip_address'], + 'subnet_id': fixed_ip['subnet_id'], + 'mac_address': mac_address} + notifier = mock.Mock() + ports = [{'id': _uuid(), 'device_id': 'router_1'}, + {'id': _uuid(), 'device_id': 'router_2'}] + with mock.patch.object(self.core_plugin, "get_ports", + return_value=ports): + self.mixin._generate_arp_table_and_notify_agent( + self.ctx, fixed_ip, mac_address, notifier) + notifier.assert_has_calls([ + mock.call(self.ctx, "router_1", expected_arp_table), + mock.call(self.ctx, "router_2", expected_arp_table)]) + def _test_update_arp_entry_for_dvr_service_port( self, device_owner, action): router_dict = {'name': 'test_router', 'admin_state_up': True,