Files
python-ganttclient/nova/scheduler/base_scheduler.py
Johannes Erdfelt 4abdde7af7 Restructure host filtering to be easier to use.
The original design for host filtering in the scheduler required the
entire filtering process be contained in a single class; contrast this
with the design for weighting the hosts, which allowed you to specify
a list of functions that would apply various weighting factors to the
hosts.

This commit modifies the filtering process to resemble the way that
the weighting process is designed. Filters can now be small, focused
classes, and you specify which filters to apply by setting the
'FLAGS.default_host_filters' flag to a list of the filter classes
that match your needs.

This is a port of the code from Launchpad, where it was orphaned:

https://code.launchpad.net/~ed-leafe/nova/scheduler-multifilter/+merge/72478

Change-Id: I5f3eff6f21409a9f0eddda3392e9ff9d03039ebe
2011-10-04 23:03:43 +00:00

95 lines
3.8 KiB
Python

# Copyright (c) 2011 Openstack, LLC.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
The BaseScheduler is the base class Scheduler for creating instances
across zones. There are two expansion points to this class for:
1. Assigning Weights to hosts for requested instances
2. Filtering Hosts based on required instance capabilities
"""
from nova import flags
from nova import log as logging
from nova.scheduler import abstract_scheduler
from nova.scheduler import host_filter
FLAGS = flags.FLAGS
flags.DEFINE_boolean('spread_first', False,
'Use a spread-first zone scheduler strategy')
LOG = logging.getLogger('nova.scheduler.base_scheduler')
class BaseScheduler(abstract_scheduler.AbstractScheduler):
"""Base class for creating Schedulers that can work across any nova
deployment, from simple designs to multiply-nested zones.
"""
def filter_hosts(self, topic, request_spec, hosts=None):
"""Filter the full host list (from the ZoneManager)"""
filters = request_spec.get('filter')
if filters is None:
# Not specified; use the default
filters = FLAGS.default_host_filters
if not isinstance(filters, (list, tuple)):
filters = [filters]
if hosts is None:
# Get the full list (only considering 'compute' services)
all_hosts = self.zone_manager.service_states.iteritems()
hosts = [(host, services["compute"])
for host, services in all_hosts
if "compute" in services]
# Make sure that the requested filters are legitimate.
selected_filters = host_filter.choose_host_filters(filters)
# TODO(sandy): We're only using InstanceType-based specs
# currently. Later we'll need to snoop for more detailed
# host filter requests.
instance_type = request_spec.get("instance_type", None)
if instance_type is None:
# No way to select; return the specified hosts
return hosts
for selected_filter in selected_filters:
query = selected_filter.instance_type_to_filter(instance_type)
hosts = selected_filter.filter_hosts(hosts, query)
return hosts
def weigh_hosts(self, request_spec, hosts):
"""Derived classes may override this to provide more sophisticated
scheduling objectives
"""
# Make sure if there are compute hosts to serve the request.
if not hosts:
return []
# NOTE(sirp): The default logic is the same as the NoopCostFunction
hosts = [dict(weight=1, hostname=hostname, capabilities=capabilities)
for hostname, capabilities in hosts]
# NOTE(Vek): What we actually need to return is enough hosts
# for all the instances!
num_instances = request_spec.get('num_instances', 1)
instances = []
while num_instances > len(hosts):
instances.extend(hosts)
num_instances -= len(hosts)
if num_instances > 0:
instances.extend(hosts[:num_instances])
# Adjust the weights for a spread-first strategy
if FLAGS.spread_first:
for i, host in enumerate(hosts):
host['weight'] = i + 1
return instances