start of zone_aware_scheduler test
This commit is contained in:
parent
eb0619c91b
commit
3470ed651b
@ -248,11 +248,18 @@ class API(base.Base):
|
|||||||
uid = context.user_id
|
uid = context.user_id
|
||||||
LOG.debug(_("Casting to scheduler for %(pid)s/%(uid)s's"
|
LOG.debug(_("Casting to scheduler for %(pid)s/%(uid)s's"
|
||||||
" instance %(instance_id)s") % locals())
|
" instance %(instance_id)s") % locals())
|
||||||
|
|
||||||
|
# NOTE(sandy): For now we're just going to pass in the
|
||||||
|
# instance_type record to the scheduler. In a later phase
|
||||||
|
# we'll be ripping this whole for-loop out and deferring the
|
||||||
|
# creation of the Instance record. At that point all this will
|
||||||
|
# change.
|
||||||
rpc.cast(context,
|
rpc.cast(context,
|
||||||
FLAGS.scheduler_topic,
|
FLAGS.scheduler_topic,
|
||||||
{"method": "run_instance",
|
{"method": "run_instance",
|
||||||
"args": {"topic": FLAGS.compute_topic,
|
"args": {"topic": FLAGS.compute_topic,
|
||||||
"instance_id": instance_id,
|
"instance_id": instance_id,
|
||||||
|
"instance_type": instance_type,
|
||||||
"availability_zone": availability_zone,
|
"availability_zone": availability_zone,
|
||||||
"injected_files": injected_files}})
|
"injected_files": injected_files}})
|
||||||
|
|
||||||
|
@ -111,6 +111,45 @@ def _process(func, zone):
|
|||||||
return func(nova, 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):
|
def child_zone_helper(zone_list, func):
|
||||||
"""Fire off a command to each zone in the list.
|
"""Fire off a command to each zone in the list.
|
||||||
The return is [novaclient return objects] from each child zone.
|
The return is [novaclient return objects] from each child zone.
|
||||||
|
@ -24,11 +24,12 @@ import operator
|
|||||||
|
|
||||||
from nova import log as logging
|
from nova import log as logging
|
||||||
from nova.scheduler import api
|
from nova.scheduler import api
|
||||||
|
from nova.scheduler import driver
|
||||||
|
|
||||||
LOG = logging.getLogger('nova.scheduler.zone_aware_scheduler')
|
LOG = logging.getLogger('nova.scheduler.zone_aware_scheduler')
|
||||||
|
|
||||||
|
|
||||||
class ZoneAwareScheduler(object):
|
class ZoneAwareScheduler(driver.Scheduler):
|
||||||
"""Base class for creating Zone Aware Schedulers."""
|
"""Base class for creating Zone Aware Schedulers."""
|
||||||
|
|
||||||
def _call_zone_method(self, context, method, specs):
|
def _call_zone_method(self, context, method, specs):
|
||||||
@ -47,18 +48,24 @@ class ZoneAwareScheduler(object):
|
|||||||
best-suited host for this request.
|
best-suited host for this request.
|
||||||
"""
|
"""
|
||||||
res = self._schedule(context, topic, *args, **kwargs)
|
res = self._schedule(context, topic, *args, **kwargs)
|
||||||
|
# TODO(sirp): should this be a host object rather than a weight-dict?
|
||||||
return res[0]
|
return res[0]
|
||||||
|
|
||||||
def _schedule(self, context, topic, *args, **kwargs):
|
def _schedule(self, context, topic, *args, **kwargs):
|
||||||
"""Returns a list of hosts that meet the required specs,
|
"""Returns a list of hosts that meet the required specs,
|
||||||
ordered by their fitness.
|
ordered by their fitness.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
#TODO(sandy): extract these from args.
|
||||||
|
num_instances = 1
|
||||||
|
specs = {}
|
||||||
|
|
||||||
# Filter local hosts based on requirements ...
|
# Filter local hosts based on requirements ...
|
||||||
host_list = self.filter_hosts()
|
host_list = self.filter_hosts(num_instances, specs)
|
||||||
|
|
||||||
# then weigh the selected hosts.
|
# then weigh the selected hosts.
|
||||||
# weighted = [ { 'weight':#, 'name':host, ...}, ]
|
# 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 ...
|
# Next, tack on the best weights from the child zones ...
|
||||||
child_results = self._call_zone_method(context, "select",
|
child_results = self._call_zone_method(context, "select",
|
||||||
@ -77,12 +84,12 @@ class ZoneAwareScheduler(object):
|
|||||||
weighted.sort(key=operator.itemgetter('weight'))
|
weighted.sort(key=operator.itemgetter('weight'))
|
||||||
return weighted
|
return weighted
|
||||||
|
|
||||||
def filter_hosts(self):
|
def filter_hosts(self, num, specs):
|
||||||
"""Derived classes must override this method and return
|
"""Derived classes must override this method and return
|
||||||
a list of hosts in [?] format."""
|
a list of hosts in [?] format."""
|
||||||
raise NotImplemented()
|
raise NotImplemented()
|
||||||
|
|
||||||
def weigh_hosts(self, hosts):
|
def weigh_hosts(self, num, specs, hosts):
|
||||||
"""Derived classes must override this method and return
|
"""Derived classes must override this method and return
|
||||||
a lists of hosts in [?] format."""
|
a lists of hosts in [?] format."""
|
||||||
raise NotImplemented()
|
raise NotImplemented()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user