From: Oleg Bondarev Date: Thu, 3 Dec 2015 14:39:20 +0000 (+0300) Subject: Do not autoreschedule routers if l3 agent is back online X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=9ec466cd42de94c2fad091edfd7583a5f47eb87a;p=openstack-build%2Fneutron-build.git Do not autoreschedule routers if l3 agent is back online If there are a lot of routers scheduled to l3 agent, rescheduling all of them one by one might take quite a long period of time - during that time some agents might get back online. In this case we should skip rescheduling. Closes-Bug: #1522436 Change-Id: If6df1f2878ea3379e8d2dba431de3e358e40189d --- diff --git a/neutron/db/l3_agentschedulers_db.py b/neutron/db/l3_agentschedulers_db.py index a7f984410..f0d1b11b9 100644 --- a/neutron/db/l3_agentschedulers_db.py +++ b/neutron/db/l3_agentschedulers_db.py @@ -107,7 +107,16 @@ class L3AgentSchedulerDbMixin(l3agentscheduler.L3AgentSchedulerPluginBase, filter(sa.or_(l3_attrs_db.RouterExtraAttributes.ha == sql.false(), l3_attrs_db.RouterExtraAttributes.ha == sql.null()))) try: + agents_back_online = set() for binding in down_bindings: + if binding.l3_agent_id in agents_back_online: + continue + else: + agent = self._get_agent(context, binding.l3_agent_id) + if agent.is_active: + agents_back_online.add(binding.l3_agent_id) + continue + agent_mode = self._get_agent_mode(binding.l3_agent) if agent_mode == constants.L3_AGENT_MODE_DVR: # rescheduling from l3 dvr agent on compute node doesn't diff --git a/neutron/tests/unit/db/test_agentschedulers_db.py b/neutron/tests/unit/db/test_agentschedulers_db.py index dde3b3a20..582794f09 100644 --- a/neutron/tests/unit/db/test_agentschedulers_db.py +++ b/neutron/tests/unit/db/test_agentschedulers_db.py @@ -720,6 +720,26 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase): self._take_down_agent_and_run_reschedule(DHCP_HOSTC) self.assertFalse(rr.called) + def test_router_is_not_rescheduled_if_agent_is_back_online(self): + plugin = manager.NeutronManager.get_service_plugins().get( + service_constants.L3_ROUTER_NAT) + l3_rpc_cb = l3_rpc.L3RpcCallback() + agent = helpers.register_l3_agent(host=L3_HOSTA) + with self.router(),\ + self.router(),\ + mock.patch.object(plugin, 'reschedule_router') as rs_mock,\ + mock.patch.object(plugin, '_get_agent') as get_agent_mock: + + # schedule the routers to the agent + l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA) + self._take_down_agent_and_run_reschedule(L3_HOSTA) + # since _get_agent is mocked it will return Mock object and + # agent.is_active will return true, so no rescheduling will be done + self.assertFalse(rs_mock.called) + # should be called only once as for second router alive agent id + # will be in cache + get_agent_mock.assert_called_once_with(mock.ANY, agent['id']) + def test_router_reschedule_from_dead_agent(self): with self.router(): l3_rpc_cb = l3_rpc.L3RpcCallback()