summaryrefslogtreecommitdiffstats
path: root/nova/scheduler
diff options
context:
space:
mode:
authorMark McLoughlin <markmc@redhat.com>2012-08-29 09:21:03 +0100
committerMark McLoughlin <markmc@redhat.com>2012-08-29 12:06:36 +0100
commit8cf635b08a57a9e3be2bef980ef38cf857b6525a (patch)
treedb4eb0485f03c6445db8e61274022dc43da26b50 /nova/scheduler
parent6727b259af491177514f075a3db91d55810c66e4 (diff)
downloadnova-8cf635b08a57a9e3be2bef980ef38cf857b6525a.tar.gz
nova-8cf635b08a57a9e3be2bef980ef38cf857b6525a.tar.xz
nova-8cf635b08a57a9e3be2bef980ef38cf857b6525a.zip
Stop using scheduler RPC API magic
If a scheduler RPC message isn't handled directly by a SchedulerManager method, the __getattr__() fallback passes the message to a driver method in the form of schedule_${method}() and, if that doesn't exist, instead calls the schedule() method supplying the topic and method args. This is pretty bizarre stuff and we appear to only use it in two cases: 1) live_migration - this is how the schedule_live_migration() method in the driver gets called, but the side-effect is that we require the client to pass a topic argument which is never used. This would be much more sanely handled with an explicit SchedulerManager.live_migration() method. 2) create_volume - the volume API asks the scheduler to pick a target host for create_volume() using this method. This would be easily handled with an SchedulerManager.create_volume() method. Change-Id: I1047489d85ac51d8d36fea1c4eb858df638ce349
Diffstat (limited to 'nova/scheduler')
-rw-r--r--nova/scheduler/chance.py9
-rw-r--r--nova/scheduler/driver.py5
-rw-r--r--nova/scheduler/filter_scheduler.py7
-rw-r--r--nova/scheduler/manager.py28
-rw-r--r--nova/scheduler/multi.py3
-rw-r--r--nova/scheduler/rpcapi.py12
-rw-r--r--nova/scheduler/simple.py9
7 files changed, 67 insertions, 6 deletions
diff --git a/nova/scheduler/chance.py b/nova/scheduler/chance.py
index 9731a0a07..e74f34054 100644
--- a/nova/scheduler/chance.py
+++ b/nova/scheduler/chance.py
@@ -24,8 +24,11 @@ Chance (Random) Scheduler implementation
import random
from nova import exception
+from nova import flags
from nova.scheduler import driver
+FLAGS = flags.FLAGS
+
class ChanceScheduler(driver.Scheduler):
"""Implements Scheduler as a random node selector."""
@@ -123,3 +126,9 @@ class ChanceScheduler(driver.Scheduler):
filter_properties)
self.compute_rpcapi.prep_resize(context, image, instance,
instance_type, host, reservations)
+
+ def schedule_create_volume(self, context, volume_id, snapshot_id,
+ reservations):
+ self.schedule(context, FLAGS.volume_topic, 'create_volume',
+ volume_id=volume_id, snapshot_id=snapshot_id,
+ reservations=reservations)
diff --git a/nova/scheduler/driver.py b/nova/scheduler/driver.py
index 42e05e903..f599965cd 100644
--- a/nova/scheduler/driver.py
+++ b/nova/scheduler/driver.py
@@ -202,6 +202,11 @@ class Scheduler(object):
msg = _("Driver must implement schedule_run_instance")
raise NotImplementedError(msg)
+ def schedule_create_volume(self, context, volume_id, snapshot_id,
+ reservations):
+ msg = _("Driver must implement schedule_create_volune")
+ raise NotImplementedError(msg)
+
def schedule_live_migration(self, context, dest,
block_migration=False, disk_over_commit=False,
instance=None, instance_id=None):
diff --git a/nova/scheduler/filter_scheduler.py b/nova/scheduler/filter_scheduler.py
index 9eea8dea6..258b66f7e 100644
--- a/nova/scheduler/filter_scheduler.py
+++ b/nova/scheduler/filter_scheduler.py
@@ -51,6 +51,13 @@ class FilterScheduler(driver.Scheduler):
msg = _("No host selection for %s defined.") % topic
raise exception.NoValidHost(reason=msg)
+ def schedule_create_volume(self, context, volume_id, snapshot_id,
+ reservations):
+ # NOTE: We're only focused on compute instances right now,
+ # so this method will always raise NoValidHost().
+ msg = _("No host selection for %s defined.") % FLAGS.volume_topic
+ raise exception.NoValidHost(reason=msg)
+
def schedule_run_instance(self, context, request_spec,
admin_password, injected_files,
requested_networks, is_first_time,
diff --git a/nova/scheduler/manager.py b/nova/scheduler/manager.py
index e1030121a..36e9a8473 100644
--- a/nova/scheduler/manager.py
+++ b/nova/scheduler/manager.py
@@ -53,7 +53,7 @@ QUOTAS = quota.QUOTAS
class SchedulerManager(manager.Manager):
"""Chooses a host to run instances on."""
- RPC_API_VERSION = '1.6'
+ RPC_API_VERSION = '1.7'
def __init__(self, scheduler_driver=None, *args, **kwargs):
if not scheduler_driver:
@@ -66,6 +66,8 @@ class SchedulerManager(manager.Manager):
# NOTE(russellb) Because of what this is doing, we must be careful
# when changing the API of the scheduler drivers, as that changes
# the rpc API as well, and the version should be updated accordingly.
+ # NOTE(markmc): This remains only for backwards compat support
+ # and can be removed when we bump the major version
return functools.partial(self._schedule, key)
def get_host_list(self, context):
@@ -91,6 +93,30 @@ class SchedulerManager(manager.Manager):
self.driver.update_service_capabilities(service_name, host,
capabilities)
+ def create_volume(self, context, volume_id, snapshot_id, reservations):
+ try:
+ self.driver.schedule_create_volume(
+ context, volume_id, snapshot_id, reservations)
+ except Exception as ex:
+ with excutils.save_and_reraise_exception():
+ self._set_vm_state_and_notify('create_volume',
+ {'vm_state': vm_states.ERROR},
+ context, ex, {})
+
+ def live_migration(self, context, dest,
+ block_migration=False, disk_over_commit=False,
+ instance=None, instance_id=None, topic=None):
+ try:
+ return self.driver.schedule_live_migration(
+ context, dest,
+ block_migration, disk_over_commit,
+ instance, instance_id)
+ except Exception as ex:
+ with excutils.save_and_reraise_exception():
+ self._set_vm_state_and_notify('live_migration',
+ {'vm_state': vm_states.ERROR},
+ context, ex, {})
+
def _schedule(self, method, context, topic, *args, **kwargs):
"""Tries to call schedule_* method on the driver to retrieve host.
Falls back to schedule(context, topic) if method doesn't exist.
diff --git a/nova/scheduler/multi.py b/nova/scheduler/multi.py
index c6de3f825..59e1212c0 100644
--- a/nova/scheduler/multi.py
+++ b/nova/scheduler/multi.py
@@ -89,6 +89,9 @@ class MultiScheduler(driver.Scheduler):
def schedule_prep_resize(self, *args, **kwargs):
return self.drivers['compute'].schedule_prep_resize(*args, **kwargs)
+ def schedule_create_volume(self, *args, **kwargs):
+ return self.drivers['volume'].schedule_create_volume(*args, **kwargs)
+
def update_service_capabilities(self, service_name, host, capabilities):
# Multi scheduler is only a holder of sub-schedulers, so
# pass the capabilities to the schedulers that matter
diff --git a/nova/scheduler/rpcapi.py b/nova/scheduler/rpcapi.py
index 84d0286a2..8ff564a59 100644
--- a/nova/scheduler/rpcapi.py
+++ b/nova/scheduler/rpcapi.py
@@ -41,6 +41,7 @@ class SchedulerAPI(nova.openstack.common.rpc.proxy.RpcProxy):
1.4 - Remove update_db from prep_resize
1.5 - Add reservations argument to prep_resize()
1.6 - Remove reservations argument to run_instance()
+ 1.7 - Add create_volume() method, remove topic from live_migration()
'''
BASE_RPC_API_VERSION = '1.0'
@@ -73,14 +74,21 @@ class SchedulerAPI(nova.openstack.common.rpc.proxy.RpcProxy):
return self.call(ctxt, self.make_msg('show_host_resources', host=host))
def live_migration(self, ctxt, block_migration, disk_over_commit,
- instance, dest, topic):
+ instance, dest):
# NOTE(comstud): Call vs cast so we can get exceptions back, otherwise
# this call in the scheduler driver doesn't return anything.
instance_p = jsonutils.to_primitive(instance)
return self.call(ctxt, self.make_msg('live_migration',
block_migration=block_migration,
disk_over_commit=disk_over_commit, instance=instance_p,
- dest=dest, topic=topic), version='1.3')
+ dest=dest), version='1.7')
+
+ def create_volume(self, ctxt, volume_id, snapshot_id, reservations):
+ self.cast(ctxt,
+ self.make_msg('create_volume',
+ volume_id=volume_id, snapshot_id=snapshot_id,
+ reservations=reservations),
+ version='1.7')
def update_service_capabilities(self, ctxt, service_name, host,
capabilities):
diff --git a/nova/scheduler/simple.py b/nova/scheduler/simple.py
index f8a1e4154..273bb2cf8 100644
--- a/nova/scheduler/simple.py
+++ b/nova/scheduler/simple.py
@@ -54,7 +54,8 @@ class SimpleScheduler(chance.ChanceScheduler):
super(SimpleScheduler, self).schedule_run_instance(context,
request_spec, reservations, *_args, **_kwargs)
- def schedule_create_volume(self, context, volume_id, *_args, **_kwargs):
+ def schedule_create_volume(self, context, volume_id, snapshot_id,
+ reservations):
"""Picks a host that is up and has the fewest volumes."""
deprecated.warn(_('nova-volume functionality is deprecated in Folsom '
'and will be removed in Grizzly. Volumes are now handled '
@@ -72,7 +73,8 @@ class SimpleScheduler(chance.ChanceScheduler):
if not utils.service_is_up(service):
raise exception.WillNotSchedule(host=host)
driver.cast_to_volume_host(context, host, 'create_volume',
- volume_id=volume_id, **_kwargs)
+ volume_id=volume_id, snapshot_id=snapshot_id,
+ reservations=reservations)
return None
results = db.service_get_all_volume_sorted(elevated)
@@ -86,7 +88,8 @@ class SimpleScheduler(chance.ChanceScheduler):
raise exception.NoValidHost(reason=msg)
if utils.service_is_up(service) and not service['disabled']:
driver.cast_to_volume_host(context, service['host'],
- 'create_volume', volume_id=volume_id, **_kwargs)
+ 'create_volume', volume_id=volume_id,
+ snapshot_id=snapshot_id, reservations=reservations)
return None
msg = _("Is the appropriate service running?")
raise exception.NoValidHost(reason=msg)