summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSandy Walsh <sandy.walsh@rackspace.com>2011-03-18 06:38:02 -0700
committerSandy Walsh <sandy.walsh@rackspace.com>2011-03-18 06:38:02 -0700
commit0bc393bd1a0b722b08a2834873a8a825b86035c2 (patch)
treea5cadb88c489e8cf369906e6f9c06c7043657ba3
parent25199b6b93d17ff7dc192306e44932969846d9b6 (diff)
enable_zone_routing flag
-rw-r--r--nova/compute/api.py20
-rw-r--r--nova/scheduler/api.py60
2 files changed, 51 insertions, 29 deletions
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 9fb4c8ae2..96538dd00 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -343,7 +343,7 @@ class API(base.Base):
rv = self.db.instance_update(context, instance_id, kwargs)
return dict(rv.iteritems())
- #@scheduler_api.reroute_if_not_found("delete")
+ @scheduler_api.reroute("delete")
def delete(self, context, instance_id):
LOG.debug(_("Going to try to terminate %s"), instance_id)
try:
@@ -373,12 +373,10 @@ class API(base.Base):
def get(self, context, instance_id):
"""Get a single instance with the given ID."""
- LOG.debug("*** COMPUTE.API::GET")
rv = self.db.instance_get(context, instance_id)
- LOG.debug("*** COMPUTE.API::GET OUT CLEAN")
return dict(rv.iteritems())
- @scheduler_api.reroute_if_not_found("get")
+ @scheduler_api.reroute_compute("get")
def routing_get(self, context, instance_id):
"""Use this method instead of get() if this is the only
operation you intend to to. It will route to novaclient.get
@@ -502,17 +500,17 @@ class API(base.Base):
"args": {"topic": FLAGS.compute_topic,
"instance_id": instance_id, }},)
- #@scheduler_api.reroute_if_not_found("pause")
+ @scheduler_api.reroute_compute("pause")
def pause(self, context, instance_id):
"""Pause the given instance."""
self._cast_compute_message('pause_instance', context, instance_id)
- #@scheduler_api.reroute_if_not_found("unpause")
+ @scheduler_api.reroute_compute("unpause")
def unpause(self, context, instance_id):
"""Unpause the given instance."""
self._cast_compute_message('unpause_instance', context, instance_id)
- #@scheduler_api.reroute_if_not_found("diagnostics")
+ @scheduler_api.reroute_compute("diagnostics")
def get_diagnostics(self, context, instance_id):
"""Retrieve diagnostics for the given instance."""
return self._call_compute_message(
@@ -524,22 +522,22 @@ class API(base.Base):
"""Retrieve actions for the given instance."""
return self.db.instance_get_actions(context, instance_id)
- #@scheduler_api.reroute_if_not_found("suspend")
+ @scheduler_api.reroute_compute("suspend")
def suspend(self, context, instance_id):
"""suspend the instance with instance_id"""
self._cast_compute_message('suspend_instance', context, instance_id)
- #@scheduler_api.reroute_if_not_found("resume")
+ @scheduler_api.reroute_compute("resume")
def resume(self, context, instance_id):
"""resume the instance with instance_id"""
self._cast_compute_message('resume_instance', context, instance_id)
- #@scheduler_api.reroute_if_not_found("rescue")
+ @scheduler_api.reroute_compute("rescue")
def rescue(self, context, instance_id):
"""Rescue the given instance."""
self._cast_compute_message('rescue_instance', context, instance_id)
- #@scheduler_api.reroute_if_not_found("unrescue")
+ @scheduler_api.reroute_compute("unrescue")
def unrescue(self, context, instance_id):
"""Unrescue the given instance."""
self._cast_compute_message('unrescue_instance', context, instance_id)
diff --git a/nova/scheduler/api.py b/nova/scheduler/api.py
index 190eb363e..90b92d7ed 100644
--- a/nova/scheduler/api.py
+++ b/nova/scheduler/api.py
@@ -28,6 +28,10 @@ import novaclient.client as client
from eventlet import greenpool
FLAGS = flags.FLAGS
+flags.DEFINE_bool('enable_zone_routing',
+ False,
+ 'When True, routing to child zones will occur.')
+
LOG = logging.getLogger('nova.scheduler.api')
@@ -83,7 +87,8 @@ def _wrap_method(function, self):
def _process(func, zone):
- """Worker stub for green thread pool"""
+ """Worker stub for green thread pool. Give the worker
+ an authenticated nova client and zone info."""
nova = client.OpenStackClient(zone.username, zone.password,
zone.api_url)
nova.authenticate()
@@ -91,36 +96,42 @@ def _process(func, zone):
def child_zone_helper(zone_list, func):
+ """Fire off a command to each zone in the list."""
green_pool = greenpool.GreenPool()
return [result for result in green_pool.imap(
_wrap_method(_process, func), zone_list)]
-def _issue_novaclient_command(nova, zone, method_name, instance_id):
- server = None
+def _issue_novaclient_command(nova, zone, collection, method_name, \
+ item_id):
+ """Use novaclient to issue command to a single child zone.
+ One of these will be run in parallel for each child zone."""
+ item = None
try:
- manager = getattr(nova, "servers")
- if isinstance(instance_id, int) or instance_id.isdigit():
- server = manager.get(int(instance_id))
+ manager = getattr(nova, collection)
+ if isinstance(item_id, int) or item_id.isdigit():
+ item = manager.get(int(item_id))
else:
- server = manager.find(name=instance_id)
+ item = manager.find(name=item_id)
except novaclient.NotFound:
url = zone.api_url
- LOG.debug(_("Instance %(instance_id)s not found on '%(url)s'" %
+ LOG.debug(_("%(collection)s '%(item_id)s' not found on '%(url)s'" %
locals()))
return
- return getattr(server, method_name)()
+ return getattr(item, method_name)()
-def wrap_novaclient_function(f, method_name, instance_id):
+def wrap_novaclient_function(f, collection, method_name, item_id):
+ """Appends collection, method_name and item_id to the incoming
+ (nova, zone) call from child_zone_helper."""
def inner(nova, zone):
- return f(nova, zone, method_name, instance_id)
+ return f(nova, zone, collection, method_name, item_id)
return inner
-class reroute_if_not_found(object):
+class reroute_compute(object):
"""Decorator used to indicate that the method should
delegate the call the child zones if the db query
can't find anything.
@@ -130,19 +141,32 @@ class reroute_if_not_found(object):
def __call__(self, f):
def wrapped_f(*args, **kwargs):
- LOG.debug("***REROUTE-3: %s / %s" % (args, kwargs))
- context = args[1]
- instance_id = args[2]
+ collection, context, item_id = \
+ self.get_collection_context_and_id()
try:
return f(*args, **kwargs)
except exception.InstanceNotFound, e:
- LOG.debug(_("Instance %(instance_id)s not found "
+ LOG.debug(_("Instance %(item_id)s not found "
"locally: '%(e)s'" % locals()))
+ if not FLAGS.enable_zone_routing:
+ raise
+
zones = db.zone_get_all(context)
+ if not zones:
+ raise
+
result = child_zone_helper(zones,
wrap_novaclient_function(_issue_novaclient_command,
- self.method_name, instance_id))
+ collection, self.method_name, item_id))
LOG.debug("***REROUTE: %s" % result)
- return result
+ return self.unmarshall_result(result)
return wrapped_f
+
+ def get_collection_context_and_id(self, args):
+ """Returns a tuple of (novaclient collection name, security
+ context and resource id. Derived class should override this."""
+ return ("servers", args[1], args[2])
+
+ def unmarshall_result(self, result):
+ return result