summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nova/scheduler/zone.py58
-rw-r--r--nova/tests/test_scheduler.py41
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"""