Set lock_path correctly.
[openstack-build/neutron-build.git] / neutron / tests / unit / scheduler / test_dhcp_agent_scheduler.py
1 # Copyright 2014 OpenStack Foundation
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #    http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 # implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 import mock
17 from oslo_config import cfg
18 from oslo_utils import importutils
19 import testscenarios
20
21 from neutron.common import constants
22 from neutron import context
23 from neutron.db import agentschedulers_db as sched_db
24 from neutron.db import common_db_mixin
25 from neutron.db import models_v2
26 from neutron.extensions import dhcpagentscheduler
27 from neutron.scheduler import dhcp_agent_scheduler
28 from neutron.tests.common import helpers
29 from neutron.tests.unit import testlib_api
30
31 # Required to generate tests from scenarios. Not compatible with nose.
32 load_tests = testscenarios.load_tests_apply_scenarios
33
34 HOST_C = 'host-c'
35 HOST_D = 'host-d'
36
37
38 class TestDhcpSchedulerBaseTestCase(testlib_api.SqlTestCase):
39
40     def setUp(self):
41         super(TestDhcpSchedulerBaseTestCase, self).setUp()
42         self.ctx = context.get_admin_context()
43         self.network = {'id': 'foo_network_id'}
44         self.network_id = 'foo_network_id'
45         self._save_networks([self.network_id])
46
47     def _create_and_set_agents_down(self, hosts, down_agent_count=0,
48                                     admin_state_up=True,
49                                     az=helpers.DEFAULT_AZ):
50         agents = []
51         for i, host in enumerate(hosts):
52             is_alive = i >= down_agent_count
53             agents.append(helpers.register_dhcp_agent(
54                 host,
55                 admin_state_up=admin_state_up,
56                 alive=is_alive,
57                 az=az))
58         return agents
59
60     def _save_networks(self, networks):
61         for network_id in networks:
62             with self.ctx.session.begin(subtransactions=True):
63                 self.ctx.session.add(models_v2.Network(id=network_id))
64
65     def _test_schedule_bind_network(self, agents, network_id):
66         scheduler = dhcp_agent_scheduler.ChanceScheduler()
67         scheduler.resource_filter.bind(self.ctx, agents, network_id)
68         results = self.ctx.session.query(
69             sched_db.NetworkDhcpAgentBinding).filter_by(
70             network_id=network_id).all()
71         self.assertEqual(len(agents), len(results))
72         for result in results:
73             self.assertEqual(network_id, result.network_id)
74
75
76 class TestDhcpScheduler(TestDhcpSchedulerBaseTestCase):
77
78     def test_schedule_bind_network_single_agent(self):
79         agents = self._create_and_set_agents_down(['host-a'])
80         self._test_schedule_bind_network(agents, self.network_id)
81
82     def test_schedule_bind_network_multi_agents(self):
83         agents = self._create_and_set_agents_down(['host-a', 'host-b'])
84         self._test_schedule_bind_network(agents, self.network_id)
85
86     def test_schedule_bind_network_multi_agent_fail_one(self):
87         agents = self._create_and_set_agents_down(['host-a'])
88         self._test_schedule_bind_network(agents, self.network_id)
89         with mock.patch.object(dhcp_agent_scheduler.LOG, 'info') as fake_log:
90             self._test_schedule_bind_network(agents, self.network_id)
91             self.assertEqual(1, fake_log.call_count)
92
93     def _test_get_agents_and_scheduler_for_dead_agent(self):
94         agents = self._create_and_set_agents_down(['dead_host', 'alive_host'],
95                                                   1)
96         dead_agent = [agents[0]]
97         alive_agent = [agents[1]]
98         self._test_schedule_bind_network(dead_agent, self.network_id)
99         scheduler = dhcp_agent_scheduler.ChanceScheduler()
100         return dead_agent, alive_agent, scheduler
101
102     def _test_reschedule_vs_network_on_dead_agent(self,
103                                                   active_hosts_only):
104         dead_agent, alive_agent, scheduler = (
105             self._test_get_agents_and_scheduler_for_dead_agent())
106         network = {'id': self.network_id}
107         plugin = mock.Mock()
108         plugin.get_subnets.return_value = [{"network_id": self.network_id,
109                                             "enable_dhcp": True}]
110         plugin.get_agents_db.return_value = dead_agent + alive_agent
111         if active_hosts_only:
112             plugin.get_dhcp_agents_hosting_networks.return_value = []
113             self.assertTrue(
114                 scheduler.schedule(
115                     plugin, self.ctx, network))
116         else:
117             plugin.get_dhcp_agents_hosting_networks.return_value = dead_agent
118             self.assertFalse(
119                 scheduler.schedule(
120                     plugin, self.ctx, network))
121
122     def test_network_rescheduled_when_db_returns_active_hosts(self):
123         self._test_reschedule_vs_network_on_dead_agent(True)
124
125     def test_network_not_rescheduled_when_db_returns_all_hosts(self):
126         self._test_reschedule_vs_network_on_dead_agent(False)
127
128     def _get_agent_binding_from_db(self, agent):
129         return self.ctx.session.query(
130             sched_db.NetworkDhcpAgentBinding
131         ).filter_by(dhcp_agent_id=agent[0].id).all()
132
133     def _test_auto_reschedule_vs_network_on_dead_agent(self,
134                                                        active_hosts_only):
135         dead_agent, alive_agent, scheduler = (
136             self._test_get_agents_and_scheduler_for_dead_agent())
137         plugin = mock.Mock()
138         plugin.get_subnets.return_value = [{"network_id": self.network_id,
139                                             "enable_dhcp": True}]
140         plugin.get_network.return_value = self.network
141         if active_hosts_only:
142             plugin.get_dhcp_agents_hosting_networks.return_value = []
143         else:
144             plugin.get_dhcp_agents_hosting_networks.return_value = dead_agent
145         network_assigned_to_dead_agent = (
146             self._get_agent_binding_from_db(dead_agent))
147         self.assertEqual(1, len(network_assigned_to_dead_agent))
148         self.assertTrue(
149             scheduler.auto_schedule_networks(
150                 plugin, self.ctx, "alive_host"))
151         network_assigned_to_dead_agent = (
152             self._get_agent_binding_from_db(dead_agent))
153         network_assigned_to_alive_agent = (
154             self._get_agent_binding_from_db(alive_agent))
155         self.assertEqual(1, len(network_assigned_to_dead_agent))
156         if active_hosts_only:
157             self.assertEqual(1, len(network_assigned_to_alive_agent))
158         else:
159             self.assertEqual(0, len(network_assigned_to_alive_agent))
160
161     def test_network_auto_rescheduled_when_db_returns_active_hosts(self):
162         self._test_auto_reschedule_vs_network_on_dead_agent(True)
163
164     def test_network_not_auto_rescheduled_when_db_returns_all_hosts(self):
165         self._test_auto_reschedule_vs_network_on_dead_agent(False)
166
167
168 class TestAutoScheduleNetworks(TestDhcpSchedulerBaseTestCase):
169     """Unit test scenarios for ChanceScheduler.auto_schedule_networks.
170
171     network_present
172         Network is present or not
173
174     enable_dhcp
175         Dhcp is enabled or disabled in the subnet of the network
176
177     scheduled_already
178         Network is already scheduled to the agent or not
179
180     agent_down
181         Dhcp agent is down or alive
182
183     valid_host
184         If true, then an valid host is passed to schedule the network,
185         else an invalid host is passed.
186
187     az_hints
188         'availability_zone_hints' of the network.
189         note that default 'availability_zone' of an agent is 'nova'.
190     """
191     scenarios = [
192         ('Network present',
193          dict(network_present=True,
194               enable_dhcp=True,
195               scheduled_already=False,
196               agent_down=False,
197               valid_host=True,
198               az_hints=[])),
199
200         ('No network',
201          dict(network_present=False,
202               enable_dhcp=False,
203               scheduled_already=False,
204               agent_down=False,
205               valid_host=True,
206               az_hints=[])),
207
208         ('Network already scheduled',
209          dict(network_present=True,
210               enable_dhcp=True,
211               scheduled_already=True,
212               agent_down=False,
213               valid_host=True,
214               az_hints=[])),
215
216         ('Agent down',
217          dict(network_present=True,
218               enable_dhcp=True,
219               scheduled_already=False,
220               agent_down=False,
221               valid_host=True,
222               az_hints=[])),
223
224         ('dhcp disabled',
225          dict(network_present=True,
226               enable_dhcp=False,
227               scheduled_already=False,
228               agent_down=False,
229               valid_host=False,
230               az_hints=[])),
231
232         ('Invalid host',
233          dict(network_present=True,
234               enable_dhcp=True,
235               scheduled_already=False,
236               agent_down=False,
237               valid_host=False,
238               az_hints=[])),
239
240         ('Match AZ',
241          dict(network_present=True,
242               enable_dhcp=True,
243               scheduled_already=False,
244               agent_down=False,
245               valid_host=True,
246               az_hints=['nova'])),
247
248         ('Not match AZ',
249          dict(network_present=True,
250               enable_dhcp=True,
251               scheduled_already=False,
252               agent_down=False,
253               valid_host=True,
254               az_hints=['not-match'])),
255     ]
256
257     def test_auto_schedule_network(self):
258         plugin = mock.MagicMock()
259         plugin.get_subnets.return_value = (
260             [{"network_id": self.network_id, "enable_dhcp": self.enable_dhcp}]
261             if self.network_present else [])
262         plugin.get_network.return_value = {'availability_zone_hints':
263                                            self.az_hints}
264         scheduler = dhcp_agent_scheduler.ChanceScheduler()
265         if self.network_present:
266             down_agent_count = 1 if self.agent_down else 0
267             agents = self._create_and_set_agents_down(
268                 ['host-a'], down_agent_count=down_agent_count)
269             if self.scheduled_already:
270                 self._test_schedule_bind_network(agents, self.network_id)
271
272         expected_result = (self.network_present and self.enable_dhcp)
273         expected_hosted_agents = (1 if expected_result and
274                                   self.valid_host else 0)
275         if (self.az_hints and
276             agents[0]['availability_zone'] not in self.az_hints):
277             expected_hosted_agents = 0
278         host = "host-a" if self.valid_host else "host-b"
279         observed_ret_value = scheduler.auto_schedule_networks(
280             plugin, self.ctx, host)
281         self.assertEqual(expected_result, observed_ret_value)
282         hosted_agents = self.ctx.session.query(
283             sched_db.NetworkDhcpAgentBinding).all()
284         self.assertEqual(expected_hosted_agents, len(hosted_agents))
285
286
287 class TestNetworksFailover(TestDhcpSchedulerBaseTestCase,
288                            sched_db.DhcpAgentSchedulerDbMixin,
289                            common_db_mixin.CommonDbMixin):
290     def test_reschedule_network_from_down_agent(self):
291         agents = self._create_and_set_agents_down(['host-a', 'host-b'], 1)
292         self._test_schedule_bind_network([agents[0]], self.network_id)
293         self._save_networks(["foo-network-2"])
294         self._test_schedule_bind_network([agents[1]], "foo-network-2")
295         with mock.patch.object(self, 'remove_network_from_dhcp_agent') as rn,\
296                 mock.patch.object(self,
297                                   'schedule_network',
298                                   return_value=[agents[1]]) as sch,\
299                 mock.patch.object(self,
300                                   'get_network',
301                                   create=True,
302                                   return_value={'id': self.network_id}):
303             notifier = mock.MagicMock()
304             self.agent_notifiers[constants.AGENT_TYPE_DHCP] = notifier
305             self.remove_networks_from_down_agents()
306             rn.assert_called_with(mock.ANY, agents[0].id, self.network_id,
307                                   notify=False)
308             sch.assert_called_with(mock.ANY, {'id': self.network_id})
309             notifier.network_added_to_agent.assert_called_with(
310                 mock.ANY, self.network_id, agents[1].host)
311
312     def _test_failed_rescheduling(self, rn_side_effect=None):
313         agents = self._create_and_set_agents_down(['host-a', 'host-b'], 1)
314         self._test_schedule_bind_network([agents[0]], self.network_id)
315         with mock.patch.object(self,
316                                'remove_network_from_dhcp_agent',
317                                side_effect=rn_side_effect) as rn,\
318                 mock.patch.object(self,
319                                   'schedule_network',
320                                   return_value=None) as sch,\
321                 mock.patch.object(self,
322                                   'get_network',
323                                   create=True,
324                                   return_value={'id': self.network_id}):
325             notifier = mock.MagicMock()
326             self.agent_notifiers[constants.AGENT_TYPE_DHCP] = notifier
327             self.remove_networks_from_down_agents()
328             rn.assert_called_with(mock.ANY, agents[0].id, self.network_id,
329                                   notify=False)
330             sch.assert_called_with(mock.ANY, {'id': self.network_id})
331             self.assertFalse(notifier.network_added_to_agent.called)
332
333     def test_reschedule_network_from_down_agent_failed(self):
334         self._test_failed_rescheduling()
335
336     def test_reschedule_network_from_down_agent_concurrent_removal(self):
337         self._test_failed_rescheduling(
338             rn_side_effect=dhcpagentscheduler.NetworkNotHostedByDhcpAgent(
339                 network_id='foo', agent_id='bar'))
340
341     def test_filter_bindings(self):
342         bindings = [
343             sched_db.NetworkDhcpAgentBinding(network_id='foo1',
344                                              dhcp_agent={'id': 'id1'}),
345             sched_db.NetworkDhcpAgentBinding(network_id='foo2',
346                                              dhcp_agent={'id': 'id1'}),
347             sched_db.NetworkDhcpAgentBinding(network_id='foo3',
348                                              dhcp_agent={'id': 'id2'}),
349             sched_db.NetworkDhcpAgentBinding(network_id='foo4',
350                                              dhcp_agent={'id': 'id2'})]
351         with mock.patch.object(self, 'agent_starting_up',
352                                side_effect=[True, False]):
353             res = [b for b in self._filter_bindings(None, bindings)]
354             # once per each agent id1 and id2
355             self.assertEqual(2, len(res))
356             res_ids = [b.network_id for b in res]
357             self.assertIn('foo3', res_ids)
358             self.assertIn('foo4', res_ids)
359
360     def test_reschedule_network_from_down_agent_failed_on_unexpected(self):
361         agents = self._create_and_set_agents_down(['host-a'], 1)
362         self._test_schedule_bind_network([agents[0]], self.network_id)
363         with mock.patch.object(
364             self, '_filter_bindings',
365             side_effect=Exception()):
366             # just make sure that no exception is raised
367             self.remove_networks_from_down_agents()
368
369     def test_reschedule_doesnt_occur_if_no_agents(self):
370         agents = self._create_and_set_agents_down(['host-a', 'host-b'], 2)
371         self._test_schedule_bind_network([agents[0]], self.network_id)
372         with mock.patch.object(
373             self, 'remove_network_from_dhcp_agent') as rn:
374             self.remove_networks_from_down_agents()
375             self.assertFalse(rn.called)
376
377
378 class DHCPAgentWeightSchedulerTestCase(TestDhcpSchedulerBaseTestCase):
379     """Unit test scenarios for WeightScheduler.schedule."""
380
381     def setUp(self):
382         super(DHCPAgentWeightSchedulerTestCase, self).setUp()
383         DB_PLUGIN_KLASS = 'neutron.plugins.ml2.plugin.Ml2Plugin'
384         self.setup_coreplugin(DB_PLUGIN_KLASS)
385         cfg.CONF.set_override("network_scheduler_driver",
386             'neutron.scheduler.dhcp_agent_scheduler.WeightScheduler')
387         self.plugin = importutils.import_object('neutron.plugins.ml2.plugin.'
388                                                 'Ml2Plugin')
389         self.assertEqual(1, self.patched_dhcp_periodic.call_count)
390         self.plugin.network_scheduler = importutils.import_object(
391             'neutron.scheduler.dhcp_agent_scheduler.WeightScheduler'
392         )
393         cfg.CONF.set_override('dhcp_agents_per_network', 1)
394         cfg.CONF.set_override("dhcp_load_type", "networks")
395
396     def test_scheduler_one_agents_per_network(self):
397         self._save_networks(['1111'])
398         helpers.register_dhcp_agent(HOST_C)
399         self.plugin.network_scheduler.schedule(self.plugin, self.ctx,
400                                                {'id': '1111'})
401         agents = self.plugin.get_dhcp_agents_hosting_networks(self.ctx,
402                                                               ['1111'])
403         self.assertEqual(1, len(agents))
404
405     def test_scheduler_two_agents_per_network(self):
406         cfg.CONF.set_override('dhcp_agents_per_network', 2)
407         self._save_networks(['1111'])
408         helpers.register_dhcp_agent(HOST_C)
409         helpers.register_dhcp_agent(HOST_D)
410         self.plugin.network_scheduler.schedule(self.plugin, self.ctx,
411                                                {'id': '1111'})
412         agents = self.plugin.get_dhcp_agents_hosting_networks(self.ctx,
413                                                               ['1111'])
414         self.assertEqual(2, len(agents))
415
416     def test_scheduler_no_active_agents(self):
417         self._save_networks(['1111'])
418         self.plugin.network_scheduler.schedule(self.plugin, self.ctx,
419                                                {'id': '1111'})
420         agents = self.plugin.get_dhcp_agents_hosting_networks(self.ctx,
421                                                               ['1111'])
422         self.assertEqual(0, len(agents))
423
424     def test_scheduler_equal_distribution(self):
425         self._save_networks(['1111', '2222', '3333'])
426         helpers.register_dhcp_agent(HOST_C)
427         helpers.register_dhcp_agent(HOST_D, networks=1)
428         self.plugin.network_scheduler.schedule(
429             self.plugin, context.get_admin_context(), {'id': '1111'})
430         helpers.register_dhcp_agent(HOST_D, networks=2)
431         self.plugin.network_scheduler.schedule(
432             self.plugin, context.get_admin_context(), {'id': '2222'})
433         helpers.register_dhcp_agent(HOST_C, networks=4)
434         self.plugin.network_scheduler.schedule(
435             self.plugin, context.get_admin_context(), {'id': '3333'})
436         agent1 = self.plugin.get_dhcp_agents_hosting_networks(
437             self.ctx, ['1111'])
438         agent2 = self.plugin.get_dhcp_agents_hosting_networks(
439             self.ctx, ['2222'])
440         agent3 = self.plugin.get_dhcp_agents_hosting_networks(
441             self.ctx, ['3333'])
442         self.assertEqual('host-c', agent1[0]['host'])
443         self.assertEqual('host-c', agent2[0]['host'])
444         self.assertEqual('host-d', agent3[0]['host'])
445
446
447 class TestDhcpSchedulerFilter(TestDhcpSchedulerBaseTestCase,
448                               sched_db.DhcpAgentSchedulerDbMixin):
449     def _test_get_dhcp_agents_hosting_networks(self, expected, **kwargs):
450         agents = self._create_and_set_agents_down(['host-a', 'host-b'], 1)
451         agents += self._create_and_set_agents_down(['host-c', 'host-d'], 1,
452                                                    admin_state_up=False)
453         self._test_schedule_bind_network(agents, self.network_id)
454         agents = self.get_dhcp_agents_hosting_networks(self.ctx,
455                                                        [self.network_id],
456                                                        **kwargs)
457         host_ids = set(a['host'] for a in agents)
458         self.assertEqual(expected, host_ids)
459
460     def test_get_dhcp_agents_hosting_networks_default(self):
461         self._test_get_dhcp_agents_hosting_networks({'host-a', 'host-b',
462                                                      'host-c', 'host-d'})
463
464     def test_get_dhcp_agents_hosting_networks_active(self):
465         self._test_get_dhcp_agents_hosting_networks({'host-b', 'host-d'},
466                                                     active=True)
467
468     def test_get_dhcp_agents_hosting_networks_admin_up(self):
469         self._test_get_dhcp_agents_hosting_networks({'host-a', 'host-b'},
470                                                     admin_state_up=True)
471
472     def test_get_dhcp_agents_hosting_networks_active_admin_up(self):
473         self._test_get_dhcp_agents_hosting_networks({'host-b'},
474                                                     active=True,
475                                                     admin_state_up=True)
476
477     def test_get_dhcp_agents_hosting_networks_admin_down(self):
478         self._test_get_dhcp_agents_hosting_networks({'host-c', 'host-d'},
479                                                     admin_state_up=False)
480
481     def test_get_dhcp_agents_hosting_networks_active_admin_down(self):
482         self._test_get_dhcp_agents_hosting_networks({'host-d'},
483                                                     active=True,
484                                                     admin_state_up=False)
485
486
487 class DHCPAgentAZAwareWeightSchedulerTestCase(TestDhcpSchedulerBaseTestCase):
488
489     def setUp(self):
490         super(DHCPAgentAZAwareWeightSchedulerTestCase, self).setUp()
491         DB_PLUGIN_KLASS = 'neutron.plugins.ml2.plugin.Ml2Plugin'
492         self.setup_coreplugin(DB_PLUGIN_KLASS)
493         cfg.CONF.set_override("network_scheduler_driver",
494             'neutron.scheduler.dhcp_agent_scheduler.AZAwareWeightScheduler')
495         self.plugin = importutils.import_object('neutron.plugins.ml2.plugin.'
496                                                 'Ml2Plugin')
497         cfg.CONF.set_override('dhcp_agents_per_network', 1)
498         cfg.CONF.set_override("dhcp_load_type", "networks")
499
500     def test_az_scheduler_one_az_hints(self):
501         self._save_networks(['1111'])
502         helpers.register_dhcp_agent('az1-host1', networks=1, az='az1')
503         helpers.register_dhcp_agent('az1-host2', networks=2, az='az1')
504         helpers.register_dhcp_agent('az2-host1', networks=3, az='az2')
505         helpers.register_dhcp_agent('az2-host2', networks=4, az='az2')
506         self.plugin.network_scheduler.schedule(self.plugin, self.ctx,
507             {'id': '1111', 'availability_zone_hints': ['az2']})
508         agents = self.plugin.get_dhcp_agents_hosting_networks(self.ctx,
509                                                               ['1111'])
510         self.assertEqual(1, len(agents))
511         self.assertEqual('az2-host1', agents[0]['host'])
512
513     def test_az_scheduler_default_az_hints(self):
514         cfg.CONF.set_override('default_availability_zones', ['az1'])
515         self._save_networks(['1111'])
516         helpers.register_dhcp_agent('az1-host1', networks=1, az='az1')
517         helpers.register_dhcp_agent('az1-host2', networks=2, az='az1')
518         helpers.register_dhcp_agent('az2-host1', networks=3, az='az2')
519         helpers.register_dhcp_agent('az2-host2', networks=4, az='az2')
520         self.plugin.network_scheduler.schedule(self.plugin, self.ctx,
521             {'id': '1111', 'availability_zone_hints': []})
522         agents = self.plugin.get_dhcp_agents_hosting_networks(self.ctx,
523                                                               ['1111'])
524         self.assertEqual(1, len(agents))
525         self.assertEqual('az1-host1', agents[0]['host'])
526
527     def test_az_scheduler_two_az_hints(self):
528         cfg.CONF.set_override('dhcp_agents_per_network', 2)
529         self._save_networks(['1111'])
530         helpers.register_dhcp_agent('az1-host1', networks=1, az='az1')
531         helpers.register_dhcp_agent('az1-host2', networks=2, az='az1')
532         helpers.register_dhcp_agent('az2-host1', networks=3, az='az2')
533         helpers.register_dhcp_agent('az2-host2', networks=4, az='az2')
534         helpers.register_dhcp_agent('az3-host1', networks=5, az='az3')
535         helpers.register_dhcp_agent('az3-host2', networks=6, az='az3')
536         self.plugin.network_scheduler.schedule(self.plugin, self.ctx,
537             {'id': '1111', 'availability_zone_hints': ['az1', 'az3']})
538         agents = self.plugin.get_dhcp_agents_hosting_networks(self.ctx,
539                                                               ['1111'])
540         self.assertEqual(2, len(agents))
541         expected_hosts = set(['az1-host1', 'az3-host1'])
542         hosts = set([a['host'] for a in agents])
543         self.assertEqual(expected_hosts, hosts)
544
545     def test_az_scheduler_two_az_hints_one_available_az(self):
546         cfg.CONF.set_override('dhcp_agents_per_network', 2)
547         self._save_networks(['1111'])
548         helpers.register_dhcp_agent('az1-host1', networks=1, az='az1')
549         helpers.register_dhcp_agent('az1-host2', networks=2, az='az1')
550         helpers.register_dhcp_agent('az2-host1', networks=3, alive=False,
551                                     az='az2')
552         helpers.register_dhcp_agent('az2-host2', networks=4,
553                                     admin_state_up=False, az='az2')
554         self.plugin.network_scheduler.schedule(self.plugin, self.ctx,
555             {'id': '1111', 'availability_zone_hints': ['az1', 'az2']})
556         agents = self.plugin.get_dhcp_agents_hosting_networks(self.ctx,
557                                                               ['1111'])
558         self.assertEqual(2, len(agents))
559         expected_hosts = set(['az1-host1', 'az1-host2'])
560         hosts = set([a['host'] for a in agents])
561         self.assertEqual(expected_hosts, hosts)
562
563     def test_az_scheduler_no_az_hints(self):
564         cfg.CONF.set_override('dhcp_agents_per_network', 2)
565         self._save_networks(['1111'])
566         helpers.register_dhcp_agent('az1-host1', networks=2, az='az1')
567         helpers.register_dhcp_agent('az1-host2', networks=3, az='az1')
568         helpers.register_dhcp_agent('az2-host1', networks=2, az='az2')
569         helpers.register_dhcp_agent('az2-host2', networks=1, az='az2')
570         self.plugin.network_scheduler.schedule(self.plugin, self.ctx,
571             {'id': '1111', 'availability_zone_hints': []})
572         agents = self.plugin.get_dhcp_agents_hosting_networks(self.ctx,
573                                                               ['1111'])
574         self.assertEqual(2, len(agents))
575         expected_hosts = set(['az1-host1', 'az2-host2'])
576         hosts = {a['host'] for a in agents}
577         self.assertEqual(expected_hosts, hosts)