1
# Copyright (c) 2011 OpenStack, LLC.
4
# Licensed under the Apache License, Version 2.0 (the "License"); you may
5
# not use this file except in compliance with the License. You may obtain
6
# a copy of the License at
8
# http://www.apache.org/licenses/LICENSE-2.0
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
# License for the specific language governing permissions and limitations
16
Least Cost is an algorithm for choosing which host machines to
17
provision a set of resources to. The input is a WeightedHost object which
18
is decided upon by a set of objective-functions, called the 'cost-functions'.
19
The WeightedHost contains a combined weight for each cost-function.
21
The cost-function and weights are tabulated, and the host with the least cost
22
is then selected for provisioning.
25
from nova import flags
26
from nova.openstack.common import cfg
27
from nova.openstack.common import log as logging
30
LOG = logging.getLogger(__name__)
33
cfg.ListOpt('least_cost_functions',
35
'nova.scheduler.least_cost.compute_fill_first_cost_fn'
37
help='Which cost functions the LeastCostScheduler should use'),
38
cfg.FloatOpt('noop_cost_fn_weight',
40
help='How much weight to give the noop cost function'),
41
cfg.FloatOpt('compute_fill_first_cost_fn_weight',
43
help='How much weight to give the fill-first cost function. '
44
'A negative value will reverse behavior: '
49
FLAGS.register_opts(least_cost_opts)
51
# TODO(sirp): Once we have enough of these rules, we can break them out into a
52
# cost_functions.py file (perhaps in a least_cost_scheduler directory)
55
class WeightedHost(object):
56
"""Reduced set of information about a host that has been weighed.
57
This is an attempt to remove some of the ad-hoc dict structures
60
def __init__(self, weight, host_state=None):
62
self.host_state = host_state
65
x = dict(weight=self.weight)
67
x['host'] = self.host_state.host
72
return "WeightedHost host: %s" % self.host_state.host
73
return "WeightedHost with no host_state"
76
def noop_cost_fn(host_state, weighing_properties):
77
"""Return a pre-weight cost of 1 for each host"""
81
def compute_fill_first_cost_fn(host_state, weighing_properties):
82
"""More free ram = higher weight. So servers with less free
83
ram will be preferred.
85
Note: the weight for this function in default configuration
86
is -1.0. With a -1.0 this function runs in reverse, so systems
87
with the most free memory will be preferred.
89
return host_state.free_ram_mb
92
def weighted_sum(weighted_fns, host_states, weighing_properties):
93
"""Use the weighted-sum method to compute a score for an array of objects.
95
Normalize the results of the objective-functions so that the weights are
96
meaningful regardless of objective-function's range.
98
:param host_list: ``[(host, HostInfo()), ...]``
99
:param weighted_fns: list of weights and functions like::
101
[(weight, objective-functions), ...]
103
:param weighing_properties: an arbitrary dict of values that can
106
:returns: a single WeightedHost object which represents the best
110
min_score, best_host = None, None
111
for host_state in host_states:
112
score = sum(weight * fn(host_state, weighing_properties)
113
for weight, fn in weighted_fns)
114
if min_score is None or score < min_score:
115
min_score, best_host = score, host_state
117
return WeightedHost(min_score, host_state=best_host)