From 24fa37e05544316b58357b753360b147878e5d94 Mon Sep 17 00:00:00 2001 From: lzklibj Date: Mon, 2 Mar 2015 02:13:41 -0800 Subject: [PATCH] Fix dvr update for subnet attach multi subnets Fix method dvr_update_router_addvm to notify every router attached to subnet where the vm will boot on. In dvr case, when a subnet only attaches to one router, the subnet will only have one distributed router interface, which device_owner is "network:router_interface_distributed". So in this case, get_ports in this method will only get one port, and it should be unnecessary to break in for loop. But when a subnet attaches multiple routers, get_ports in this method will return all distributed router interfaces and the routers hold those interfaces should be notified when an instance booted on the subnet. So it should also be unnecessary to break in for loop. Change-Id: I3a5808e5b6e8b78abd1a5b924395844507da0764 Closes-Bug: #1427122 Co-Authored-By: Ryan Moats --- neutron/db/l3_dvrscheduler_db.py | 4 +- .../unit/scheduler/test_l3_agent_scheduler.py | 38 +++++++++++++++++-- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/neutron/db/l3_dvrscheduler_db.py b/neutron/db/l3_dvrscheduler_db.py index 6caba149441..5435903f02b 100644 --- a/neutron/db/l3_dvrscheduler_db.py +++ b/neutron/db/l3_dvrscheduler_db.py @@ -106,7 +106,6 @@ class L3_DVRsch_db_mixin(l3agent_sch_db.L3AgentSchedulerDbMixin): filter_sub = {'fixed_ips': {'subnet_id': [subnet]}, 'device_owner': [n_const.DEVICE_OWNER_DVR_INTERFACE]} - router_id = None ports = self._core_plugin.get_ports(context, filters=filter_sub) for port in ports: router_id = port['device_id'] @@ -115,8 +114,7 @@ class L3_DVRsch_db_mixin(l3agent_sch_db.L3AgentSchedulerDbMixin): payload = {'subnet_id': subnet} self.l3_rpc_notifier.routers_updated( context, [router_id], None, payload) - break - LOG.debug('DVR: dvr_update_router_addvm %s ', router_id) + LOG.debug('DVR: dvr_update_router_addvm %s ', router_id) def get_dvr_routers_by_portid(self, context, port_id): """Gets the dvr routers on vmport subnets.""" diff --git a/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py b/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py index e4421e4aae4..93451fb4a72 100644 --- a/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py +++ b/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py @@ -948,7 +948,8 @@ class L3DvrSchedulerTestCase(testlib_api.SqlTestCase): } ] } - dvr_port = { + dvr_ports = [ + { 'id': 'dvr_port1', 'device_id': 'r1', 'device_owner': 'network:router_interface_distributed', @@ -958,23 +959,52 @@ class L3DvrSchedulerTestCase(testlib_api.SqlTestCase): 'ip_address': '10.10.10.1' } ] - } + }, + { + 'id': 'dvr_port2', + 'device_id': 'r2', + 'device_owner': 'network:router_interface_distributed', + 'fixed_ips': [ + { + 'subnet_id': '80947d4a-fbc8-484b-9f92-623a6bfcf3e0', + 'ip_address': '10.10.10.123' + } + ] + } + ] r1 = { 'id': 'r1', 'distributed': True, } + r2 = { + 'id': 'r2', + 'distributed': True, + } with mock.patch( 'neutron.db.db_base_plugin_v2.NeutronDbPluginV2' '.get_ports', - return_value=[dvr_port]),\ + return_value=dvr_ports),\ mock.patch( 'neutron.manager.NeutronManager.get_service_plugins', return_value=mock.Mock()),\ mock.patch('neutron.db.l3_db.L3_NAT_db_mixin.get_router', - return_value=r1),\ + router_id='r1', return_value=r1),\ + mock.patch('neutron.db.l3_db.L3_NAT_db_mixin.get_router', + router_id='r2', return_value=r2),\ mock.patch('neutron.api.rpc.agentnotifiers.l3_rpc_agent_api' '.L3AgentNotifyAPI'): self.dut.dvr_update_router_addvm(self.adminContext, port) + self.assertEqual( + self.dut.l3_rpc_notifier.routers_updated.call_count, 2) + payload = {'subnet_id': port['fixed_ips'][0]['subnet_id']} + expected_calls = [ + mock.call.routers_updated( + self.adminContext, ['r1'], None, payload), + mock.call.routers_updated( + self.adminContext, ['r2'], None, payload) + ] + self.dut.l3_rpc_notifier.routers_updated.assert_has_calls( + expected_calls, any_order=True) def test_get_dvr_routers_by_portid(self): dvr_port = {