From 1c04e18ec922b6a6f6de6734fbceb0eed336f2ee Mon Sep 17 00:00:00 2001 From: Mikhail Chernik Date: Mon, 27 Jun 2016 22:04:46 +0200 Subject: [PATCH] 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 --- .../scheduler/filters/numa_topology_filter.py | 18 +++++----- nova/tests/unit/scheduler/fakes.py | 36 +++++++++++++------ .../filters/test_numa_topology_filters.py | 6 ++-- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/nova/scheduler/filters/numa_topology_filter.py b/nova/scheduler/filters/numa_topology_filter.py index 2417f43927b0..d6b0342d4fa2 100644 --- a/nova/scheduler/filters/numa_topology_filter.py +++ b/nova/scheduler/filters/numa_topology_filter.py @@ -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 diff --git a/nova/tests/unit/scheduler/fakes.py b/nova/tests/unit/scheduler/fakes.py index 32e79071b3c8..c3e10d02e706 100644 --- a/nova/tests/unit/scheduler/fakes.py +++ b/nova/tests/unit/scheduler/fakes.py @@ -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( diff --git a/nova/tests/unit/scheduler/filters/test_numa_topology_filters.py b/nova/tests/unit/scheduler/filters/test_numa_topology_filters.py index cc7414f580c8..ffb040dac4fc 100644 --- a/nova/tests/unit/scheduler/filters/test_numa_topology_filters.py +++ b/nova/tests/unit/scheduler/filters/test_numa_topology_filters.py @@ -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