Add new style instance group scheduler filters
Prior to Icehouse, there was a different type of handling of the 'group' scheduler hint that got lost in the completion of the server groups API. This patch completes the code necessary to provide backwards compatibility with the old behavior. Previously, the policy for groups was simply based on what scheduler filters you had enabled. You could have either the affinity or anti-affinity filter enabled and that would be applied to all groups. These filters now act on groups with a policy type of 'legacy'. New filters have been added that can be enabled simultaneously and act based on the policy set on the group via the server group API. DocImpact Change-Id: Ia65c151396415ca48725cb3c756f33efa01d2fe5 Closes-bug: #1296913
This commit is contained in:
parent
ea6d8403bd
commit
2bca0c9011
|
@ -119,10 +119,20 @@ There are some standard filter classes to use (:mod:`nova.scheduler.filters`):
|
|||
* |TypeAffinityFilter| - Only passes hosts that are not already running an
|
||||
instance of the requested type.
|
||||
* |AggregateTypeAffinityFilter| - limits instance_type by aggregate.
|
||||
* |GroupAntiAffinityFilter| - ensures that each instance in group is on a
|
||||
different host.
|
||||
* |GroupAffinityFilter| - ensures that each instance in group is on a same
|
||||
host with one of the instance host in a group.
|
||||
* |ServerGroupAntiAffinityFilter| - This filter implements anti-affinity for a
|
||||
server group. First you must create a server group with a policy of
|
||||
'anti-affinity' via the server groups API. Then, when you boot a new server,
|
||||
provide a scheduler hint of 'group=<uuid>' where <uuid> is the UUID of the
|
||||
server group you created. This will result in the server getting added to the
|
||||
group. When the server gets scheduled, anti-affinity will be enforced among
|
||||
all servers in that group.
|
||||
* |ServerGroupAffinityFilter| - This filter works the same way as
|
||||
ServerGroupAffinityFilter. The difference is that when you create the server
|
||||
group, you should specify a policy of 'affinity'.
|
||||
* |GroupAntiAffinityFilter| - This filter is deprecated in favor of
|
||||
ServerGroupAntiAffinityFilter.
|
||||
* |GroupAffinityFilter| - This filter is deprecated in favor of
|
||||
ServerGroupAffinityFilter.
|
||||
* |AggregateMultiTenancyIsolation| - isolate tenants in specific aggregates.
|
||||
* |AggregateImagePropertiesIsolation| - isolates hosts based on image
|
||||
properties and aggregate metadata.
|
||||
|
|
|
@ -99,15 +99,18 @@ class SimpleCIDRAffinityFilter(AffinityFilter):
|
|||
return True
|
||||
|
||||
|
||||
class GroupAntiAffinityFilter(AffinityFilter):
|
||||
class _GroupAntiAffinityFilter(AffinityFilter):
|
||||
"""Schedule the instance on a different host from a set of group
|
||||
hosts.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(_GroupAntiAffinityFilter, self).__init__()
|
||||
|
||||
def host_passes(self, host_state, filter_properties):
|
||||
# Only invoke the filter is 'anti-affinity' is configured
|
||||
policies = filter_properties.get('group_policies', [])
|
||||
if 'anti-affinity' not in policies:
|
||||
if self.policy_name not in policies:
|
||||
return True
|
||||
|
||||
group_hosts = filter_properties.get('group_hosts') or []
|
||||
|
@ -121,14 +124,29 @@ class GroupAntiAffinityFilter(AffinityFilter):
|
|||
return True
|
||||
|
||||
|
||||
class GroupAffinityFilter(AffinityFilter):
|
||||
class GroupAntiAffinityFilter(_GroupAntiAffinityFilter):
|
||||
def __init__(self):
|
||||
self.policy_name = 'legacy'
|
||||
super(GroupAntiAffinityFilter, self).__init__()
|
||||
|
||||
|
||||
class ServerGroupAntiAffinityFilter(_GroupAntiAffinityFilter):
|
||||
def __init__(self):
|
||||
self.policy_name = 'anti-affinity'
|
||||
super(ServerGroupAntiAffinityFilter, self).__init__()
|
||||
|
||||
|
||||
class _GroupAffinityFilter(AffinityFilter):
|
||||
"""Schedule the instance on to host from a set of group hosts.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(_GroupAffinityFilter, self).__init__()
|
||||
|
||||
def host_passes(self, host_state, filter_properties):
|
||||
# Only invoke the filter is 'affinity' is configured
|
||||
policies = filter_properties.get('group_policies', [])
|
||||
if 'affinity' not in policies:
|
||||
if self.policy_name not in policies:
|
||||
return True
|
||||
|
||||
group_hosts = filter_properties.get('group_hosts', [])
|
||||
|
@ -140,3 +158,15 @@ class GroupAffinityFilter(AffinityFilter):
|
|||
|
||||
# No groups configured
|
||||
return True
|
||||
|
||||
|
||||
class GroupAffinityFilter(_GroupAffinityFilter):
|
||||
def __init__(self):
|
||||
self.policy_name = 'legacy'
|
||||
super(GroupAffinityFilter, self).__init__()
|
||||
|
||||
|
||||
class ServerGroupAffinityFilter(_GroupAffinityFilter):
|
||||
def __init__(self):
|
||||
self.policy_name = 'affinity'
|
||||
super(ServerGroupAffinityFilter, self).__init__()
|
||||
|
|
|
@ -1555,28 +1555,44 @@ class HostFiltersTestCase(test.NoDBTestCase):
|
|||
filter_properties = {}
|
||||
self.assertFalse(filt_cls.host_passes(host, filter_properties))
|
||||
|
||||
def test_group_anti_affinity_filter_passes(self):
|
||||
filt_cls = self.class_map['GroupAntiAffinityFilter']()
|
||||
def _test_group_anti_affinity_filter_passes(self, cls, policy):
|
||||
filt_cls = self.class_map[cls]()
|
||||
host = fakes.FakeHostState('host1', 'node1', {})
|
||||
filter_properties = {}
|
||||
self.assertTrue(filt_cls.host_passes(host, filter_properties))
|
||||
filter_properties = {'group_policies': ['affinity']}
|
||||
self.assertTrue(filt_cls.host_passes(host, filter_properties))
|
||||
filter_properties = {'group_policies': ['anti-affinity']}
|
||||
filter_properties = {'group_policies': [policy]}
|
||||
filter_properties['group_hosts'] = []
|
||||
self.assertTrue(filt_cls.host_passes(host, filter_properties))
|
||||
filter_properties['group_hosts'] = ['host2']
|
||||
self.assertTrue(filt_cls.host_passes(host, filter_properties))
|
||||
|
||||
def test_group_anti_affinity_filter_fails(self):
|
||||
filt_cls = self.class_map['GroupAntiAffinityFilter']()
|
||||
def test_group_anti_affinity_filter_passes(self):
|
||||
self._test_group_anti_affinity_filter_passes(
|
||||
'ServerGroupAntiAffinityFilter', 'anti-affinity')
|
||||
|
||||
def test_group_anti_affinity_filter_passes_legacy(self):
|
||||
self._test_group_anti_affinity_filter_passes(
|
||||
'GroupAntiAffinityFilter', 'legacy')
|
||||
|
||||
def _test_group_anti_affinity_filter_fails(self, cls, policy):
|
||||
filt_cls = self.class_map[cls]()
|
||||
host = fakes.FakeHostState('host1', 'node1', {})
|
||||
filter_properties = {'group_policies': ['anti-affinity'],
|
||||
filter_properties = {'group_policies': [policy],
|
||||
'group_hosts': ['host1']}
|
||||
self.assertFalse(filt_cls.host_passes(host, filter_properties))
|
||||
|
||||
def test_group_affinity_filter_passes(self):
|
||||
filt_cls = self.class_map['GroupAffinityFilter']()
|
||||
def test_group_anti_affinity_filter_fails(self):
|
||||
self._test_group_anti_affinity_filter_fails(
|
||||
'ServerGroupAntiAffinityFilter', 'anti-affinity')
|
||||
|
||||
def test_group_anti_affinity_filter_fails_legacy(self):
|
||||
self._test_group_anti_affinity_filter_fails(
|
||||
'GroupAntiAffinityFilter', 'legacy')
|
||||
|
||||
def _test_group_affinity_filter_passes(self, cls, policy):
|
||||
filt_cls = self.class_map['ServerGroupAffinityFilter']()
|
||||
host = fakes.FakeHostState('host1', 'node1', {})
|
||||
filter_properties = {}
|
||||
self.assertTrue(filt_cls.host_passes(host, filter_properties))
|
||||
|
@ -1586,13 +1602,29 @@ class HostFiltersTestCase(test.NoDBTestCase):
|
|||
'group_hosts': ['host1']}
|
||||
self.assertTrue(filt_cls.host_passes(host, filter_properties))
|
||||
|
||||
def test_group_affinity_filter_fails(self):
|
||||
filt_cls = self.class_map['GroupAffinityFilter']()
|
||||
def test_group_affinity_filter_passes(self):
|
||||
self._test_group_affinity_filter_passes(
|
||||
'ServerGroupAffinityFilter', 'affinity')
|
||||
|
||||
def test_group_affinity_filter_passes_legacy(self):
|
||||
self._test_group_affinity_filter_passes(
|
||||
'GroupAffinityFilter', 'legacy')
|
||||
|
||||
def _test_group_affinity_filter_fails(self, cls, policy):
|
||||
filt_cls = self.class_map[cls]()
|
||||
host = fakes.FakeHostState('host1', 'node1', {})
|
||||
filter_properties = {'group_policies': ['affinity'],
|
||||
filter_properties = {'group_policies': [policy],
|
||||
'group_hosts': ['host2']}
|
||||
self.assertFalse(filt_cls.host_passes(host, filter_properties))
|
||||
|
||||
def test_group_affinity_filter_fails(self):
|
||||
self._test_group_affinity_filter_fails(
|
||||
'ServerGroupAffinityFilter', 'affinity')
|
||||
|
||||
def test_group_affinity_filter_fails_legacy(self):
|
||||
self._test_group_affinity_filter_fails(
|
||||
'GroupAffinityFilter', 'legacy')
|
||||
|
||||
def test_aggregate_multi_tenancy_isolation_with_meta_passes(self):
|
||||
self._stub_service_is_up(True)
|
||||
filt_cls = self.class_map['AggregateMultiTenancyIsolation']()
|
||||
|
|
Loading…
Reference in New Issue