Fix require thread policy for multi-NUMA computes

CPU thread policy "require" demands that instances are created on hosts
with hardware threads, e.g HyperThreading. It is possible that a compute
has several NUMA nodes, but only some of them contribute to the list of
pinned CPUs. In this case NUMATopologyFiler will exclude the compute
from candidates even if hardware threads are enabled and cores from
other NUMA nodes are available for CPU pinning.

This commit allows a compute with enabled HyperThreading to pass
NUMATopologyFilter if at least one NUMA node contributes to the list of
cores allowed for CPU pinning.

Change-Id: I3235cc6bf1a2a9e29a17acc43472e2a6bd4c26ec
Closes-Bug: 1596692
(cherry picked from commit 1c04e18ec9)
This commit is contained in:
Mikhail Chernik 2016-06-27 22:04:46 +02:00 committed by Vladik Romanovsky
parent 24d2539ed1
commit a4a834f3bf
3 changed files with 39 additions and 21 deletions

View File

@ -46,14 +46,16 @@ class NUMATopologyFilter(filters.BaseHostFilter):
if fields.CPUThreadAllocationPolicy.REQUIRE not in cpu_thread_policy:
return True
for cell in host_topology.cells:
# the presence of siblings indicates hyperthreading (HT)
if not cell.siblings:
LOG.debug("%(host_state)s fails CPU policy requirements. "
"Host does not have hyperthreading or "
"hyperthreading is disabled, but 'require' threads "
"policy was requested.", {'host_state': host_state})
return False
# the presence of siblings in at least one cell indicates
# hyperthreading (HT)
has_hyperthreading = any(cell.siblings for cell in host_topology.cells)
if not has_hyperthreading:
LOG.debug("%(host_state)s fails CPU policy requirements. "
"Host does not have hyperthreading or "
"hyperthreading is disabled, but 'require' threads "
"policy was requested.", {'host_state': host_state})
return False
return True

View File

@ -43,16 +43,32 @@ NUMA_TOPOLOGY = objects.NUMATopology(
total=512, used=0)],
siblings=[], pinned_cpus=set([]))])
NUMA_TOPOLOGY_W_HT = objects.NUMATopology(cells=[
objects.NUMACell(
id=0, cpuset=set([1, 2, 5, 6]), memory=512,
cpu_usage=0, memory_usage=0, mempages=[],
siblings=[set([1, 5]), set([2, 6])], pinned_cpus=set([])),
objects.NUMACell(
id=1, cpuset=set([3, 4, 7, 8]), memory=512,
cpu_usage=0, memory_usage=0, mempages=[],
siblings=[set([3, 4]), set([7, 8])], pinned_cpus=set([]))
])
NUMA_TOPOLOGIES_W_HT = [
objects.NUMATopology(cells=[
objects.NUMACell(
id=0, cpuset=set([1, 2, 5, 6]), memory=512,
cpu_usage=0, memory_usage=0, mempages=[],
siblings=[set([1, 5]), set([2, 6])], pinned_cpus=set([])),
objects.NUMACell(
id=1, cpuset=set([3, 4, 7, 8]), memory=512,
cpu_usage=0, memory_usage=0, mempages=[],
siblings=[set([3, 4]), set([7, 8])], pinned_cpus=set([]))
]),
objects.NUMATopology(cells=[
objects.NUMACell(
id=0, cpuset=set([]), memory=512,
cpu_usage=0, memory_usage=0, mempages=[],
siblings=[], pinned_cpus=set([])),
objects.NUMACell(
id=1, cpuset=set([1, 2, 5, 6]), memory=512,
cpu_usage=0, memory_usage=0, mempages=[],
siblings=[set([1, 5]), set([2, 6])], pinned_cpus=set([])),
objects.NUMACell(
id=2, cpuset=set([3, 4, 7, 8]), memory=512,
cpu_usage=0, memory_usage=0, mempages=[],
siblings=[set([3, 4]), set([7, 8])], pinned_cpus=set([])),
]),
]
COMPUTE_NODES = [
objects.ComputeNode(

View File

@ -178,10 +178,10 @@ class TestNUMATopologyFilter(test.NoDBTestCase):
def test_numa_topology_filter_pass_cpu_thread_policy_require(self):
cpu_policy = fields.CPUAllocationPolicy.DEDICATED
cpu_thread_policy = fields.CPUThreadAllocationPolicy.REQUIRE
numa_topology = fakes.NUMA_TOPOLOGY_W_HT
self._do_test_numa_topology_filter_cpu_policy(
numa_topology, cpu_policy, cpu_thread_policy, True)
for numa_topology in fakes.NUMA_TOPOLOGIES_W_HT:
self._do_test_numa_topology_filter_cpu_policy(
numa_topology, cpu_policy, cpu_thread_policy, True)
def test_numa_topology_filter_pass_cpu_thread_policy_others(self):
cpu_policy = fields.CPUAllocationPolicy.DEDICATED