From f2706b230018ca718614cd86e8c6b68f8cbd7c3f Mon Sep 17 00:00:00 2001 From: Chris Friesen Date: Wed, 8 Jun 2016 18:15:34 -0600 Subject: [PATCH] Fix resource tracking for instances with no numa topology This fixes a problem in host NUMA node resource tracking when there is an instance with no numa topology on the same node as instances with numa topology. It's triggered while running the resource audit, which ultimately calls hardware.get_host_numa_usage_from_instance() and assigns the result to self.compute_node.numa_topology. The problem occurs if you have a number of instances with numa topology, and then an instance with no numa topology. When running numa_usage_from_instances() for the instance with no numa topology we cache the values of "memory_usage" and "cpu_usage". However, because instance.cells is empty we don't enter the loop. Since the two lines in this commit are indented too far they don't get called, and we end up appending a host cell with "cpu_usage" and "memory_usage" of zero. This results in a host numa_topology cell with incorrect "cpu_usage" and "memory_usage" values, though I think the overall host cpu/memory usage is still correct. The fix is to reduce the indentation of the two lines in question so that they get called even when the instance has no numa topology. This writes the original host cell usage information back to it. Change-Id: I7e327b79b731393ed787c4e131dc6d9654f424d0 Closes-Bug: #1590607 --- nova/tests/unit/virt/test_hardware.py | 30 +++++++++++++++++++++++++++ nova/virt/hardware.py | 5 ++--- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/nova/tests/unit/virt/test_hardware.py b/nova/tests/unit/virt/test_hardware.py index 6c1c479d56..6a95d5a03b 100644 --- a/nova/tests/unit/virt/test_hardware.py +++ b/nova/tests/unit/virt/test_hardware.py @@ -1472,6 +1472,36 @@ class NUMATopologyTest(test.NoDBTestCase): self.assertEqual(hostusage.cells[1].cpu_usage, 0) self.assertEqual(hostusage.cells[1].memory_usage, 0) + # Test the case where we have an instance with numa topology + # and one without + def test_topo_usage_mixed(self): + 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([])), + objects.NUMACell(id=1, cpuset=set([2, 3]), memory=512, + cpu_usage=0, memory_usage=0, mempages=[], + siblings=[], pinned_cpus=set([])), + ]) + instance1_topo = objects.InstanceNUMATopology(cells=[ + objects.InstanceNUMACell(id=0, cpuset=set([0, 1]), memory=256), + objects.InstanceNUMACell(id=1, cpuset=set([2]), memory=128), + ]) + instance2_topo = None + + hostusage = hw.numa_usage_from_instances(hosttopo, [instance1_topo]) + self.assertEqual(hostusage.cells[0].cpu_usage, 2) + self.assertEqual(hostusage.cells[0].memory_usage, 256) + self.assertEqual(hostusage.cells[1].cpu_usage, 1) + self.assertEqual(hostusage.cells[1].memory_usage, 128) + + # This is like processing an instance with no numa_topology + hostusage = hw.numa_usage_from_instances(hostusage, instance2_topo) + self.assertEqual(hostusage.cells[0].cpu_usage, 2) + self.assertEqual(hostusage.cells[0].memory_usage, 256) + self.assertEqual(hostusage.cells[1].cpu_usage, 1) + self.assertEqual(hostusage.cells[1].memory_usage, 128) + def assertNUMACellMatches(self, expected_cell, got_cell): attrs = ('cpuset', 'memory', 'id') if isinstance(expected_cell, objects.NUMATopology): diff --git a/nova/virt/hardware.py b/nova/virt/hardware.py index a3ed4e16ab..47d6d6a845 100644 --- a/nova/virt/hardware.py +++ b/nova/virt/hardware.py @@ -1353,9 +1353,8 @@ def numa_usage_from_instances(host, instances, free=False): else: newcell.pin_cpus(pinned_cpus) - newcell.cpu_usage = max(0, cpu_usage) - newcell.memory_usage = max(0, memory_usage) - + newcell.cpu_usage = max(0, cpu_usage) + newcell.memory_usage = max(0, memory_usage) cells.append(newcell) return objects.NUMATopology(cells=cells)