972cdef50c
Add decorations where required. There are roughly a dozen classes in Neutron that define abstract methods or properties but are not decorated with @six.add_metaclass(abc.ABCMeta). Without this decoration, children can be created without defining the required methods or properties. Decorating RBACColumns in db/rbac_db_models.py causes failures and will be reported separately. Decorating unit tests is of dubious benifit and should be addressed separately (if at all). There are also several more places where metaclassing isn't correct, to be taken care of in follow-on patches. For example, BaseScheduler is using the fact the None doesn't have a filter_agents() method, which gives developers confusing error messages when they incorrectly implement the interface, and they won't see any error until schedule() is called. As an aside, the docstring for this base class is also incorrect. Change-Id: I2b2cce37d9b0d40559a715a7d510a969b8ba9963 Closes-Bug: #1577648
78 lines
2.8 KiB
Python
78 lines
2.8 KiB
Python
# Copyright (c) 2015 OpenStack Foundation.
|
|
# 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.
|
|
|
|
import abc
|
|
from operator import attrgetter
|
|
import random
|
|
|
|
import six
|
|
|
|
|
|
@six.add_metaclass(abc.ABCMeta)
|
|
class BaseScheduler(object):
|
|
"""The base scheduler (agnostic to resource type).
|
|
Child classes of BaseScheduler must define the
|
|
self.resource_filter to filter agents of
|
|
particular type.
|
|
"""
|
|
resource_filter = None
|
|
|
|
@abc.abstractmethod
|
|
def select(self, plugin, context, resource_hostable_agents,
|
|
resource_hosted_agents, num_agents_needed):
|
|
"""Return a subset of agents based on the specific scheduling logic."""
|
|
|
|
def schedule(self, plugin, context, resource):
|
|
"""Select and bind agents to a given resource."""
|
|
if not self.resource_filter:
|
|
return
|
|
# filter the agents that can host the resource
|
|
filtered_agents_dict = self.resource_filter.filter_agents(
|
|
plugin, context, resource)
|
|
num_agents = filtered_agents_dict['n_agents']
|
|
hostable_agents = filtered_agents_dict['hostable_agents']
|
|
hosted_agents = filtered_agents_dict['hosted_agents']
|
|
chosen_agents = self.select(plugin, context, hostable_agents,
|
|
hosted_agents, num_agents)
|
|
# bind the resource to the agents
|
|
self.resource_filter.bind(context, chosen_agents, resource['id'])
|
|
return chosen_agents
|
|
|
|
|
|
class BaseChanceScheduler(BaseScheduler):
|
|
"""Choose agents randomly."""
|
|
|
|
def __init__(self, resource_filter):
|
|
self.resource_filter = resource_filter
|
|
|
|
def select(self, plugin, context, resource_hostable_agents,
|
|
resource_hosted_agents, num_agents_needed):
|
|
chosen_agents = random.sample(resource_hostable_agents,
|
|
num_agents_needed)
|
|
return chosen_agents
|
|
|
|
|
|
class BaseWeightScheduler(BaseScheduler):
|
|
"""Choose agents based on load."""
|
|
|
|
def __init__(self, resource_filter):
|
|
self.resource_filter = resource_filter
|
|
|
|
def select(self, plugin, context, resource_hostable_agents,
|
|
resource_hosted_agents, num_agents_needed):
|
|
chosen_agents = sorted(resource_hostable_agents,
|
|
key=attrgetter('load'))[0:num_agents_needed]
|
|
return chosen_agents
|