From e344b3038aa3c667484ccfadef5c331eb8ff1cec Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Tue, 23 Jan 2018 16:09:02 +0000 Subject: [PATCH] Don't filter out sibling sets with one core libvirt collects and exposes information about the host just as it does for guests. This information includes things like the host CPU topology. Nova uses this information to, among other things, generate an instance of 'nova.objects.numa.NUMACell' for each host NUMA cell. The 'siblings' field for each of these objects is populated using a combination of the siblings information exposed by libvirt minus the cores we've been told not to use, via the nova-specific 'vcpu_pin_set' option. On pretty much any standard (x86) machine, it would be exceedingly unlikely to find an asymmetric topology like so: socket 0 core 0 thread 0 (CPU #0) thread 1 (CPU #2) core 1 thread 0 (CPU #1) (note the missing 'CPU 3'). However these do happen in nova's world and are perfectly valid, thanks to the aforementioned 'vcpu_pin_set' option. Historically, once we've generated this list of sibling sets needed for the 'siblings' field, we've filtered out sets that contain less than two siblings (i.e. the cores have no siblings, or CPU #1 in the above example). This would be a fair assumption on normal hardware, where asymmetric topologies like the above wouldn't exist, but it doesn't really make sense in this use case. What we're trying to expose via the siblings attribute is the relationships between cores: if no relationship exists, we should say as much. The code that populates the 'siblings' attribute is modified to no longer exclude sibling sets with only one sibling. This allows us to simplify code that was previously having to switch between the 'siblings' attribute and the flat 'cpuset' attribute. In addition, all tests that use the 'NUMACell' object are updated to set the 'sibling' attribute as it is now always set in "real" code. This ensures behavior hasn't regressed. Change-Id: I8982ab25338969cd98621f79b7fbec8af43d12c5 Partial-Bug: #1744965 --- nova/objects/numa.py | 22 +- .../scheduler/filters/numa_topology_filter.py | 6 +- nova/tests/unit/compute/test_claims.py | 6 +- nova/tests/unit/compute/test_compute.py | 6 +- .../unit/compute/test_resource_tracker.py | 6 +- nova/tests/unit/objects/test_compute_node.py | 4 +- nova/tests/unit/objects/test_numa.py | 43 ++-- nova/tests/unit/scheduler/fakes.py | 35 ++- nova/tests/unit/virt/libvirt/test_driver.py | 35 +-- nova/tests/unit/virt/test_hardware.py | 241 +++++++++++------- nova/virt/libvirt/driver.py | 4 +- 11 files changed, 235 insertions(+), 173 deletions(-) diff --git a/nova/objects/numa.py b/nova/objects/numa.py index 94892d1e44..ad9d464221 100644 --- a/nova/objects/numa.py +++ b/nova/objects/numa.py @@ -76,6 +76,11 @@ class NUMACell(base.NovaObject): def avail_memory(self): return self.memory - self.memory_usage + @property + def has_threads(self): + """Check if SMT threads, a.k.a. HyperThreads, are present.""" + return any(len(sibling_set) > 1 for sibling_set in self.siblings) + def pin_cpus(self, cpus): if cpus - self.cpuset: raise exception.CPUPinningUnknown(requested=list(cpus), @@ -96,12 +101,6 @@ class NUMACell(base.NovaObject): self.pinned_cpus -= cpus def pin_cpus_with_siblings(self, cpus): - # NOTE(snikitin): Empty siblings list means that HyperThreading is - # disabled on the NUMA cell and we must pin CPUs like normal CPUs. - if not self.siblings: - self.pin_cpus(cpus) - return - pin_siblings = set() for sib in self.siblings: if cpus & sib: @@ -109,12 +108,6 @@ class NUMACell(base.NovaObject): self.pin_cpus(pin_siblings) def unpin_cpus_with_siblings(self, cpus): - # NOTE(snikitin): Empty siblings list means that HyperThreading is - # disabled on the NUMA cell and we must unpin CPUs like normal CPUs. - if not self.siblings: - self.unpin_cpus(cpus) - return - pin_siblings = set() for sib in self.siblings: if cpus & sib: @@ -211,6 +204,11 @@ class NUMATopology(base.NovaObject): 'cells': fields.ListOfObjectsField('NUMACell'), } + @property + def has_threads(self): + """Check if any cell use SMT threads (a.k.a. Hyperthreads)""" + return any(cell.has_threads for cell in self.cells) + @classmethod def obj_from_primitive(cls, primitive, context=None): if 'nova_object.name' in primitive: diff --git a/nova/scheduler/filters/numa_topology_filter.py b/nova/scheduler/filters/numa_topology_filter.py index 10079ce2f1..34a314279d 100644 --- a/nova/scheduler/filters/numa_topology_filter.py +++ b/nova/scheduler/filters/numa_topology_filter.py @@ -48,11 +48,7 @@ class NUMATopologyFilter(filters.BaseHostFilter): if fields.CPUThreadAllocationPolicy.REQUIRE not in cpu_thread_policy: return True - # 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: + if not host_topology.has_threads: LOG.debug("%(host_state)s fails CPU policy requirements. " "Host does not have hyperthreading or " "hyperthreading is disabled, but 'require' threads " diff --git a/nova/tests/unit/compute/test_claims.py b/nova/tests/unit/compute/test_claims.py index 55fa959fdd..3e1b7c2aff 100644 --- a/nova/tests/unit/compute/test_claims.py +++ b/nova/tests/unit/compute/test_claims.py @@ -136,11 +136,13 @@ class ClaimTestCase(test.NoDBTestCase): 'numa_topology': objects.NUMATopology( cells=[objects.NUMACell(id=1, cpuset=set([1, 2]), memory=512, memory_usage=0, cpu_usage=0, - mempages=[], siblings=[], + mempages=[], + siblings=[set([1]), set([2])], pinned_cpus=set([])), objects.NUMACell(id=2, cpuset=set([3, 4]), memory=512, memory_usage=0, cpu_usage=0, - mempages=[], siblings=[], + mempages=[], + siblings=[set([3]), set([4])], pinned_cpus=set([]))] )._to_json() } diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py index 01acaeae30..f4cf3c0e17 100644 --- a/nova/tests/unit/compute/test_compute.py +++ b/nova/tests/unit/compute/test_compute.py @@ -5673,14 +5673,16 @@ class ComputeTestCase(BaseTestCase, # are used cell1 = objects.NUMACell( id=0, cpuset=set([1, 2]), pinned_cpus=set([1, 2]), memory=512, - pagesize=2048, cpu_usage=2, memory_usage=0, siblings=[], + pagesize=2048, cpu_usage=2, memory_usage=0, + siblings=[set([1]), set([2])], mempages=[objects.NUMAPagesTopology( size_kb=2048, total=256, used=256)]) # as instance placed in node_0 all cpus from node_1 (cpu3 and cpu4) # are free (on current host) cell2 = objects.NUMACell( id=1, cpuset=set([3, 4]), pinned_cpus=set(), memory=512, - pagesize=2048, memory_usage=0, cpu_usage=0, siblings=[], + pagesize=2048, memory_usage=0, cpu_usage=0, + siblings=[set([3]), set([4])], mempages=[objects.NUMAPagesTopology( size_kb=2048, total=256, used=0)]) host_numa_topology = objects.NUMATopology(cells=[cell1, cell2]) diff --git a/nova/tests/unit/compute/test_resource_tracker.py b/nova/tests/unit/compute/test_resource_tracker.py index 8de185ac55..ab7295f962 100644 --- a/nova/tests/unit/compute/test_resource_tracker.py +++ b/nova/tests/unit/compute/test_resource_tracker.py @@ -163,11 +163,13 @@ _NUMA_HOST_TOPOLOGIES = { objects.NUMACell(id=0, cpuset=set([1, 2]), memory=_2MB, cpu_usage=0, memory_usage=0, mempages=[_NUMA_PAGE_TOPOLOGIES['2kb*8']], - siblings=[], pinned_cpus=set([])), + siblings=[set([1]), set([2])], + pinned_cpus=set([])), objects.NUMACell(id=1, cpuset=set([3, 4]), memory=_2MB, cpu_usage=0, memory_usage=0, mempages=[_NUMA_PAGE_TOPOLOGIES['2kb*8']], - siblings=[], pinned_cpus=set([]))]), + siblings=[set([3]), set([4])], + pinned_cpus=set([]))]), } diff --git a/nova/tests/unit/objects/test_compute_node.py b/nova/tests/unit/objects/test_compute_node.py index 6d7c4d9202..15187d1e23 100644 --- a/nova/tests/unit/objects/test_compute_node.py +++ b/nova/tests/unit/objects/test_compute_node.py @@ -42,11 +42,11 @@ fake_numa_topology = objects.NUMATopology( cells=[objects.NUMACell(id=0, cpuset=set([1, 2]), memory=512, cpu_usage=0, memory_usage=0, mempages=[], pinned_cpus=set([]), - siblings=[]), + siblings=[set([1]), set([2])]), objects.NUMACell(id=1, cpuset=set([3, 4]), memory=512, cpu_usage=0, memory_usage=0, mempages=[], pinned_cpus=set([]), - siblings=[])]) + siblings=[set([3]), set([4])])]) fake_numa_topology_db_format = fake_numa_topology._to_json() fake_supported_instances = [('x86_64', 'kvm', 'hvm')] fake_hv_spec = hv_spec.HVSpec(arch=fake_supported_instances[0][0], diff --git a/nova/tests/unit/objects/test_numa.py b/nova/tests/unit/objects/test_numa.py index eb32439bc7..f6a89a5fa1 100644 --- a/nova/tests/unit/objects/test_numa.py +++ b/nova/tests/unit/objects/test_numa.py @@ -22,12 +22,12 @@ fake_obj_numa = objects.NUMATopology( id=0, cpuset=set([1, 2]), memory=512, cpu_usage=2, memory_usage=256, mempages=[], pinned_cpus=set([]), - siblings=[]), + siblings=[set([1]), set([2])]), objects.NUMACell( id=1, cpuset=set([3, 4]), memory=512, cpu_usage=1, memory_usage=128, mempages=[], pinned_cpus=set([]), - siblings=[])]) + siblings=[set([3]), set([4])])]) class _TestNUMA(object): @@ -72,12 +72,12 @@ class _TestNUMA(object): objects.NUMACell( id=0, cpuset=set([1, 2]), memory=512, cpu_usage=2, memory_usage=256, - pinned_cpus=set([1]), siblings=[], + pinned_cpus=set([1]), siblings=[set([1]), set([2])], mempages=[]), objects.NUMACell( id=1, cpuset=set([3, 4]), memory=512, cpu_usage=1, memory_usage=128, - pinned_cpus=set([]), siblings=[], + pinned_cpus=set([]), siblings=[set([3]), set([4])], mempages=[]) ] ) @@ -85,10 +85,12 @@ class _TestNUMA(object): self.assertEqual(set([3, 4]), obj.cells[1].free_cpus) def test_pinning_logic(self): - numacell = objects.NUMACell(id=0, cpuset=set([1, 2, 3, 4]), memory=512, - cpu_usage=2, memory_usage=256, - pinned_cpus=set([1]), siblings=[], - mempages=[]) + numacell = objects.NUMACell( + id=0, cpuset=set([1, 2, 3, 4]), memory=512, + cpu_usage=2, memory_usage=256, + pinned_cpus=set([1]), + siblings=[set([1]), set([2]), set([3]), set([4])], + mempages=[]) numacell.pin_cpus(set([2, 3])) self.assertEqual(set([4]), numacell.free_cpus) @@ -114,11 +116,11 @@ class _TestNUMA(object): self.assertEqual(set([1, 2, 3, 4]), numacell.free_cpus) def test_pinning_with_siblings(self): - numacell = objects.NUMACell(id=0, cpuset=set([1, 2, 3, 4]), memory=512, - cpu_usage=2, memory_usage=256, - pinned_cpus=set([]), - siblings=[set([1, 3]), set([2, 4])], - mempages=[]) + numacell = objects.NUMACell( + id=0, cpuset=set([1, 2, 3, 4]), memory=512, + cpu_usage=2, memory_usage=256, + pinned_cpus=set([]), siblings=[set([1, 3]), set([2, 4])], + mempages=[]) numacell.pin_cpus_with_siblings(set([1, 2])) self.assertEqual(set(), numacell.free_cpus) @@ -137,12 +139,13 @@ class _TestNUMA(object): numacell.unpin_cpus_with_siblings(set([4])) self.assertEqual(set([1, 2, 3, 4]), numacell.free_cpus) - def test_pinning_with_siblings_with_empty_siblings_list(self): - numacell = objects.NUMACell(id=0, cpuset=set([1, 2, 3, 4]), memory=512, - cpu_usage=0, memory_usage=256, - pinned_cpus=set([]), - siblings=[], - mempages=[]) + def test_pinning_with_siblings_no_host_siblings(self): + numacell = objects.NUMACell( + id=0, cpuset=set([1, 2, 3, 4]), memory=512, + cpu_usage=0, memory_usage=256, + pinned_cpus=set([]), + siblings=[set([1]), set([2]), set([3]), set([4])], + mempages=[]) numacell.pin_cpus_with_siblings(set([1, 2])) self.assertEqual(set([1, 2]), numacell.pinned_cpus) @@ -169,7 +172,7 @@ class _TestNUMA(object): def test_can_fit_hugepages(self): cell = objects.NUMACell( id=0, cpuset=set([1, 2]), memory=1024, - siblings=[], pinned_cpus=set([]), + siblings=[set([1]), set([2])], pinned_cpus=set([]), mempages=[ objects.NUMAPagesTopology( size_kb=4, total=1548736, used=0), diff --git a/nova/tests/unit/scheduler/fakes.py b/nova/tests/unit/scheduler/fakes.py index 297dc795ae..23dcb585fb 100644 --- a/nova/tests/unit/scheduler/fakes.py +++ b/nova/tests/unit/scheduler/fakes.py @@ -23,26 +23,21 @@ from nova.scheduler import driver from nova.scheduler import host_manager from nova.tests import uuidsentinel -NUMA_TOPOLOGY = objects.NUMATopology( - cells=[ - objects.NUMACell( - id=0, cpuset=set([1, 2]), memory=512, - cpu_usage=0, memory_usage=0, mempages=[ - objects.NUMAPagesTopology(size_kb=16, - total=387184, - used=0), - objects.NUMAPagesTopology(size_kb=2048, - total=512, used=0)], - siblings=[], pinned_cpus=set([])), - objects.NUMACell( - id=1, cpuset=set([3, 4]), memory=512, - cpu_usage=0, memory_usage=0, mempages=[ - objects.NUMAPagesTopology(size_kb=4, - total=1548736, - used=0), - objects.NUMAPagesTopology(size_kb=2048, - total=512, used=0)], - siblings=[], pinned_cpus=set([]))]) +NUMA_TOPOLOGY = objects.NUMATopology(cells=[ + objects.NUMACell( + id=0, cpuset=set([1, 2]), memory=512, + cpu_usage=0, memory_usage=0, mempages=[ + objects.NUMAPagesTopology(size_kb=16, total=387184, used=0), + objects.NUMAPagesTopology(size_kb=2048, total=512, used=0)], + pinned_cpus=set([]), + siblings=[set([1]), set([2])]), + objects.NUMACell( + id=1, cpuset=set([3, 4]), memory=512, + cpu_usage=0, memory_usage=0, mempages=[ + objects.NUMAPagesTopology(size_kb=4, total=1548736, used=0), + objects.NUMAPagesTopology(size_kb=2048, total=512, used=0)], + pinned_cpus=set([]), + siblings=[set([3]), set([4])])]) NUMA_TOPOLOGIES_W_HT = [ objects.NUMATopology(cells=[ diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 41b5976861..59bd66c47c 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -2274,7 +2274,8 @@ class LibvirtConnTestCase(test.NoDBTestCase, host_topology = objects.NUMATopology( cells=[ objects.NUMACell( - id=3, cpuset=set([1]), memory=1024, mempages=[ + id=3, cpuset=set([1]), siblings=[set([1])], memory=1024, + mempages=[ objects.NUMAPagesTopology(size_kb=4, total=2000, used=0), objects.NUMAPagesTopology(size_kb=2048, total=512, @@ -2303,7 +2304,8 @@ class LibvirtConnTestCase(test.NoDBTestCase, host_topology = objects.NUMATopology( cells=[ objects.NUMACell( - id=3, cpuset=set([1]), memory=1024, mempages=[ + id=3, cpuset=set([1]), siblings=[set([1])], memory=1024, + mempages=[ objects.NUMAPagesTopology(size_kb=4, total=2000, used=0), objects.NUMAPagesTopology(size_kb=2048, total=512, @@ -3121,11 +3123,14 @@ class LibvirtConnTestCase(test.NoDBTestCase, host_topology = objects.NUMATopology( cells=[ objects.NUMACell( - id=0, cpuset=set([1, 2]), memory=1024, mempages=[]), + id=0, cpuset=set([1, 2]), siblings=[set([1]), set([2])], + memory=1024, mempages=[]), objects.NUMACell( - id=1, cpuset=set([3, 4]), memory=1024, mempages=[]), + id=1, cpuset=set([3, 4]), siblings=[set([3]), set([4])], + memory=1024, mempages=[]), objects.NUMACell( - id=16, cpuset=set([5, 6]), memory=1024, mempages=[])]) + id=16, cpuset=set([5, 6]), siblings=[set([5]), set([6])], + memory=1024, mempages=[])]) drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) with test.nested( @@ -13651,7 +13656,7 @@ class LibvirtConnTestCase(test.NoDBTestCase, self.assertEqual(set([]), got_topo.cells[2].pinned_cpus) self.assertEqual(set([]), got_topo.cells[3].pinned_cpus) self.assertEqual([set([0, 1])], got_topo.cells[0].siblings) - self.assertEqual([], got_topo.cells[1].siblings) + self.assertEqual([set([3])], got_topo.cells[1].siblings) @mock.patch.object(host.Host, 'has_min_version', return_value=True) def test_get_host_numa_topology(self, mock_version): @@ -16104,17 +16109,13 @@ class HostStateTestCase(test.NoDBTestCase): "vendor_id": '8086', "dev_type": fields.PciDeviceType.SRIOV_PF, "phys_function": None}] - numa_topology = objects.NUMATopology( - cells=[objects.NUMACell( - id=1, cpuset=set([1, 2]), memory=1024, - cpu_usage=0, memory_usage=0, - mempages=[], siblings=[], - pinned_cpus=set([])), - objects.NUMACell( - id=2, cpuset=set([3, 4]), memory=1024, - cpu_usage=0, memory_usage=0, - mempages=[], siblings=[], - pinned_cpus=set([]))]) + numa_topology = objects.NUMATopology(cells=[ + objects.NUMACell( + id=1, cpuset=set([1, 2]), memory=1024, cpu_usage=0, memory_usage=0, + mempages=[], siblings=[set([1]), set([2])], pinned_cpus=set([])), + objects.NUMACell( + id=2, cpuset=set([3, 4]), memory=1024, cpu_usage=0, memory_usage=0, + mempages=[], siblings=[set([3]), set([4])], pinned_cpus=set([]))]) class FakeConnection(libvirt_driver.LibvirtDriver): """Fake connection object.""" diff --git a/nova/tests/unit/virt/test_hardware.py b/nova/tests/unit/virt/test_hardware.py index 878850986e..467969c48d 100644 --- a/nova/tests/unit/virt/test_hardware.py +++ b/nova/tests/unit/virt/test_hardware.py @@ -1280,14 +1280,17 @@ class NUMATopologyTest(test.NoDBTestCase): objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), memory=1024, cpu_usage=0, memory_usage=0, mempages=[ hpages0_4K, hpages0_2M], - siblings=[], pinned_cpus=set([])), + siblings=[set([0]), set([1]), set([2]), set([3])], + pinned_cpus=set([])), objects.NUMACell(id=1, cpuset=set([4, 6]), memory=512, cpu_usage=0, memory_usage=0, mempages=[ hpages1_4K, hpages1_2M], - siblings=[], pinned_cpus=set([])), + siblings=[set([4]), set([6])], + pinned_cpus=set([])), objects.NUMACell(id=2, cpuset=set([5, 7]), memory=512, cpu_usage=0, memory_usage=0, mempages=[], - siblings=[], pinned_cpus=set([])), + siblings=[set([5]), set([7])], + pinned_cpus=set([])), ]) instance1 = objects.InstanceNUMATopology(cells=[ objects.InstanceNUMACell(id=0, cpuset=set([0, 1, 2]), memory=256), @@ -1344,13 +1347,16 @@ class NUMATopologyTest(test.NoDBTestCase): hosttopo = objects.NUMATopology(cells=[ objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), memory=1024, cpu_usage=0, memory_usage=0, mempages=[], - siblings=[], pinned_cpus=set([])), + siblings=[set([0]), set([1]), set([2]), set([3])], + pinned_cpus=set([])), objects.NUMACell(id=5, cpuset=set([4, 6]), memory=512, cpu_usage=0, memory_usage=0, mempages=[], - siblings=[], pinned_cpus=set([])), + siblings=[set([4]), set([6])], + pinned_cpus=set([])), objects.NUMACell(id=6, cpuset=set([5, 7]), memory=512, cpu_usage=0, memory_usage=0, mempages=[], - siblings=[], pinned_cpus=set([])), + siblings=[set([5]), set([7])], + pinned_cpus=set([])), ]) instance1 = objects.InstanceNUMATopology(cells=[ objects.InstanceNUMACell(id=0, cpuset=set([0, 1, 2]), memory=256), @@ -1400,13 +1406,16 @@ class NUMATopologyTest(test.NoDBTestCase): hosttopo = objects.NUMATopology(cells=[ objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), memory=1024, cpu_usage=2, memory_usage=512, mempages=[], - siblings=[], pinned_cpus=set([])), + siblings=[set([0]), set([1]), set([2]), set([3])], + pinned_cpus=set([])), objects.NUMACell(id=1, cpuset=set([4, 6]), memory=512, cpu_usage=1, memory_usage=512, mempages=[], - siblings=[], pinned_cpus=set([])), + siblings=[set([4]), set([6])], + pinned_cpus=set([])), objects.NUMACell(id=2, cpuset=set([5, 7]), memory=256, cpu_usage=0, memory_usage=0, mempages=[], - siblings=[], pinned_cpus=set([])), + siblings=[set([5]), set([7])], + pinned_cpus=set([])), ]) instance1 = objects.InstanceNUMATopology(cells=[ objects.InstanceNUMACell(id=0, cpuset=set([0, 1, 2]), memory=512), @@ -1449,7 +1458,8 @@ class NUMATopologyTest(test.NoDBTestCase): total=512, used=128, reserved=reserved[0][2048])], - siblings=[], pinned_cpus=set([])), + siblings=[set([0]), set([1])], + pinned_cpus=set([])), objects.NUMACell(id=1, cpuset=set([2, 3]), memory=512, cpu_usage=0, memory_usage=0, mempages=[ objects.NUMAPagesTopology( @@ -1457,7 +1467,8 @@ class NUMATopologyTest(test.NoDBTestCase): total=5, used=2, reserved=reserved[1][1048576])], - siblings=[], pinned_cpus=set([])), + siblings=[set([2]), set([3])], + pinned_cpus=set([])), ]) instance1 = objects.InstanceNUMATopology(cells=[ objects.InstanceNUMACell( @@ -1516,10 +1527,12 @@ class NUMATopologyTest(test.NoDBTestCase): hosttopo = objects.NUMATopology(cells=[ objects.NUMACell(id=0, cpuset=set([0, 1]), memory=512, cpu_usage=0, memory_usage=0, mempages=[], - siblings=[], pinned_cpus=set([])), + siblings=[set([0]), set([1])], + pinned_cpus=set([])), objects.NUMACell(id=1, cpuset=set([2, 3]), memory=512, cpu_usage=0, memory_usage=0, mempages=[], - siblings=[], pinned_cpus=set([])), + siblings=[set([2]), set([3])], + pinned_cpus=set([])), ]) instance1 = objects.InstanceNUMATopology(cells=[ objects.InstanceNUMACell(id=0, cpuset=set([0, 1]), memory=256), @@ -1550,10 +1563,12 @@ class NUMATopologyTest(test.NoDBTestCase): hosttopo = objects.NUMATopology(cells=[ objects.NUMACell(id=0, cpuset=set([0, 1]), memory=512, cpu_usage=0, memory_usage=0, mempages=[], - siblings=[], pinned_cpus=set([])), + siblings=[set([0]), set([1])], + pinned_cpus=set([])), objects.NUMACell(id=1, cpuset=set([2, 3]), memory=512, cpu_usage=0, memory_usage=0, mempages=[], - siblings=[], pinned_cpus=set([])), + siblings=[set([2]), set([3])], + pinned_cpus=set([])), ]) instance1_topo = objects.InstanceNUMATopology(cells=[ objects.InstanceNUMACell(id=0, cpuset=set([0, 1]), memory=256), @@ -1588,10 +1603,11 @@ class NUMATopologyTest(test.NoDBTestCase): cells=[ objects.NUMACell(id=1, cpuset=set([1, 2]), memory=1024, cpu_usage=0, memory_usage=0, mempages=[], - siblings=[], pinned_cpus=set([])), + siblings=[set([1]), set([2])], + pinned_cpus=set([])), objects.NUMACell(id=2, cpuset=set([3, 4]), memory=1024, - cpu_usage=0, memory_usage=0, - mempages=[], siblings=[], + cpu_usage=0, memory_usage=0, mempages=[], + siblings=[set([3]), set([4])], pinned_cpus=set([]))]) got = objects.NUMATopology.obj_from_db_obj(expected._to_json()) @@ -1603,7 +1619,8 @@ class VirtNUMATopologyCellUsageTestCase(test.NoDBTestCase): def test_fit_instance_cell_success_no_limit(self): host_cell = objects.NUMACell(id=4, cpuset=set([1, 2]), memory=1024, cpu_usage=0, memory_usage=0, mempages=[], - siblings=[], pinned_cpus=set([])) + siblings=[set([1]), set([2])], + pinned_cpus=set([])) instance_cell = objects.InstanceNUMACell( id=0, cpuset=set([1, 2]), memory=1024) fitted_cell = hw._numa_fit_instance_cell(host_cell, instance_cell) @@ -1612,9 +1629,9 @@ class VirtNUMATopologyCellUsageTestCase(test.NoDBTestCase): def test_fit_instance_cell_success_w_limit(self): host_cell = objects.NUMACell(id=4, cpuset=set([1, 2]), memory=1024, - cpu_usage=2, - memory_usage=1024, - mempages=[], siblings=[], + cpu_usage=2, memory_usage=1024, + mempages=[], + siblings=[set([1]), set([2])], pinned_cpus=set([])) limit_cell = objects.NUMATopologyLimits( cpu_allocation_ratio=2, ram_allocation_ratio=2) @@ -1628,7 +1645,8 @@ class VirtNUMATopologyCellUsageTestCase(test.NoDBTestCase): def test_fit_instance_cell_self_overcommit(self): host_cell = objects.NUMACell(id=4, cpuset=set([1, 2]), memory=1024, cpu_usage=0, memory_usage=0, mempages=[], - siblings=[], pinned_cpus=set([])) + siblings=[set([1]), set([2])], + pinned_cpus=set([])) limit_cell = objects.NUMATopologyLimits( cpu_allocation_ratio=2, ram_allocation_ratio=2) instance_cell = objects.InstanceNUMACell( @@ -1639,9 +1657,9 @@ class VirtNUMATopologyCellUsageTestCase(test.NoDBTestCase): def test_fit_instance_cell_fail_w_limit(self): host_cell = objects.NUMACell(id=4, cpuset=set([1, 2]), memory=1024, - cpu_usage=2, - memory_usage=1024, - mempages=[], siblings=[], + cpu_usage=2, memory_usage=1024, + mempages=[], + siblings=[set([1]), set([2])], pinned_cpus=set([])) instance_cell = objects.InstanceNUMACell( id=0, cpuset=set([1, 2]), memory=4096) @@ -1666,11 +1684,13 @@ class VirtNUMAHostTopologyTestCase(test.NoDBTestCase): cells=[ objects.NUMACell(id=1, cpuset=set([1, 2]), memory=2048, cpu_usage=2, memory_usage=2048, - mempages=[], siblings=[], + mempages=[], + siblings=[set([1]), set([2])], pinned_cpus=set([])), objects.NUMACell(id=2, cpuset=set([3, 4]), memory=2048, cpu_usage=2, memory_usage=2048, - mempages=[], siblings=[], + mempages=[], + siblings=[set([3]), set([4])], pinned_cpus=set([]))]) self.limits = objects.NUMATopologyLimits( @@ -1835,10 +1855,12 @@ class HelperMethodsTestCase(test.NoDBTestCase): self.hosttopo = objects.NUMATopology(cells=[ objects.NUMACell(id=0, cpuset=set([0, 1]), memory=512, memory_usage=0, cpu_usage=0, mempages=[], - siblings=[], pinned_cpus=set([])), + siblings=[set([0]), set([1])], + pinned_cpus=set([])), objects.NUMACell(id=1, cpuset=set([2, 3]), memory=512, memory_usage=0, cpu_usage=0, mempages=[], - siblings=[], pinned_cpus=set([])), + siblings=[set([2]), set([3])], + pinned_cpus=set([])), ]) self.instancetopo = objects.InstanceNUMATopology( instance_uuid=uuids.instance, @@ -2008,7 +2030,7 @@ class VirtMemoryPagesTestCase(test.NoDBTestCase): size_kb=2048, total=512, used=0)], - siblings=[], pinned_cpus=set([])) + siblings=[set([0])], pinned_cpus=set([])) topo = hw._numa_pagesize_usage_from_cell(hostcell, instcell, 1) self.assertEqual(2048, topo[0].size_kb) @@ -2099,7 +2121,7 @@ class VirtMemoryPagesTestCase(test.NoDBTestCase): id=0, cpuset=set([0]), memory=1024, mempages=[ objects.NUMAPagesTopology(size_kb=4, total=262144, used=0), ], - siblings=[], pinned_cpus=set([])) + siblings=[set([0])], pinned_cpus=set([])) inst_cell = objects.InstanceNUMACell( id=0, cpuset=set([0]), memory=1024, pagesize=hw.MEMPAGES_SMALL) @@ -2126,7 +2148,7 @@ class VirtMemoryPagesTestCase(test.NoDBTestCase): objects.NUMAPagesTopology(size_kb=4, total=256, used=0), objects.NUMAPagesTopology(size_kb=2048, total=512, used=0) ], - siblings=[], pinned_cpus=set([])) + siblings=[set([0])], pinned_cpus=set([])) self.assertEqual( 2048, @@ -2140,7 +2162,7 @@ class VirtMemoryPagesTestCase(test.NoDBTestCase): objects.NUMAPagesTopology(size_kb=4, total=256, used=0), objects.NUMAPagesTopology(size_kb=2048, total=512, used=0) ], - siblings=[], pinned_cpus=set([])) + siblings=[set([0])], pinned_cpus=set([])) self.assertEqual( 2048, @@ -2155,7 +2177,7 @@ class VirtMemoryPagesTestCase(test.NoDBTestCase): objects.NUMAPagesTopology(size_kb=4, total=256, used=0), objects.NUMAPagesTopology(size_kb=2048, total=512, used=0) ], - siblings=[], pinned_cpus=set([])) + siblings=[set([0])], pinned_cpus=set([])) self.assertIsNone(hw._numa_cell_supports_pagesize_request( host_cell, inst_cell)) @@ -2168,7 +2190,7 @@ class VirtMemoryPagesTestCase(test.NoDBTestCase): objects.NUMAPagesTopology(size_kb=4, total=256, used=0), objects.NUMAPagesTopology(size_kb=2048, total=512, used=0) ], - siblings=[], pinned_cpus=set([])) + siblings=[set([0])], pinned_cpus=set([])) self.assertRaises(exception.MemoryPageSizeNotSupported, hw._numa_cell_supports_pagesize_request, host_cell, inst_cell) @@ -2215,8 +2237,9 @@ class _CPUPinningTestCaseBase(object): class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): def test_get_pinning_inst_too_large_cpu(self): host_pin = objects.NUMACell(id=0, cpuset=set([0, 1, 2]), - memory=2048, memory_usage=0, siblings=[], - mempages=[], pinned_cpus=set([])) + memory=2048, memory_usage=0, mempages=[], + siblings=[set([0]), set([1]), set([2])], + pinned_cpus=set([])) inst_pin = objects.InstanceNUMACell(cpuset=set([0, 1, 2, 3]), memory=2048) @@ -2226,7 +2249,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): def test_get_pinning_inst_too_large_mem(self): host_pin = objects.NUMACell(id=0, cpuset=set([0, 1, 2]), memory=2048, memory_usage=1024, - siblings=[], mempages=[], + mempages=[], + siblings=[set([0]), set([1]), set([2])], pinned_cpus=set([])) inst_pin = objects.InstanceNUMACell(cpuset=set([0, 1, 2]), memory=2048) @@ -2236,9 +2260,10 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): def test_get_pinning_inst_not_avail(self): host_pin = objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), - memory=2048, memory_usage=0, - pinned_cpus=set([0]), - siblings=[], mempages=[]) + memory=2048, memory_usage=0, mempages=[], + siblings=[set([0]), set([1]), set([2]), + set([3])], + pinned_cpus=set([0])) inst_pin = objects.InstanceNUMACell(cpuset=set([0, 1, 2, 3]), memory=2048) @@ -2247,8 +2272,9 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): def test_get_pinning_no_sibling_fits_empty(self): host_pin = objects.NUMACell(id=0, cpuset=set([0, 1, 2]), - memory=2048, memory_usage=0, siblings=[], - mempages=[], pinned_cpus=set([])) + memory=2048, memory_usage=0, mempages=[], + siblings=[set([0]), set([1]), set([2])], + pinned_cpus=set([])) inst_pin = objects.InstanceNUMACell(cpuset=set([0, 1, 2]), memory=2048) inst_pin = hw._numa_fit_instance_cell_with_pinning(host_pin, inst_pin) @@ -2260,9 +2286,10 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): def test_get_pinning_no_sibling_fits_w_usage(self): host_pin = objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), - memory=2048, memory_usage=0, - pinned_cpus=set([1]), mempages=[], - siblings=[]) + memory=2048, memory_usage=0, mempages=[], + siblings=[set([0]), set([1]), set([2]), + set([3])], + pinned_cpus=set([1])) inst_pin = objects.InstanceNUMACell(cpuset=set([0, 1, 2]), memory=1024) inst_pin = hw._numa_fit_instance_cell_with_pinning(host_pin, inst_pin) @@ -2272,8 +2299,10 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): def test_get_pinning_instance_siblings_fits(self): host_pin = objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), - memory=2048, memory_usage=0, siblings=[], - mempages=[], pinned_cpus=set([])) + memory=2048, memory_usage=0, mempages=[], + siblings=[set([0]), set([1]), set([2]), + set([3])], + pinned_cpus=set([])) inst_pin = objects.InstanceNUMACell( cpuset=set([0, 1, 2, 3]), memory=2048) @@ -2366,10 +2395,10 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): def test_get_pinning_require_policy_no_siblings(self): host_pin = objects.NUMACell( id=0, - cpuset=set([0, 1, 2, 3, 4, 5, 6, 7]), + cpuset=set(range(0, 8)), memory=4096, memory_usage=0, pinned_cpus=set([]), - siblings=[], + siblings=[set([x]) for x in range(0, 8)], mempages=[]) inst_pin = objects.InstanceNUMACell( cpuset=set([0, 1, 2, 3]), @@ -2539,9 +2568,10 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): def test_get_pinning_isolate_policy_fits(self): host_pin = objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), - memory=4096, memory_usage=0, - siblings=[], - mempages=[], pinned_cpus=set([])) + memory=4096, memory_usage=0, mempages=[], + siblings=[set([0]), set([1]), set([2]), + set([3])], + pinned_cpus=set([])) inst_pin = objects.InstanceNUMACell( cpuset=set([0, 1]), memory=2048, @@ -2590,11 +2620,13 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): def test_host_numa_fit_instance_to_host_single_cell(self): host_topo = objects.NUMATopology( cells=[objects.NUMACell(id=0, cpuset=set([0, 1]), memory=2048, - memory_usage=0, siblings=[], - mempages=[], pinned_cpus=set([])), + memory_usage=0, mempages=[], + siblings=[set([0]), set([1])], + pinned_cpus=set([])), objects.NUMACell(id=1, cpuset=set([2, 3]), memory=2048, - memory_usage=0, siblings=[], - mempages=[], pinned_cpus=set([]))] + memory_usage=0, mempages=[], + siblings=[set([2]), set([3])], + pinned_cpus=set([]))] ) inst_topo = objects.InstanceNUMATopology( cells=[objects.InstanceNUMACell( @@ -2608,13 +2640,14 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): def test_host_numa_fit_instance_to_host_single_cell_w_usage(self): host_topo = objects.NUMATopology( - cells=[objects.NUMACell(id=0, cpuset=set([0, 1]), - pinned_cpus=set([0]), memory=2048, - memory_usage=0, siblings=[], - mempages=[]), + cells=[objects.NUMACell(id=0, cpuset=set([0, 1]), memory=2048, + memory_usage=0, mempages=[], + siblings=[set([0]), set([1])], + pinned_cpus=set([0])), objects.NUMACell(id=1, cpuset=set([2, 3]), memory=2048, - memory_usage=0, siblings=[], - mempages=[], pinned_cpus=set([]))]) + memory_usage=0, mempages=[], + siblings=[set([2]), set([3])], + pinned_cpus=set([]))]) inst_topo = objects.InstanceNUMATopology( cells=[objects.InstanceNUMACell( cpuset=set([0, 1]), memory=2048, @@ -2628,11 +2661,13 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): def test_host_numa_fit_instance_to_host_single_cell_fail(self): host_topo = objects.NUMATopology( cells=[objects.NUMACell(id=0, cpuset=set([0, 1]), memory=2048, - pinned_cpus=set([0]), memory_usage=0, - siblings=[], mempages=[]), + memory_usage=0, mempages=[], + siblings=[set([0]), set([1])], + pinned_cpus=set([0])), objects.NUMACell(id=1, cpuset=set([2, 3]), memory=2048, - pinned_cpus=set([2]), memory_usage=0, - siblings=[], mempages=[])]) + memory_usage=0, mempages=[], + siblings=[set([2]), set([3])], + pinned_cpus=set([2]))]) inst_topo = objects.InstanceNUMATopology( cells=[objects.InstanceNUMACell( cpuset=set([0, 1]), memory=2048, @@ -2645,11 +2680,15 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): host_topo = objects.NUMATopology( cells=[objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), memory=2048, memory_usage=0, - siblings=[], mempages=[], + mempages=[], + siblings=[set([0]), set([1]), set([2]), + set([3])], pinned_cpus=set([])), objects.NUMACell(id=1, cpuset=set([4, 5, 6, 7]), memory=2048, memory_usage=0, - siblings=[], mempages=[], + mempages=[], + siblings=[set([4]), set([5]), set([6]), + set([7])], pinned_cpus=set([]))]) inst_topo = objects.InstanceNUMATopology( cells=[objects.InstanceNUMACell( @@ -2666,17 +2705,24 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): def test_host_numa_fit_instance_to_host_barely_fit(self): host_topo = objects.NUMATopology( cells=[objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), - memory=2048, pinned_cpus=set([0]), - siblings=[], mempages=[], - memory_usage=0), + memory=2048, memory_usage=0, + mempages=[], + siblings=[set([0]), set([1]), set([2]), + set([3])], + pinned_cpus=set([0])), objects.NUMACell(id=1, cpuset=set([4, 5, 6, 7]), memory=2048, memory_usage=0, - siblings=[], mempages=[], + mempages=[], + siblings=[set([4]), set([5]), set([6]), + set([7])], pinned_cpus=set([4, 5, 6])), objects.NUMACell(id=2, cpuset=set([8, 9, 10, 11]), memory=2048, memory_usage=0, - siblings=[], mempages=[], + mempages=[], + siblings=[set([8]), set([9]), + set([10]), set([11])], pinned_cpus=set([10, 11]))]) + inst_topo = objects.InstanceNUMATopology( cells=[objects.InstanceNUMACell( cpuset=set([0, 1]), memory=2048, @@ -2693,11 +2739,15 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): host_topo = objects.NUMATopology( cells=[objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), memory=4096, memory_usage=0, - mempages=[], siblings=[], + mempages=[], + siblings=[set([0]), set([1]), set([2]), + set([3])], pinned_cpus=set([0])), objects.NUMACell(id=1, cpuset=set([4, 5, 6, 7]), memory=4096, memory_usage=0, - siblings=[], mempages=[], + mempages=[], + siblings=[set([4]), set([5]), set([6]), + set([7])], pinned_cpus=set([4, 5, 6]))]) inst_topo = objects.InstanceNUMATopology( cells=[objects.InstanceNUMACell( @@ -2713,11 +2763,15 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): host_topo = objects.NUMATopology( cells=[objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), memory=4096, memory_usage=0, - siblings=[], mempages=[], + mempages=[], + siblings=[set([0]), set([1]), set([2]), + set([3])], pinned_cpus=set([])), objects.NUMACell(id=1, cpuset=set([4, 5, 6, 7]), memory=4096, memory_usage=0, - siblings=[], mempages=[], + mempages=[], + siblings=[set([4]), set([5]), set([6]), + set([7])], pinned_cpus=set([]))]) inst_topo = objects.InstanceNUMATopology( cells=[objects.InstanceNUMACell( @@ -2736,7 +2790,9 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): host_pin = objects.NUMATopology( cells=[objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), memory=4096, cpu_usage=0, - memory_usage=0, siblings=[], + memory_usage=0, + siblings=[set([0]), set([1]), set([2]), + set([3])], mempages=[], pinned_cpus=set([]))]) inst_pin_1 = objects.InstanceNUMATopology( cells=[objects.InstanceNUMACell( @@ -2758,7 +2814,9 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): host_pin = objects.NUMATopology( cells=[objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), memory=4096, cpu_usage=0, memory_usage=0, - siblings=[], mempages=[], + mempages=[], + siblings=[set([0]), set([1]), set([2]), + set([3])], pinned_cpus=set([0, 1, 3]))]) inst_pin_1 = objects.InstanceNUMATopology( cells=[objects.InstanceNUMACell( @@ -2777,7 +2835,9 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): host_pin = objects.NUMATopology( cells=[objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), memory=4096, cpu_usage=0, - memory_usage=0, siblings=[], + memory_usage=0, + siblings=[set([0]), set([1]), set([2]), + set([3])], mempages=[], pinned_cpus=set([]))]) inst_pin_1 = objects.InstanceNUMATopology( cells=[objects.InstanceNUMACell( @@ -2841,7 +2901,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): cells=[objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), memory=4096, cpu_usage=0, memory_usage=0, - siblings=[], + siblings=[set([0]), set([1]), set([2]), + set([3])], mempages=[], pinned_cpus=set([]))]) inst_pin = objects.InstanceNUMATopology( cells=[objects.InstanceNUMACell( @@ -2861,7 +2922,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): cells=[objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), memory=4096, cpu_usage=4, memory_usage=0, - siblings=[], + siblings=[set([0]), set([1]), set([2]), + set([3])], mempages=[], pinned_cpus=set([0, 1, 2, 3]))]) inst_pin = objects.InstanceNUMATopology( @@ -2882,7 +2944,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase): class CPUSReservedCellTestCase(test.NoDBTestCase): def _test_reserved(self, reserved): host_cell = objects.NUMACell(id=0, cpuset=set([0, 1, 2]), - memory=2048, memory_usage=0, siblings=[], + memory=2048, memory_usage=0, + siblings=[set([0]), set([1]), set([2])], mempages=[], pinned_cpus=set([])) inst_cell = objects.InstanceNUMACell(cpuset=set([0, 1]), memory=2048) return hw._numa_fit_instance_cell_with_pinning( @@ -2942,12 +3005,12 @@ class EmulatorThreadsTestCase(test.NoDBTestCase): def _host_topology(): return objects.NUMATopology( cells=[objects.NUMACell(id=0, cpuset=set([0, 1]), memory=2048, - cpu_usage=0, - memory_usage=0, siblings=[], + cpu_usage=0, memory_usage=0, + siblings=[set([0]), set([1])], mempages=[], pinned_cpus=set([])), objects.NUMACell(id=1, cpuset=set([2, 3]), memory=2048, - cpu_usage=0, - memory_usage=0, siblings=[], + cpu_usage=0, memory_usage=0, + siblings=[set([2]), set([3])], mempages=[], pinned_cpus=set([]))]) def test_single_node_not_defined(self): diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index fa746a5d11..205a608629 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -5970,8 +5970,8 @@ class LibvirtDriver(driver.ComputeDriver): )) cpuset &= allowed_cpus siblings = [sib & allowed_cpus for sib in siblings] - # Filter out singles and empty sibling sets that may be left - siblings = [sib for sib in siblings if len(sib) > 1] + # Filter out empty sibling sets that may be left + siblings = [sib for sib in siblings if len(sib) > 0] mempages = [ objects.NUMAPagesTopology(