Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions nova/scheduler/weights/affinity.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ def _weigh_object(self, host_state, request_spec):
class ServerGroupSoftAffinityWeigher(_SoftAffinityWeigherBase):
policy_name = 'soft-affinity'
warning_sent = False
_SHARD_PREFIX = 'vc-'

def weight_multiplier(self):
if (CONF.filter_scheduler.soft_affinity_weight_multiplier < 0 and
Expand All @@ -70,6 +71,39 @@ def weight_multiplier(self):

return CONF.filter_scheduler.soft_affinity_weight_multiplier

def _weigh_object(self, host_state, request_spec):
weight = super(ServerGroupSoftAffinityWeigher, self)._weigh_object(
host_state, request_spec)

# if the host contained servers from the same group, return that weight
if weight:
return weight

# get shards of the host
host_shard_aggrs = [aggr for aggr in host_state.aggregates
if aggr.name.startswith(self._SHARD_PREFIX)]
if not host_shard_aggrs:
LOG.warning('No aggregates found for host %(host)s.',
{'host': host_state.host})
return 0

if len(host_shard_aggrs) > 1:
LOG.warning('More than one host aggregates found for '
'host %(host)s, selecting first.',
{'host': host_state.host})
host_shard_aggr = host_shard_aggrs[0]

group_hosts = None
if request_spec.instance_group and request_spec.instance_group.hosts:
group_hosts = set(request_spec.instance_group.hosts)
if not group_hosts:
return 0
# group_hosts doesn't contain our host, because otherwise we would
# have returned a weighed already as we would have instances
if group_hosts & set(host_shard_aggr.hosts):
return 0.5
return 0


class ServerGroupSoftAntiAffinityWeigher(_SoftAffinityWeigherBase):
policy_name = 'soft-anti-affinity'
Expand Down
44 changes: 35 additions & 9 deletions nova/tests/unit/scheduler/weights/test_weights_affinity.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ def setUp(self):
self.weight_handler = weights.HostWeightHandler()
self.weighers = []

def _get_weighed_host(self, hosts, policy, group='default'):
def _get_weighed_host(self, hosts, policy, group='default',
expected_host=None, match_host=False):
if group == 'default':
members = ['member1', 'member2', 'member3', 'member4', 'member5',
'member6', 'member7']
Expand All @@ -38,17 +39,27 @@ def _get_weighed_host(self, hosts, policy, group='default'):
request_spec = objects.RequestSpec(
instance_group=objects.InstanceGroup(
policy=policy,
members=members))
return self.weight_handler.get_weighed_objects(self.weighers,
hosts,
request_spec)[0]
members=members,
hosts=[h.host for h in hosts]))
hosts = self.weight_handler.get_weighed_objects(self.weighers,
hosts,
request_spec)
if not match_host:
return hosts[0]
else:
for host in hosts:
if host.obj.host == expected_host:
return host

def _get_all_hosts(self):
aggs1 = [objects.Aggregate(id=1, name='vc-a-1', hosts=['host1'])]
aggs2 = [objects.Aggregate(id=2, name='vc-a-2', hosts=['host3']),
objects.Aggregate(id=2, name='vc-a-3', hosts=['host4'])]
host_values = [
('host1', 'node1', {'instances': {
'member1': mock.sentinel,
'instance13': mock.sentinel
}}),
}, 'aggregates': aggs1}),
('host2', 'node2', {'instances': {
'member2': mock.sentinel,
'member3': mock.sentinel,
Expand All @@ -60,12 +71,12 @@ def _get_all_hosts(self):
}}),
('host3', 'node3', {'instances': {
'instance15': mock.sentinel
}}),
}, 'aggregates': aggs2}),
('host4', 'node4', {'instances': {
'member6': mock.sentinel,
'member7': mock.sentinel,
'instance16': mock.sentinel
}})]
}, 'aggregates': aggs2})]
return [fakes.FakeHostState(host, node, values)
for host, node, values in host_values]

Expand Down Expand Up @@ -105,6 +116,20 @@ def test_soft_affinity_weight_multiplier_positive_value(self):
expected_weight=2.0,
expected_host='host2')

def test_soft_affinity_weight_multiplier_same_shards(self):
"""For host, which does not contain servers of server-group,
but in same shard as the servers in the server-group, weight
is 0.5. Due to normalization smallest weight become 0.0
"""
self.flags(soft_affinity_weight_multiplier=2.0,
group='filter_scheduler')
expected_weight = 0.0
hostinfo_list = self._get_all_hosts()
weighed_host = self._get_weighed_host(hostinfo_list,
policy='soft-affinity', group='default',
expected_host='host3', match_host=True)
self.assertEqual(expected_weight, weighed_host.weight)

@mock.patch.object(affinity, 'LOG')
def test_soft_affinity_weight_multiplier_negative_value(self, mock_log):
self.flags(soft_affinity_weight_multiplier=-1.0,
Expand All @@ -116,7 +141,8 @@ def test_soft_affinity_weight_multiplier_negative_value(self, mock_log):
self._do_test(policy='soft-affinity',
expected_weight=0.0,
expected_host='host3')
self.assertEqual(1, mock_log.warning.call_count)
# one from _weigh_object() and two from weight_multiplier()
self.assertEqual(3, mock_log.warning.call_count)

def test_running_twice(self):
"""Run the weighing twice for different groups each run
Expand Down