summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortermie <github@anarkystic.com>2011-08-11 16:26:26 -0700
committertermie <github@anarkystic.com>2011-08-11 16:26:26 -0700
commit500bd3218906e2575467467700f80f5b31e0a87e (patch)
treeda75f863e66a619d036c363db820267c1a1ae400
parentfe0bde67193ce76376e72a7263b89240a63722a8 (diff)
allow scheduling topics to multiple drivers
-rw-r--r--nova/scheduler/manager.py5
-rw-r--r--nova/scheduler/multi.py73
-rw-r--r--nova/tests/scheduler/test_scheduler.py24
3 files changed, 98 insertions, 4 deletions
diff --git a/nova/scheduler/manager.py b/nova/scheduler/manager.py
index c8b16b622..13c0bf22a 100644
--- a/nova/scheduler/manager.py
+++ b/nova/scheduler/manager.py
@@ -34,12 +34,13 @@ from nova.scheduler import zone_manager
LOG = logging.getLogger('nova.scheduler.manager')
FLAGS = flags.FLAGS
flags.DEFINE_string('scheduler_driver',
- 'nova.scheduler.chance.ChanceScheduler',
- 'Driver to use for the scheduler')
+ 'nova.scheduler.multi.MultiScheduler',
+ 'Default driver to use for the scheduler')
class SchedulerManager(manager.Manager):
"""Chooses a host to run instances on."""
+
def __init__(self, scheduler_driver=None, *args, **kwargs):
self.zone_manager = zone_manager.ZoneManager()
if not scheduler_driver:
diff --git a/nova/scheduler/multi.py b/nova/scheduler/multi.py
new file mode 100644
index 000000000..b1578033c
--- /dev/null
+++ b/nova/scheduler/multi.py
@@ -0,0 +1,73 @@
+# 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.
+
+"""
+Scheduler that allows routing some calls to one driver and others to another.
+"""
+
+from nova import flags
+from nova import utils
+from nova.scheduler import driver
+
+
+FLAGS = flags.FLAGS
+flags.DEFINE_string('compute_scheduler_driver',
+ 'nova.scheduler.chance.ChanceScheduler',
+ 'Driver to use for scheduling compute calls')
+flags.DEFINE_string('volume_scheduler_driver',
+ 'nova.scheduler.chance.ChanceScheduler',
+ 'Driver to use for scheduling volume calls')
+
+
+# A mapping of methods to topics so we can figure out which driver to use.
+_METHOD_MAP = {'run_instance': 'compute',
+ 'start_instance': 'compute',
+ 'create_volume': 'volume'}
+
+
+class MultiScheduler(driver.Scheduler):
+ """A scheduler that holds multiple sub-schedulers.
+
+ This exists to allow flag-driven composibility of schedulers, allowing
+ third parties to integrate custom schedulers more easily.
+
+ """
+
+ def __init__(self):
+ super(MultiScheduler, self).__init__()
+ compute_driver = utils.import_object(FLAGS.compute_scheduler_driver)
+ volume_driver = utils.import_object(FLAGS.volume_scheduler_driver)
+
+ self.drivers = {'compute': compute_driver,
+ 'volume': volume_driver}
+
+ def __getattr__(self, key):
+ if not key.startswith('schedule_'):
+ raise AttributeError(key)
+ method = key[len('schedule_'):]
+ if method not in _METHOD_MAP:
+ raise AttributeError(key)
+ return getattr(self.drivers[_METHOD_MAP[method]], key)
+
+ def set_zone_manager(self, zone_manager):
+ for k, v in self.drivers.iteritems():
+ v.set_zone_manager(zone_manager)
+
+ def schedule(self, context, topic, *_args, **_kwargs):
+ return self.drivers[topic].schedule(context, topic, *_args, **_kwargs)
diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py
index 7a26fd1bb..d70a6779f 100644
--- a/nova/tests/scheduler/test_scheduler.py
+++ b/nova/tests/scheduler/test_scheduler.py
@@ -36,8 +36,9 @@ from nova import test
from nova import rpc
from nova import utils
from nova.scheduler import api
-from nova.scheduler import manager
from nova.scheduler import driver
+from nova.scheduler import manager
+from nova.scheduler import multi
from nova.compute import power_state
@@ -391,7 +392,7 @@ class SimpleDriverTestCase(test.TestCase):
compute1.kill()
compute2.kill()
- def test_wont_sechedule_if_specified_host_is_down_no_queue(self):
+ def test_wont_schedule_if_specified_host_is_down_no_queue(self):
compute1 = service.Service('host1',
'nova-compute',
'compute',
@@ -903,6 +904,25 @@ class SimpleDriverTestCase(test.TestCase):
db.service_destroy(self.context, s_ref2['id'])
+class MultiDriverTestCase(SimpleDriverTestCase):
+ """Test case for multi driver."""
+
+ def setUp(self):
+ super(MultiDriverTestCase, self).setUp()
+ self.flags(connection_type='fake',
+ stub_network=True,
+ max_cores=4,
+ max_gigabytes=4,
+ network_manager='nova.network.manager.FlatManager',
+ volume_driver='nova.volume.driver.FakeISCSIDriver',
+ compute_scheduler_driver=('nova.scheduler.simple'
+ '.SimpleScheduler'),
+ volume_scheduler_driver=('nova.scheduler.simple'
+ '.SimpleScheduler'),
+ scheduler_driver='nova.scheduler.multi.MultiScheduler')
+ self.scheduler = manager.SchedulerManager()
+
+
class FakeZone(object):
def __init__(self, id, api_url, username, password):
self.id = id