Merge "Make numa_usage_from_instances consider CPU pinning"
This commit is contained in:
commit
5bbb97f7be
@ -1822,3 +1822,8 @@ class MemoryPageSizeForbidden(Invalid):
|
||||
|
||||
class MemoryPageSizeNotSupported(Invalid):
|
||||
msg_fmt = _("Page size %(pagesize)s is not supported by the host.")
|
||||
|
||||
|
||||
class CPUPinningInvalid(Invalid):
|
||||
msg_fmt = _("Cannot pin/unpin cpus %(requested)s from the following "
|
||||
"pinned set %(pinned)s")
|
||||
|
@ -92,6 +92,10 @@ class InstanceNUMACell(base.NovaObject,
|
||||
|
||||
return map(set, zip(*[iter(cpu_list)] * threads))
|
||||
|
||||
@property
|
||||
def cpu_pinning_requested(self):
|
||||
return self.cpu_pinning is not None
|
||||
|
||||
def pin(self, vcpu, pcpu):
|
||||
if vcpu not in self.cpuset:
|
||||
return
|
||||
@ -202,3 +206,7 @@ class InstanceNUMATopology(base.NovaObject,
|
||||
return cls(cells=[
|
||||
InstanceNUMACell._from_dict(cell_dict)
|
||||
for cell_dict in data_dict.get('cells', [])])
|
||||
|
||||
@property
|
||||
def cpu_pinning_requested(self):
|
||||
return all(cell.cpu_pinning_requested for cell in self.cells)
|
||||
|
@ -67,6 +67,18 @@ class NUMACell(base.NovaObject,
|
||||
def avail_memory(self):
|
||||
return self.memory - self.memory_usage
|
||||
|
||||
def pin_cpus(self, cpus):
|
||||
if self.pinned_cpus & cpus:
|
||||
raise exception.CPUPinningInvalid(requested=list(cpus),
|
||||
pinned=list(self.pinned_cpus))
|
||||
self.pinned_cpus |= cpus
|
||||
|
||||
def unpin_cpus(self, cpus):
|
||||
if (self.pinned_cpus & cpus) != cpus:
|
||||
raise exception.CPUPinningInvalid(requested=list(cpus),
|
||||
pinned=list(self.pinned_cpus))
|
||||
self.pinned_cpus -= cpus
|
||||
|
||||
def _to_dict(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
|
@ -10,6 +10,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
import uuid
|
||||
|
||||
import mock
|
||||
@ -140,6 +141,20 @@ class _TestInstanceNUMATopology(object):
|
||||
inst_cell = objects.InstanceNUMACell()
|
||||
self.assertEqual(0, len(inst_cell.obj_get_changes()))
|
||||
|
||||
def test_cpu_pinning_requested_cell(self):
|
||||
inst_cell = objects.InstanceNUMACell(cpuset=set([0, 1, 2, 3]),
|
||||
cpu_pinning=None)
|
||||
self.assertFalse(inst_cell.cpu_pinning_requested)
|
||||
inst_cell.cpu_pinning = {}
|
||||
self.assertTrue(inst_cell.cpu_pinning_requested)
|
||||
|
||||
def test_cpu_pinning_requested(self):
|
||||
fake_topo_obj = copy.deepcopy(fake_obj_numa_topology)
|
||||
self.assertFalse(fake_topo_obj.cpu_pinning_requested)
|
||||
for cell in fake_topo_obj.cells:
|
||||
cell.cpu_pinning = dict(zip(*map(list, [cell.cpuset] * 2)))
|
||||
self.assertTrue(fake_topo_obj.cpu_pinning_requested)
|
||||
|
||||
|
||||
class TestInstanceNUMATopology(test_objects._LocalTest,
|
||||
_TestInstanceNUMATopology):
|
||||
|
@ -33,7 +33,7 @@ class _TestNUMA(object):
|
||||
|
||||
self.assertEqual(d1, d2)
|
||||
|
||||
def test_pinning_logic(self):
|
||||
def test_free_cpus(self):
|
||||
obj = objects.NUMATopology(cells=[
|
||||
objects.NUMACell(
|
||||
id=0, cpuset=set([1, 2]), memory=512,
|
||||
@ -48,6 +48,21 @@ class _TestNUMA(object):
|
||||
self.assertEqual(set([2]), obj.cells[0].free_cpus)
|
||||
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]))
|
||||
numacell.pin_cpus(set([2, 3]))
|
||||
self.assertEqual(set([4]), numacell.free_cpus)
|
||||
self.assertRaises(exception.CPUPinningInvalid,
|
||||
numacell.pin_cpus, set([1, 4]))
|
||||
self.assertRaises(exception.CPUPinningInvalid,
|
||||
numacell.pin_cpus, set([1, 6]))
|
||||
self.assertRaises(exception.CPUPinningInvalid,
|
||||
numacell.unpin_cpus, set([1, 4]))
|
||||
numacell.unpin_cpus(set([1, 2, 3]))
|
||||
self.assertEqual(set([1, 2, 3, 4]), numacell.free_cpus)
|
||||
|
||||
def test_pages_topology_wipe(self):
|
||||
pages_topology = objects.NUMAPagesTopology(
|
||||
size_kb=2048, total=1024, used=512)
|
||||
|
@ -1828,3 +1828,56 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
|
||||
memory=1024, cpu_pinning={})])
|
||||
inst_topo = hw.numa_fit_instance_to_host(host_topo, inst_topo)
|
||||
self.assertIsNone(inst_topo)
|
||||
|
||||
def test_cpu_pinning_usage_from_instances(self):
|
||||
host_pin = objects.NUMATopology(
|
||||
cells=[objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]),
|
||||
memory=4096, cpu_usage=0,
|
||||
memory_usage=0)])
|
||||
inst_pin_1 = objects.InstanceNUMATopology(
|
||||
cells=[objects.InstanceNUMACell(
|
||||
cpuset=set([0, 1]), id=0, cpu_pinning={0: 0, 1: 3},
|
||||
memory=2048)])
|
||||
inst_pin_2 = objects.InstanceNUMATopology(
|
||||
cells = [objects.InstanceNUMACell(
|
||||
cpuset=set([0, 1]), id=0, cpu_pinning={0: 1, 1: 2},
|
||||
memory=2048)])
|
||||
|
||||
host_pin = hw.numa_usage_from_instances(
|
||||
host_pin, [inst_pin_1, inst_pin_2])
|
||||
self.assertEqual(set([0, 1, 2, 3]),
|
||||
host_pin.cells[0].pinned_cpus)
|
||||
|
||||
def test_cpu_pinning_usage_from_instances_free(self):
|
||||
host_pin = objects.NUMATopology(
|
||||
cells=[objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]),
|
||||
memory=4096, cpu_usage=0, memory_usage=0,
|
||||
pinned_cpus=set([0, 1, 3]))])
|
||||
inst_pin_1 = objects.InstanceNUMATopology(
|
||||
cells=[objects.InstanceNUMACell(
|
||||
cpuset=set([0]), memory=1024, cpu_pinning={0: 1}, id=0)])
|
||||
inst_pin_2 = objects.InstanceNUMATopology(
|
||||
cells=[objects.InstanceNUMACell(
|
||||
cpuset=set([0, 1]), memory=1024, id=0,
|
||||
cpu_pinning={0: 0, 1: 3})])
|
||||
host_pin = hw.numa_usage_from_instances(
|
||||
host_pin, [inst_pin_1, inst_pin_2], free=True)
|
||||
self.assertEqual(set(), host_pin.cells[0].pinned_cpus)
|
||||
|
||||
def test_host_usage_from_instances_fail(self):
|
||||
host_pin = objects.NUMATopology(
|
||||
cells=[objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]),
|
||||
memory=4096, cpu_usage=0,
|
||||
memory_usage=0)])
|
||||
inst_pin_1 = objects.InstanceNUMATopology(
|
||||
cells=[objects.InstanceNUMACell(
|
||||
cpuset=set([0, 1]), memory=2048, id=0,
|
||||
cpu_pinning={0: 0, 1: 3})])
|
||||
inst_pin_2 = objects.InstanceNUMATopology(
|
||||
cells = [objects.InstanceNUMACell(
|
||||
cpuset=set([0, 1]), id=0, memory=2048,
|
||||
cpu_pinning={0: 0, 1: 2})])
|
||||
|
||||
self.assertRaises(exception.CPUPinningInvalid,
|
||||
hw.numa_usage_from_instances, host_pin,
|
||||
[inst_pin_1, inst_pin_2])
|
||||
|
@ -779,7 +779,7 @@ def _numa_fit_instance_cell(host_cell, instance_cell, limit_cell=None):
|
||||
len(instance_cell.cpuset) > len(host_cell.cpuset)):
|
||||
return None
|
||||
|
||||
if instance_cell.cpu_pinning is not None:
|
||||
if instance_cell.cpu_pinning_requested:
|
||||
new_instance_cell = _numa_fit_instance_cell_with_pinning(
|
||||
host_cell, instance_cell)
|
||||
if not new_instance_cell:
|
||||
@ -1121,7 +1121,12 @@ def numa_usage_from_instances(host, instances, free=False):
|
||||
for hostcell in host.cells:
|
||||
memory_usage = hostcell.memory_usage
|
||||
cpu_usage = hostcell.cpu_usage
|
||||
mempages = hostcell.mempages
|
||||
|
||||
newcell = objects.NUMACell(
|
||||
id=hostcell.id, cpuset=hostcell.cpuset, memory=hostcell.memory,
|
||||
cpu_usage=0, memory_usage=0,
|
||||
pinned_cpus=hostcell.pinned_cpus, siblings=hostcell.siblings)
|
||||
|
||||
for instance in instances:
|
||||
for instancecell in instance.cells:
|
||||
if instancecell.id == hostcell.id:
|
||||
@ -1129,15 +1134,19 @@ def numa_usage_from_instances(host, instances, free=False):
|
||||
memory_usage + sign * instancecell.memory)
|
||||
cpu_usage = cpu_usage + sign * len(instancecell.cpuset)
|
||||
if instancecell.pagesize and instancecell.pagesize > 0:
|
||||
mempages = _numa_pagesize_usage_from_cell(
|
||||
newcell.mempages = _numa_pagesize_usage_from_cell(
|
||||
hostcell, instancecell, sign)
|
||||
if instance.cpu_pinning_requested:
|
||||
pinned_cpus = set(instancecell.cpu_pinning.values())
|
||||
if free:
|
||||
newcell.unpin_cpus(pinned_cpus)
|
||||
else:
|
||||
newcell.pin_cpus(pinned_cpus)
|
||||
|
||||
cell = objects.NUMACell(
|
||||
id=hostcell.id, cpuset=hostcell.cpuset, memory=hostcell.memory,
|
||||
cpu_usage=max(0, cpu_usage), memory_usage=max(0, memory_usage),
|
||||
mempages=mempages)
|
||||
newcell.cpu_usage = max(0, cpu_usage)
|
||||
newcell.memory_usage = max(0, memory_usage)
|
||||
|
||||
cells.append(cell)
|
||||
cells.append(newcell)
|
||||
|
||||
return objects.NUMATopology(cells=cells)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user