start of zone_aware_scheduler test

This commit is contained in:
Sandy Walsh
2011-05-11 11:12:31 -07:00
parent 74aff1dbd2
commit 91b8ac3f98
2 changed files with 58 additions and 12 deletions

View File

@@ -111,6 +111,45 @@ def _process(func, zone):
return func(nova, zone)
def call_zone_method(context, method, errors_to_ignore=None, *args, **kwargs):
"""Returns a list of (zone, call_result) objects."""
if not isinstance(errors_to_ignore, (list, tuple)):
# This will also handle the default None
errors_to_ignore = [errors_to_ignore]
pool = greenpool.GreenPool()
results = []
for zone in db.zone_get_all(context):
try:
nova = novaclient.OpenStack(zone.username, zone.password,
zone.api_url)
nova.authenticate()
except novaclient.exceptions.BadRequest, e:
url = zone.api_url
LOG.warn(_("Failed request to zone; URL=%(url)s: %(e)s")
% locals())
#TODO (dabo) - add logic for failure counts per zone,
# with escalation after a given number of failures.
continue
zone_method = getattr(nova.zones, method)
def _error_trap(*args, **kwargs):
try:
return zone_method(*args, **kwargs)
except Exception as e:
if type(e) in errors_to_ignore:
return None
# TODO (dabo) - want to be able to re-raise here.
# Returning a string now; raising was causing issues.
# raise e
return "ERROR", "%s" % e
res = pool.spawn(_error_trap, *args, **kwargs)
results.append((zone, res))
pool.waitall()
return [(zone.id, res.wait()) for zone, res in results]
def child_zone_helper(zone_list, func):
"""Fire off a command to each zone in the list.
The return is [novaclient return objects] from each child zone.

View File

@@ -24,11 +24,12 @@ import operator
from nova import log as logging
from nova.scheduler import api
from nova.scheduler import driver
LOG = logging.getLogger('nova.scheduler.zone_aware_scheduler')
class ZoneAwareScheduler(object):
class ZoneAwareScheduler(driver.Scheduler):
"""Base class for creating Zone Aware Schedulers."""
def _call_zone_method(self, context, method, specs):
@@ -42,23 +43,29 @@ class ZoneAwareScheduler(object):
anything about the children."""
return self._schedule(context, "compute", *args, **kwargs)
def schedule(self, context, topic, *args, **kwargs):
def schedule(self, context, topic, *args, **kwargs):
"""The schedule() contract requires we return the one
best-suited host for this request.
"""
res = self._schedule(context, topic, *args, **kwargs)
# TODO(sirp): should this be a host object rather than a weight-dict?
return res[0]
def _schedule(self, context, topic, *args, **kwargs):
"""Returns a list of hosts that meet the required specs,
ordered by their fitness.
"""
#TODO(sandy): extract these from args.
num_instances = 1
specs = {}
# Filter local hosts based on requirements ...
host_list = self.filter_hosts()
host_list = self.filter_hosts(num_instances, specs)
# then weigh the selected hosts.
# weighted = [ { 'weight':#, 'name':host, ...}, ]
weighted = self.weight_hosts(host_list)
weighted = self.weigh_hosts(num_instances, specs, host_list)
# Next, tack on the best weights from the child zones ...
child_results = self._call_zone_method(context, "select",
@@ -77,12 +84,12 @@ class ZoneAwareScheduler(object):
weighted.sort(key=operator.itemgetter('weight'))
return weighted
def filter_hosts(self):
"""Derived classes must override this method and return
a list of hosts in [?] format."""
raise NotImplemented()
def filter_hosts(self, num, specs):
"""Derived classes must override this method and return
a list of hosts in [?] format."""
raise NotImplemented()
def weigh_hosts(self, hosts):
"""Derived classes must override this method and return
a lists of hosts in [?] format."""
raise NotImplemented()
def weigh_hosts(self, num, specs, hosts):
"""Derived classes must override this method and return
a lists of hosts in [?] format."""
raise NotImplemented()