start of zone_aware_scheduler test
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user