From 1318437a0caf38e695a819848832a955fef7d909 Mon Sep 17 00:00:00 2001 From: Eugene Nikanorov Date: Fri, 5 Jun 2015 01:46:22 +0400 Subject: [PATCH] Skip rescheduling networks if no DHCP agents available This eliminates the problem of unscheduled networks in case of communication failure between agents and servers which can occur if messaging queue service fails. Change-Id: Ied4fa301fc3d475bee25c47f3a01c2381ae9a01e Closes-Bug: #1461714 --- neutron/db/agentschedulers_db.py | 11 ++++++++++- .../unit/scheduler/test_dhcp_agent_scheduler.py | 14 ++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/neutron/db/agentschedulers_db.py b/neutron/db/agentschedulers_db.py index 61eff9b07..b9d9c11db 100644 --- a/neutron/db/agentschedulers_db.py +++ b/neutron/db/agentschedulers_db.py @@ -271,7 +271,16 @@ class DhcpAgentSchedulerDbMixin(dhcpagentscheduler dhcp_notifier = self.agent_notifiers.get(constants.AGENT_TYPE_DHCP) try: - for binding in self._filter_bindings(context, down_bindings): + dead_bindings = [b for b in + self._filter_bindings(context, down_bindings)] + dead_agents = set([b.dhcp_agent_id for b in dead_bindings]) + agents = self.get_agents_db( + context, {'agent_type': [constants.AGENT_TYPE_DHCP]}) + if len(agents) == len(dead_agents): + LOG.warn(_LW("No DHCP agents available, " + "skipping rescheduling")) + return + for binding in dead_bindings: LOG.warn(_LW("Removing network %(network)s from agent " "%(agent)s because the agent did not report " "to the server in the last %(dead_time)s " diff --git a/neutron/tests/unit/scheduler/test_dhcp_agent_scheduler.py b/neutron/tests/unit/scheduler/test_dhcp_agent_scheduler.py index 5ee1adb16..260a5b01a 100644 --- a/neutron/tests/unit/scheduler/test_dhcp_agent_scheduler.py +++ b/neutron/tests/unit/scheduler/test_dhcp_agent_scheduler.py @@ -21,6 +21,7 @@ import testscenarios from neutron.common import constants from neutron import context from neutron.db import agentschedulers_db as sched_db +from neutron.db import common_db_mixin from neutron.db import models_v2 from neutron.extensions import dhcpagentscheduler from neutron.scheduler import dhcp_agent_scheduler @@ -177,7 +178,8 @@ class TestAutoScheduleNetworks(TestDhcpSchedulerBaseTestCase): class TestNetworksFailover(TestDhcpSchedulerBaseTestCase, - sched_db.DhcpAgentSchedulerDbMixin): + sched_db.DhcpAgentSchedulerDbMixin, + common_db_mixin.CommonDbMixin): def test_reschedule_network_from_down_agent(self): agents = self._create_and_set_agents_down(['host-a', 'host-b'], 1) self._test_schedule_bind_network([agents[0]], self.network_id) @@ -201,7 +203,7 @@ class TestNetworksFailover(TestDhcpSchedulerBaseTestCase, mock.ANY, self.network_id, agents[1].host) def _test_failed_rescheduling(self, rn_side_effect=None): - agents = self._create_and_set_agents_down(['host-a'], 1) + agents = self._create_and_set_agents_down(['host-a', 'host-b'], 1) self._test_schedule_bind_network([agents[0]], self.network_id) with mock.patch.object(self, 'remove_network_from_dhcp_agent', @@ -257,6 +259,14 @@ class TestNetworksFailover(TestDhcpSchedulerBaseTestCase, # just make sure that no exception is raised self.remove_networks_from_down_agents() + def test_reschedule_doesnt_occur_if_no_agents(self): + agents = self._create_and_set_agents_down(['host-a'], 1) + self._test_schedule_bind_network([agents[0]], self.network_id) + with mock.patch.object( + self, 'remove_network_from_dhcp_agent') as rn: + self.remove_networks_from_down_agents() + self.assertFalse(rn.called) + class DHCPAgentWeightSchedulerTestCase(TestDhcpSchedulerBaseTestCase): """Unit test scenarios for WeightScheduler.schedule.""" -- 2.45.2