Skip to content

Commit 59ac941

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Factor out a mixin class for candidate aware filters"
2 parents 38592c2 + 87c0602 commit 59ac941

File tree

3 files changed

+65
-49
lines changed

3 files changed

+65
-49
lines changed

nova/scheduler/filters/__init__.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@
1616
"""
1717
Scheduler host filters
1818
"""
19+
from oslo_log import log as logging
20+
1921
from nova import filters
2022

23+
LOG = logging.getLogger(__name__)
24+
2125

2226
class BaseHostFilter(filters.BaseFilter):
2327
"""Base class for host filters."""
@@ -53,6 +57,43 @@ def host_passes(self, host_state, filter_properties):
5357
raise NotImplementedError()
5458

5559

60+
class CandidateFilterMixin:
61+
"""Mixing that helps to implement a Filter that needs to filter host by
62+
Placement allocation candidates.
63+
"""
64+
65+
def filter_candidates(self, host_state, filter_func):
66+
"""Checks still viable allocation candidates by the filter_func and
67+
keep only those that are passing it.
68+
69+
:param host_state: HostState object holding the list of still viable
70+
allocation candidates
71+
:param filter_func: A callable that takes an allocation candidate and
72+
returns a True like object if the candidate passed the filter or a
73+
False like object if it doesn't.
74+
"""
75+
good_candidates = []
76+
for candidate in host_state.allocation_candidates:
77+
LOG.debug(
78+
f'{self.__class__.__name__} tries allocation candidate: '
79+
f'{candidate}',
80+
)
81+
if filter_func(candidate):
82+
LOG.debug(
83+
f'{self.__class__.__name__} accepted allocation '
84+
f'candidate: {candidate}',
85+
)
86+
good_candidates.append(candidate)
87+
else:
88+
LOG.debug(
89+
f'{self.__class__.__name__} rejected allocation '
90+
f'candidate: {candidate}',
91+
)
92+
93+
host_state.allocation_candidates = good_candidates
94+
return good_candidates
95+
96+
5697
class HostFilterHandler(filters.BaseFilterHandler):
5798
def __init__(self):
5899
super(HostFilterHandler, self).__init__(BaseHostFilter)

nova/scheduler/filters/numa_topology_filter.py

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@
2020
LOG = logging.getLogger(__name__)
2121

2222

23-
class NUMATopologyFilter(filters.BaseHostFilter):
23+
class NUMATopologyFilter(
24+
filters.BaseHostFilter,
25+
filters.CandidateFilterMixin,
26+
):
2427
"""Filter on requested NUMA topology."""
2528

2629
# NOTE(sean-k-mooney): In change I0322d872bdff68936033a6f5a54e8296a6fb343
@@ -97,34 +100,19 @@ def host_passes(self, host_state, spec_obj):
97100
if network_metadata:
98101
limits.network_metadata = network_metadata
99102

100-
good_candidates = []
101-
for candidate in host_state.allocation_candidates:
102-
LOG.debug(
103-
'NUMATopologyFilter tries allocation candidate: %s, %s',
104-
candidate, requested_topology
105-
)
106-
instance_topology = (hardware.numa_fit_instance_to_host(
107-
host_topology, requested_topology,
103+
good_candidates = self.filter_candidates(
104+
host_state,
105+
lambda candidate: hardware.numa_fit_instance_to_host(
106+
host_topology,
107+
requested_topology,
108108
limits=limits,
109109
pci_requests=pci_requests,
110110
pci_stats=host_state.pci_stats,
111-
provider_mapping=candidate['mappings'],
112-
))
113-
if instance_topology:
114-
LOG.debug(
115-
'NUMATopologyFilter accepted allocation candidate: %s',
116-
candidate
117-
)
118-
good_candidates.append(candidate)
119-
else:
120-
LOG.debug(
121-
'NUMATopologyFilter rejected allocation candidate: %s',
122-
candidate
123-
)
124-
125-
host_state.allocation_candidates = good_candidates
126-
127-
if not host_state.allocation_candidates:
111+
provider_mapping=candidate["mappings"],
112+
),
113+
)
114+
115+
if not good_candidates:
128116
LOG.debug("%(host)s, %(node)s fails NUMA topology "
129117
"requirements. The instance does not fit on this "
130118
"host.", {'host': host_state.host,

nova/scheduler/filters/pci_passthrough_filter.py

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@
2020
LOG = logging.getLogger(__name__)
2121

2222

23-
class PciPassthroughFilter(filters.BaseHostFilter):
23+
class PciPassthroughFilter(
24+
filters.BaseHostFilter,
25+
filters.CandidateFilterMixin,
26+
):
2427
"""Pci Passthrough Filter based on PCI request
2528
2629
Filter that schedules instances on a host if the host has devices
@@ -54,28 +57,12 @@ def host_passes(self, host_state, spec_obj):
5457
{'host_state': host_state, 'requests': pci_requests})
5558
return False
5659

57-
good_candidates = []
58-
for candidate in host_state.allocation_candidates:
59-
LOG.debug(
60-
'PciPassthroughFilter tries allocation candidate: %s',
61-
candidate
62-
)
63-
if host_state.pci_stats.support_requests(
64-
pci_requests.requests,
65-
provider_mapping=candidate['mappings']
66-
):
67-
LOG.debug(
68-
'PciPassthroughFilter accepted allocation candidate: %s',
69-
candidate
70-
)
71-
good_candidates.append(candidate)
72-
else:
73-
LOG.debug(
74-
'PciPassthroughFilter rejected allocation candidate: %s',
75-
candidate
76-
)
77-
78-
host_state.allocation_candidates = good_candidates
60+
good_candidates = self.filter_candidates(
61+
host_state,
62+
lambda candidate: host_state.pci_stats.support_requests(
63+
pci_requests.requests, provider_mapping=candidate["mappings"]
64+
),
65+
)
7966

8067
if not good_candidates:
8168
LOG.debug("%(host_state)s doesn't have the required PCI devices"

0 commit comments

Comments
 (0)