From 480b04ce04f98bae6ff4ab13cec9e01b34204134 Mon Sep 17 00:00:00 2001 From: ushen Date: Sun, 18 Aug 2019 21:54:04 +0800 Subject: [PATCH] Unnecessary routers should not be created We observe an excessive amount of routers created on compute node on which some virtual machines got a fixed ip on floating network. Rpc servers should filter out those unnecessary routers during syncing. Change-Id: I299031a505f05cd0469e2476b867b9dbca59c5bf Partial-Bug: #1840579 --- neutron/db/l3_dvrscheduler_db.py | 10 ++++- .../tests/unit/db/test_agentschedulers_db.py | 39 +++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/neutron/db/l3_dvrscheduler_db.py b/neutron/db/l3_dvrscheduler_db.py index 7ce33fe81dd..304746944b5 100644 --- a/neutron/db/l3_dvrscheduler_db.py +++ b/neutron/db/l3_dvrscheduler_db.py @@ -174,12 +174,18 @@ class L3_DVRsch_db_mixin(l3agent_sch_db.L3AgentSchedulerDbMixin): router_ids.add(subnet_port['device_id']) return router_ids - def get_subnet_ids_on_router(self, context, router_id): + def get_subnet_ids_on_router(self, context, router_id, + keep_gateway_port=True): """Return subnet IDs for interfaces attached to the given router.""" subnet_ids = set() filter_rtr = {'device_id': [router_id]} int_ports = self._core_plugin.get_ports(context, filters=filter_rtr) + for int_port in int_ports: + if (not keep_gateway_port and + int_port['device_owner'] == + n_const.DEVICE_OWNER_ROUTER_GW): + continue int_ips = int_port['fixed_ips'] if int_ips: int_subnet = int_ips[0]['subnet_id'] @@ -433,7 +439,7 @@ class L3_DVRsch_db_mixin(l3agent_sch_db.L3AgentSchedulerDbMixin): else: for router_id in (router_ids - result_set): subnet_ids = self.get_subnet_ids_on_router( - context, router_id) + context, router_id, keep_gateway_port=False) if (subnet_ids and self._check_dvr_serviceable_ports_on_host( context, agent_db['host'], diff --git a/neutron/tests/unit/db/test_agentschedulers_db.py b/neutron/tests/unit/db/test_agentschedulers_db.py index f7707a57dbf..16ecb1123b8 100644 --- a/neutron/tests/unit/db/test_agentschedulers_db.py +++ b/neutron/tests/unit/db/test_agentschedulers_db.py @@ -17,6 +17,7 @@ import datetime import mock from neutron_lib.api.definitions import dhcpagentscheduler as das_apidef +from neutron_lib.api.definitions import portbindings from neutron_lib import constants from neutron_lib import context from neutron_lib.db import api as db_api @@ -1068,6 +1069,44 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase): # No router will be auto scheduled. self.assertEqual(0, len(host_routers['routers'])) + def test_sync_dvr_router_with_fixedip_on_fip_net(self): + l3_rpc_cb = l3_rpc.L3RpcCallback() + self._register_dvr_agents() + + with self.subnet() as s: + # first create an external network + net_id = s['subnet']['network_id'] + self._set_net_external(net_id) + # create router with external gateway + router = {'name': 'router1', + 'external_gateway_info': {'network_id': net_id}, + 'tenant_id': 'tenant_id', + 'admin_state_up': True, + 'distributed': True} + r = self.l3plugin.create_router(self.adminContext, + {'router': router}) + self.l3plugin.schedule_router(self.adminContext, r['id']) + with self.port(subnet=s, + device_owner=DEVICE_OWNER_COMPUTE) as port: + # bind port to L3_HOSTB + updated_port = { + "port": { + portbindings.HOST_ID: L3_HOSTB + } + } + self.plugin.update_port( + self.adminContext, + port['port']['id'], + updated_port + ) + ret_b = l3_rpc_cb.sync_routers( + self.adminContext, + host=L3_HOSTB, + router_ids=[r['id']]) + + router_ids = [r['id'] for r in ret_b] + self.assertEqual(0, len(router_ids)) + def test_router_without_l3_agents(self): with self.subnet() as s: self._set_net_external(s['subnet']['network_id'])