diff --git a/neutron/db/l3_dvrscheduler_db.py b/neutron/db/l3_dvrscheduler_db.py index baf340e9b02..ddb5758f047 100644 --- a/neutron/db/l3_dvrscheduler_db.py +++ b/neutron/db/l3_dvrscheduler_db.py @@ -166,12 +166,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'] @@ -421,7 +427,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 3369f3659b0..64c66e06ca2 100644 --- a/neutron/tests/unit/db/test_agentschedulers_db.py +++ b/neutron/tests/unit/db/test_agentschedulers_db.py @@ -16,6 +16,7 @@ import datetime import mock +from neutron_lib.api.definitions import portbindings from neutron_lib import constants from neutron_lib import context from neutron_lib.plugins import constants as plugin_constants @@ -1001,6 +1002,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_data = {'name': 'router1', + 'external_gateway_info': {'network_id': net_id}, + 'tenant_id': 'tenant_id', + 'admin_state_up': True, + 'distributed': True} + router = self.l3plugin.create_router(self.adminContext, + {'router': router_data}) + self.l3plugin.schedule_router(self.adminContext, router['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=[router['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'])