Skip to content

Commit

Permalink
Pep8 fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
rconradharris committed May 17, 2011
1 parent d6fbe41 commit 439787e
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 23 deletions.
3 changes: 3 additions & 0 deletions nova/exception.py
Expand Up @@ -460,15 +460,18 @@ class FlavorNotFound(NotFound):
class ZoneNotFound(NotFound):
message = _("Zone %(zone_id)s could not be found.")


# TODO(sirp): move these into the schedule classes since they are internal?
class SchedulerHostFilterDriverNotFound(NotFound):
message = _("Scheduler Host Filter Driver %(driver_name)s could"
" not be found.")


class SchedulerCostFunctionNotFound(NotFound):
message = _("Scheduler cost function %(cost_fn_str)s could"
" not be found.")


class SchedulerWeightFlagNotFound(NotFound):
message = _("Scheduler weight flag not found: %(flag_name)s")

Expand Down
30 changes: 21 additions & 9 deletions nova/scheduler/least_cost.py
Expand Up @@ -13,16 +13,19 @@
# License for the specific language governing permissions and limitations
# under the License.
"""
Helpful docstring here
Least Cost Scheduler is a mechanism for choosing which host machines to
provision a set of resources to. The input of the least-cost-scheduler is a
set of objective-functions, called the 'cost-functions', a weight for each
cost-function, and a list of candidate hosts (gathered via FilterHosts).
The cost-function and weights are tabulated, and the host with the least cost
is then selected for provisioning.
"""

import collections

from nova import flags
from nova import log as logging
# TODO(sirp): this should be just `zone_aware` to match naming scheme
# TODO(sirp): perhaps all zone-aware stuff should go under a `zone_aware`
# module
from nova.scheduler import zone_aware_scheduler
from nova import utils

Expand All @@ -38,13 +41,17 @@
# cost_functions.py file (perhaps in a least_cost_scheduler directory)
flags.DEFINE_integer('noop_cost_fn_weight', 1,
'How much weight to give the noop cost function')


def noop_cost_fn(host):
"""Return a pre-weight cost of 1 for each host"""
return 1


flags.DEFINE_integer('fill_first_cost_fn_weight', 1,
'How much weight to give the fill-first cost function')


def fill_first_cost_fn(host):
"""Prefer hosts that have less ram available, filter_hosts will exclude
hosts that don't have enough ram"""
Expand All @@ -68,7 +75,7 @@ def get_cost_fns(self):
except exception.ClassNotFound:
raise exception.SchedulerCostFunctionNotFound(
cost_fn_str=cost_fn_str)

try:
weight = getattr(FLAGS, "%s_weight" % cost_fn.__name__)
except AttributeError:
Expand All @@ -82,17 +89,22 @@ def get_cost_fns(self):
def weigh_hosts(self, num, request_spec, hosts):
"""Returns a list of dictionaries of form:
[ {weight: weight, hostname: hostname} ]"""

# FIXME(sirp): weigh_hosts should handle more than just instances
hostnames = [hostname for hostname, _ in hosts]
hostnames = [hostname for hostname, caps in hosts]

cost_fns = self.get_cost_fns()
costs = weighted_sum(domain=hosts, weighted_fns=cost_fns)

weighted = []
weight_log = []
for cost, hostname in zip(costs, hostnames):
weight_log.append("%s: %s" % (hostname, "%.2f" % cost))
weight_dict = dict(weight=cost, hostname=hostname)
weighted.append(weight_dict)
return weighted

LOG.debug(_("Weighted Costs => %s") % weight_log)
return weighted


