diff options
| author | Sandy Walsh <sandy.walsh@rackspace.com> | 2011-03-18 06:38:02 -0700 |
|---|---|---|
| committer | Sandy Walsh <sandy.walsh@rackspace.com> | 2011-03-18 06:38:02 -0700 |
| commit | 0bc393bd1a0b722b08a2834873a8a825b86035c2 (patch) | |
| tree | a5cadb88c489e8cf369906e6f9c06c7043657ba3 | |
| parent | 25199b6b93d17ff7dc192306e44932969846d9b6 (diff) | |
enable_zone_routing flag
| -rw-r--r-- | nova/compute/api.py | 20 | ||||
| -rw-r--r-- | nova/scheduler/api.py | 60 |
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 |
