diff options
-rw-r--r-- | nova/scheduler/zone.py | 58 | ||||
-rw-r--r-- | nova/tests/test_scheduler.py | 41 |
2 files changed, 99 insertions, 0 deletions
diff --git a/nova/scheduler/zone.py b/nova/scheduler/zone.py new file mode 100644 index 000000000..ec2166adf --- /dev/null +++ b/nova/scheduler/zone.py @@ -0,0 +1,58 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2010 Openstack, LLC. +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" +Availability Zone Scheduler implementation +""" + +import random + +from nova.scheduler import driver +from nova import db + + +class ZoneScheduler(driver.Scheduler): + """Implements Scheduler as a random node selector.""" + + def hosts_up_with_zone(self, context, topic, zone): + """Return the list of hosts that have a running service + for topic and availability zone (if defined). + """ + + if zone is None: + return self.hosts_up(context, topic) + + services = db.service_get_all_by_topic(context, topic) + return [service.host + for service in services + if self.service_is_up(service) + and service.availability_zone == zone] + + + def schedule(self, context, topic, *_args, **_kwargs): + """Picks a host that is up at random in selected + availability zone (if defined). + """ + + zone = _kwargs.get('availability_zone') + hosts = self.hosts_up_with_zone(context, topic, zone) + if not hosts: + raise driver.NoValidHost(_("No hosts found")) + return hosts[int(random.random() * len(hosts))] + diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 99f62f136..127d666e4 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -76,6 +76,47 @@ class SchedulerTestCase(test.TestCase): self.mox.ReplayAll() scheduler.named_method(ctxt, 'topic', num=7) +class ZoneSchedulerTestCase(test.TestCase): + """Test case for zone scheduler""" + def setUp(self): + super(ZoneSchedulerTestCase, self).setUp() + self.flags(scheduler_driver='nova.scheduler.zone.ZoneScheduler') + + def _create_service_model(self, **kwargs): + service = db.sqlalchemy.models.Service() + service.host = kwargs['host'] + service.disabled = False + service.deleted = False + service.report_count = 0 + service.binary = 'nova-compute' + service.topic = 'compute' + service.id = kwargs['id'] + service.availability_zone = kwargs['zone'] + service.created_at = datetime.datetime.utcnow() + return service + + + def test_with_two_zones(self): + scheduler = manager.SchedulerManager() + ctxt = context.get_admin_context() + service_list = [ + self._create_service_model(id=1, host='host1', zone='zone1'), + self._create_service_model(id=2, host='host2', zone='zone2'), + self._create_service_model(id=3, host='host3', zone='zone2'), + self._create_service_model(id=4, host='host4', zone='zone2'), + self._create_service_model(id=5, host='host5', zone='zone2') + ] + self.mox.StubOutWithMock(db, 'service_get_all_by_topic') + db.service_get_all_by_topic(IgnoreArg(), IgnoreArg()).AndReturn(service_list) + self.mox.StubOutWithMock(rpc, 'cast', use_mock_anything=True) + rpc.cast(ctxt, + 'compute.host1', + {'method': 'run_instance', + 'args':{'instance_id': 'i-ffffffff', + 'availability_zone': 'zone1'}}) + self.mox.ReplayAll() + scheduler.run_instance(ctxt, 'compute', instance_id='i-ffffffff', availability_zone='zone1') + class ZoneSchedulerTestCase(test.TestCase): """Test case for zone scheduler""" |