def normalize_list(L):
Expand All @@ -110,7 +122,7 @@ def weighted_sum(domain, weighted_fns, normalize=True):
"""Use the weighted-sum method to compute a score for an array of objects.
Normalize the results of the objective-functions so that the weights are
meaningful regardless of objective-function's range.
domain - input to be scored
weighted_fns - list of weights and functions like:
[(weight, objective-functions)]
Expand Down
11 changes: 6 additions & 5 deletions nova/scheduler/zone_aware_scheduler.py
Expand Up @@ -80,7 +80,7 @@ def provision_resource(self, context, item, instance_id, kwargs):
LOG.debug(_("Casted to compute %(host)s for run_instance")
% locals())
else:
# TODO(sandy) Provision in child zone ...
# TODO(sandy) Provision in child zone ...
LOG.warning(_("Provision to Child Zone not supported (yet)")
% locals())
pass
Expand Down Expand Up @@ -117,11 +117,11 @@ def _schedule(self, context, topic, request_spec, *args, **kwargs):
# Filter local hosts based on requirements ...
host_list = self.filter_hosts(num_instances, request_spec)

# then weigh the selected hosts.
# weighted = [{weight=weight, name=hostname}, ...]

# TODO(sirp): weigh_hosts should also be a function of 'topic' or
# resources, so that we can apply different objective functions to it

# then weigh the selected hosts.
# weighted = [{weight=weight, name=hostname}, ...]
weighted = self.weigh_hosts(num_instances, request_spec, host_list)

# Next, tack on the best weights from the child zones ...
Expand All @@ -145,8 +145,9 @@ def filter_hosts(self, num, request_spec):
"""Derived classes must override this method and return
a list of hosts in [(hostname, capability_dict)] format."""
# NOTE(sirp): The default logic is the equivalent to AllHostsFilter
service_states = self.zone_manager.service_states
return [(host, services)
for host, services in self.zone_manager.service_states.iteritems()]
for host, services in service_states.iteritems()]

def weigh_hosts(self, num, request_spec, hosts):
"""Derived classes may override this to provide more sophisticated
Expand Down
5 changes: 3 additions & 2 deletions nova/test.py
Expand Up @@ -212,9 +212,10 @@ def raise_assertion(msg):
for key in d1keys:
d1value = d1[key]
d2value = d2[key]

try:
within_tolerance = abs(float(d1value) - float(d2value)) < tolerance
error = abs(float(d1value) - float(d2value))
within_tolerance = error <= tolerance
except ValueError:
# If both values aren't convertable to float, just ignore
within_tolerance = False
Expand Down
18 changes: 11 additions & 7 deletions nova/tests/test_least_cost_scheduler.py
Expand Up @@ -30,6 +30,7 @@ def __init__(self, host_id, free_ram, io):
self.free_ram = free_ram
self.io = io


class WeightedSumTestCase(test.TestCase):
def test_empty_domain(self):
domain = []
Expand All @@ -50,21 +51,23 @@ def test_basic_costing(self):
(2, lambda h: h.io), # Avoid high I/O
]

costs = least_cost.weighted_sum(domain=hosts, weighted_fns=weighted_fns)
costs = least_cost.weighted_sum(
domain=hosts, weighted_fns=weighted_fns)

# Each 256 MB unit of free-ram contributes 0.5 points by way of:
# cost = weight * (score/max_score) = 1 * (256/512) = 0.5
# Each 100 iops of IO adds 0.5 points by way of:
# cost = 2 * (100/400) = 2 * 0.25 = 0.5
expected = [1.5, 2.5, 1.5]
self.assertEqual(expected, costs)
self.assertEqual(expected, costs)


# TODO(sirp): unify this with test_host_filter tests? possibility of sharing
# test setup code
class FakeZoneManager:
pass


class LeastCostSchedulerTestCase(test.TestCase):
def _host_caps(self, multiplier):
# Returns host capabilities in the following way:
Expand Down Expand Up @@ -116,7 +119,6 @@ def tearDown(self):
#FLAGS.default_host_filter_driver = self.old_flag
super(LeastCostSchedulerTestCase, self).tearDown()


def assertWeights(self, expected, num, request_spec, hosts):
weighted = self.sched.weigh_hosts(num, request_spec, hosts)
self.assertDictListMatch(weighted, expected, approx_equal=True)
Expand All @@ -138,8 +140,9 @@ def test_noop_cost_fn(self):
num = 1
request_spec = {}
hosts = self.sched.filter_hosts(num, request_spec)

expected = [ dict(weight=1, hostname=hostname) for hostname, caps in hosts]

expected = [dict(weight=1, hostname=hostname)
for hostname, caps in hosts]
self.assertWeights(expected, num, request_spec, hosts)

def test_cost_fn_weights(self):
Expand All @@ -152,7 +155,8 @@ def test_cost_fn_weights(self):
request_spec = {}
hosts = self.sched.filter_hosts(num, request_spec)

expected = [ dict(weight=2, hostname=hostname) for hostname, caps in hosts]
expected = [dict(weight=2, hostname=hostname)
for hostname, caps in hosts]
self.assertWeights(expected, num, request_spec, hosts)

def test_fill_first_cost_fn(self):
Expand All @@ -164,7 +168,7 @@ def test_fill_first_cost_fn(self):
num = 1
request_spec = {}
hosts = self.sched.filter_hosts(num, request_spec)

expected = []
for idx, (hostname, caps) in enumerate(hosts):
# Costs are normalized so over 10 hosts, each host with increasing
Expand Down

0 comments on commit 439787e

Please sign in to comment.