summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorDavid Scannell <dscannell@gridcentric.com>2013-02-13 11:18:04 -0500
committerHans Lindgren <hanlind@kth.se>2013-02-18 15:00:18 +0100
commit53a7538a84ea2612cd86e6e98887cab7723dcbb2 (patch)
tree70d4f21d6b944ec8295dc786b7d3925ca9314db8 /nova
parent931515378cfb893a8d15d06b25216fe9242f53b6 (diff)
downloadnova-53a7538a84ea2612cd86e6e98887cab7723dcbb2.tar.gz
nova-53a7538a84ea2612cd86e6e98887cab7723dcbb2.tar.xz
nova-53a7538a84ea2612cd86e6e98887cab7723dcbb2.zip
Add select_hosts to scheduler manager rpc
This adds a select_hosts(...) method to the scheduler manager rpc that allows other services to query it for the best suited host instead of relying on it to proxy its messages. This can be used by extensions that need the scheduler to determine the best-fit host but want to prepare and send their own messages to that host. Change-Id: I5b4760114dfcdb0464fac8ea81f46f7532ac0580
Diffstat (limited to 'nova')
-rw-r--r--nova/scheduler/chance.py6
-rw-r--r--nova/scheduler/driver.py5
-rw-r--r--nova/scheduler/filter_scheduler.py5
-rw-r--r--nova/scheduler/manager.py9
-rw-r--r--nova/scheduler/rpcapi.py7
-rw-r--r--nova/tests/scheduler/test_chance_scheduler.py30
-rw-r--r--nova/tests/scheduler/test_filter_scheduler.py40
-rw-r--r--nova/tests/scheduler/test_rpcapi.py6
8 files changed, 107 insertions, 1 deletions
diff --git a/nova/scheduler/chance.py b/nova/scheduler/chance.py
index e161166fd..806758e42 100644
--- a/nova/scheduler/chance.py
+++ b/nova/scheduler/chance.py
@@ -57,6 +57,12 @@ class ChanceScheduler(driver.Scheduler):
return hosts[int(random.random() * len(hosts))]
+ def select_hosts(self, context, request_spec, filter_properties):
+ """Selects a set of random hosts."""
+ return [self._schedule(context, CONF.compute_topic,
+ request_spec, filter_properties)
+ for instance_uuid in request_spec.get('instance_uuids', [])]
+
def schedule_run_instance(self, context, request_spec,
admin_password, injected_files,
requested_networks, is_first_time,
diff --git a/nova/scheduler/driver.py b/nova/scheduler/driver.py
index 2565e4e40..1a2e8254a 100644
--- a/nova/scheduler/driver.py
+++ b/nova/scheduler/driver.py
@@ -160,6 +160,11 @@ class Scheduler(object):
msg = _("Driver must implement schedule_run_instance")
raise NotImplementedError(msg)
+ def select_hosts(self, context, request_spec, filter_properties):
+ """Must override select_hosts method for scheduler to work."""
+ msg = _("Driver must implement select_hosts")
+ raise NotImplementedError(msg)
+
def schedule_live_migration(self, context, instance, dest,
block_migration, disk_over_commit):
"""Live migration scheduling method.
diff --git a/nova/scheduler/filter_scheduler.py b/nova/scheduler/filter_scheduler.py
index c9118cb22..ecf909c9b 100644
--- a/nova/scheduler/filter_scheduler.py
+++ b/nova/scheduler/filter_scheduler.py
@@ -137,6 +137,11 @@ class FilterScheduler(driver.Scheduler):
request_spec=request_spec, filter_properties=filter_properties,
node=weighed_host.obj.nodename)
+ def select_hosts(self, context, request_spec, filter_properties):
+ """Selects a filtered set of hosts."""
+ return [host.obj.host for host in self._schedule(context, request_spec,
+ filter_properties)]
+
def _provision_resource(self, context, weighed_host, request_spec,
filter_properties, requested_networks, injected_files,
admin_password, is_first_time, instance_uuid=None):
diff --git a/nova/scheduler/manager.py b/nova/scheduler/manager.py
index 64a388f60..176d1f014 100644
--- a/nova/scheduler/manager.py
+++ b/nova/scheduler/manager.py
@@ -56,7 +56,7 @@ QUOTAS = quota.QUOTAS
class SchedulerManager(manager.Manager):
"""Chooses a host to run instances on."""
- RPC_API_VERSION = '2.5'
+ RPC_API_VERSION = '2.6'
def __init__(self, scheduler_driver=None, *args, **kwargs):
if not scheduler_driver:
@@ -285,3 +285,10 @@ class SchedulerManager(manager.Manager):
def get_backdoor_port(self, context):
return self.backdoor_port
+
+ def select_hosts(self, context, request_spec, filter_properties):
+ """Returns host(s) best suited for this request_spec and
+ filter_properties"""
+ hosts = self.driver.select_hosts(context, request_spec,
+ filter_properties)
+ return hosts
diff --git a/nova/scheduler/rpcapi.py b/nova/scheduler/rpcapi.py
index c3a37d6ad..5ce8abd7f 100644
--- a/nova/scheduler/rpcapi.py
+++ b/nova/scheduler/rpcapi.py
@@ -56,6 +56,7 @@ class SchedulerAPI(nova.openstack.common.rpc.proxy.RpcProxy):
2.4 - Change update_service_capabilities()
- accepts a list of capabilities
2.5 - Add get_backdoor_port()
+ 2.6 - Add select_hosts()
'''
#
@@ -117,3 +118,9 @@ class SchedulerAPI(nova.openstack.common.rpc.proxy.RpcProxy):
def get_backdoor_port(self, context, host):
return self.call(context, self.make_msg('get_backdoor_port'),
version='2.5')
+
+ def select_hosts(self, ctxt, request_spec, filter_properties):
+ return self.call(ctxt, self.make_msg('select_hosts',
+ request_spec=request_spec,
+ filter_properties=filter_properties),
+ version='2.6')
diff --git a/nova/tests/scheduler/test_chance_scheduler.py b/nova/tests/scheduler/test_chance_scheduler.py
index dcbe86f75..0ee617044 100644
--- a/nova/tests/scheduler/test_chance_scheduler.py
+++ b/nova/tests/scheduler/test_chance_scheduler.py
@@ -165,3 +165,33 @@ class ChanceSchedulerTestCase(test_scheduler.SchedulerTestCase):
self.driver.schedule_prep_resize(fake_context, {}, {}, {},
instance, {}, None)
self.assertEqual(info['called'], 0)
+
+ def test_select_hosts(self):
+ ctxt = context.RequestContext('fake', 'fake', False)
+ ctxt_elevated = 'fake-context-elevated'
+ fake_args = (1, 2, 3)
+ instance_opts = {'fake_opt1': 'meow', 'launch_index': -1}
+ instance1 = {'uuid': 'fake-uuid1'}
+ instance2 = {'uuid': 'fake-uuid2'}
+ request_spec = {'instance_uuids': ['fake-uuid1', 'fake-uuid2'],
+ 'instance_properties': instance_opts}
+
+ self.mox.StubOutWithMock(ctxt, 'elevated')
+ self.mox.StubOutWithMock(self.driver, 'hosts_up')
+ self.mox.StubOutWithMock(random, 'random')
+
+ ctxt.elevated().AndReturn(ctxt_elevated)
+ # instance 1
+ self.driver.hosts_up(ctxt_elevated, 'compute').AndReturn(
+ ['host1', 'host2', 'host3', 'host4'])
+ random.random().AndReturn(.5)
+
+ # instance 2
+ ctxt.elevated().AndReturn(ctxt_elevated)
+ self.driver.hosts_up(ctxt_elevated, 'compute').AndReturn(
+ ['host1', 'host2', 'host3', 'host4'])
+ random.random().AndReturn(.2)
+
+ self.mox.ReplayAll()
+ hosts = self.driver.select_hosts(ctxt, request_spec, {})
+ self.assertEquals(['host3', 'host1'], hosts)
diff --git a/nova/tests/scheduler/test_filter_scheduler.py b/nova/tests/scheduler/test_filter_scheduler.py
index 4b07581fb..849f63f5d 100644
--- a/nova/tests/scheduler/test_filter_scheduler.py
+++ b/nova/tests/scheduler/test_filter_scheduler.py
@@ -656,3 +656,43 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase):
self.assertEquals(1, len(hosts))
self.assertEquals(50, hosts[0].weight)
+
+ def test_select_hosts_happy_day(self):
+ """select_hosts is basically a wrapper around the _select() method.
+ Similar to the _select tests, this just does a happy path test to
+ ensure there is nothing glaringly wrong."""
+
+ self.next_weight = 1.0
+
+ selected_hosts = []
+
+ def _fake_weigh_objects(_self, functions, hosts, options):
+ self.next_weight += 2.0
+ host_state = hosts[0]
+ selected_hosts.append(host_state.host)
+ return [weights.WeighedHost(host_state, self.next_weight)]
+
+ sched = fakes.FakeFilterScheduler()
+ fake_context = context.RequestContext('user', 'project',
+ is_admin=True)
+
+ self.stubs.Set(sched.host_manager, 'get_filtered_hosts',
+ fake_get_filtered_hosts)
+ self.stubs.Set(weights.HostWeightHandler,
+ 'get_weighed_objects', _fake_weigh_objects)
+ fakes.mox_host_manager_db_calls(self.mox, fake_context)
+
+ request_spec = {'num_instances': 10,
+ 'instance_type': {'memory_mb': 512, 'root_gb': 512,
+ 'ephemeral_gb': 0,
+ 'vcpus': 1},
+ 'instance_properties': {'project_id': 1,
+ 'root_gb': 512,
+ 'memory_mb': 512,
+ 'ephemeral_gb': 0,
+ 'vcpus': 1,
+ 'os_type': 'Linux'}}
+ self.mox.ReplayAll()
+ hosts = sched.select_hosts(fake_context, request_spec, {})
+ self.assertEquals(len(hosts), 10)
+ self.assertEquals(hosts, selected_hosts)
diff --git a/nova/tests/scheduler/test_rpcapi.py b/nova/tests/scheduler/test_rpcapi.py
index e9a1680a8..af6a57ba6 100644
--- a/nova/tests/scheduler/test_rpcapi.py
+++ b/nova/tests/scheduler/test_rpcapi.py
@@ -90,3 +90,9 @@ class SchedulerRpcAPITestCase(test.TestCase):
def test_get_backdoor_port(self):
self._test_scheduler_api('get_backdoor_port', rpc_method='call',
host='fake_host', version='2.5')
+
+ def test_select_hosts(self):
+ self._test_scheduler_api('select_hosts', rpc_method='call',
+ request_spec='fake_request_spec',
+ filter_properties='fake_prop',
+ version='2.6')