From b095fa11a4df221a5d539d142bd3c0340935ad9d Mon Sep 17 00:00:00 2001 From: watanabe isao Date: Wed, 24 Jun 2015 18:15:31 +0900 Subject: [PATCH] Bug-Fix for unexpected DHCP agent redundant This fix let DHCP scheduler not looks at only active agents, but all available agents. This helps db module to remove dead agent, when rebinding, properly. Change-Id: I8534ddfae299724c05641183c2fe4c1c98c614e8 Closes-Bug: 1388698 --- neutron/scheduler/dhcp_agent_scheduler.py | 4 +- .../scheduler/test_dhcp_agent_scheduler.py | 73 +++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/neutron/scheduler/dhcp_agent_scheduler.py b/neutron/scheduler/dhcp_agent_scheduler.py index 73840505d13..6a149440dde 100644 --- a/neutron/scheduler/dhcp_agent_scheduler.py +++ b/neutron/scheduler/dhcp_agent_scheduler.py @@ -59,7 +59,7 @@ class AutoScheduler(object): continue for net_id in net_ids: agents = plugin.get_dhcp_agents_hosting_networks( - context, [net_id], active=True) + context, [net_id]) if len(agents) >= agents_per_network: continue if any(dhcp_agent.id == agent.id for agent in agents): @@ -131,7 +131,7 @@ class DhcpFilter(base_resource_filter.BaseResourceFilter): # subnets whose enable_dhcp is false with context.session.begin(subtransactions=True): network_hosted_agents = plugin.get_dhcp_agents_hosting_networks( - context, [network['id']], active=True) + context, [network['id']]) if len(network_hosted_agents) >= agents_per_network: LOG.debug('Network %s is already hosted by enough agents.', network['id']) diff --git a/neutron/tests/unit/scheduler/test_dhcp_agent_scheduler.py b/neutron/tests/unit/scheduler/test_dhcp_agent_scheduler.py index 6dc8b68e969..1fa35898638 100644 --- a/neutron/tests/unit/scheduler/test_dhcp_agent_scheduler.py +++ b/neutron/tests/unit/scheduler/test_dhcp_agent_scheduler.py @@ -88,6 +88,79 @@ class TestDhcpScheduler(TestDhcpSchedulerBaseTestCase): self._test_schedule_bind_network(agents, self.network_id) self.assertEqual(1, fake_log.call_count) + def _test_get_agents_and_scheduler_for_dead_agent(self): + agents = self._create_and_set_agents_down(['dead_host', 'alive_host'], + 1) + dead_agent = [agents[0]] + alive_agent = [agents[1]] + self._test_schedule_bind_network(dead_agent, self.network_id) + scheduler = dhcp_agent_scheduler.ChanceScheduler() + return dead_agent, alive_agent, scheduler + + def _test_reschedule_vs_network_on_dead_agent(self, + active_hosts_only): + dead_agent, alive_agent, scheduler = ( + self._test_get_agents_and_scheduler_for_dead_agent()) + network = {'id': self.network_id} + plugin = mock.Mock() + plugin.get_subnets.return_value = [{"network_id": self.network_id, + "enable_dhcp": True}] + plugin.get_agents_db.return_value = dead_agent + alive_agent + if active_hosts_only: + plugin.get_dhcp_agents_hosting_networks.return_value = [] + self.assertTrue( + scheduler.schedule( + plugin, self.ctx, network)) + else: + plugin.get_dhcp_agents_hosting_networks.return_value = dead_agent + self.assertFalse( + scheduler.schedule( + plugin, self.ctx, network)) + + def test_network_rescheduled_when_db_returns_active_hosts(self): + self._test_reschedule_vs_network_on_dead_agent(True) + + def test_network_not_rescheduled_when_db_returns_all_hosts(self): + self._test_reschedule_vs_network_on_dead_agent(False) + + def _get_agent_binding_from_db(self, agent): + return self.ctx.session.query( + sched_db.NetworkDhcpAgentBinding + ).filter_by(dhcp_agent_id=agent[0].id).all() + + def _test_auto_reschedule_vs_network_on_dead_agent(self, + active_hosts_only): + dead_agent, alive_agent, scheduler = ( + self._test_get_agents_and_scheduler_for_dead_agent()) + plugin = mock.Mock() + plugin.get_subnets.return_value = [{"network_id": self.network_id, + "enable_dhcp": True}] + if active_hosts_only: + plugin.get_dhcp_agents_hosting_networks.return_value = [] + else: + plugin.get_dhcp_agents_hosting_networks.return_value = dead_agent + network_assigned_to_dead_agent = ( + self._get_agent_binding_from_db(dead_agent)) + self.assertEqual(1, len(network_assigned_to_dead_agent)) + self.assertTrue( + scheduler.auto_schedule_networks( + plugin, self.ctx, "alive_host")) + network_assigned_to_dead_agent = ( + self._get_agent_binding_from_db(dead_agent)) + network_assigned_to_alive_agent = ( + self._get_agent_binding_from_db(alive_agent)) + self.assertEqual(1, len(network_assigned_to_dead_agent)) + if active_hosts_only: + self.assertEqual(1, len(network_assigned_to_alive_agent)) + else: + self.assertEqual(0, len(network_assigned_to_alive_agent)) + + def test_network_auto_rescheduled_when_db_returns_active_hosts(self): + self._test_auto_reschedule_vs_network_on_dead_agent(True) + + def test_network_not_auto_rescheduled_when_db_returns_all_hosts(self): + self._test_auto_reschedule_vs_network_on_dead_agent(False) + class TestAutoScheduleNetworks(TestDhcpSchedulerBaseTestCase): """Unit test scenarios for ChanceScheduler.auto_schedule_networks.