Add CPU pinning data to InstanceNUMACell object

We will use this object to hold the data about CPU pinning for each
instance. We add the CPU pinning and topology information to each
InstanceNUMACell. We will use this information to track pinning of each
instance.

Change-Id: Ic299e474ea210c9028a046b2665c0021fb2baf06
Blueprint: virt-driver-cpu-pinning
This commit is contained in:
Nikola Dipanov 2014-11-29 11:46:24 +01:00
parent 79603e3e95
commit 139529a90e
3 changed files with 92 additions and 10 deletions

View File

@ -17,22 +17,42 @@ from oslo.serialization import jsonutils
from nova import db
from nova import exception
from nova.objects import base
from nova.objects import fields
from nova.objects import fields as obj_fields
from nova.virt import hardware
class InstanceNUMACell(base.NovaObject):
# Version 1.0: Initial version
# Version 1.1: Add pagesize field
VERSION = '1.1'
# Version 1.2: Add cpu_pinning_raw and topology fields
VERSION = '1.2'
fields = {
'id': fields.IntegerField(read_only=True),
'cpuset': fields.SetOfIntegersField(),
'memory': fields.IntegerField(),
'pagesize': fields.IntegerField(nullable=True),
'id': obj_fields.IntegerField(read_only=True),
'cpuset': obj_fields.SetOfIntegersField(),
'memory': obj_fields.IntegerField(),
'pagesize': obj_fields.IntegerField(nullable=True),
'cpu_topology': obj_fields.ObjectField('VirtCPUTopology',
nullable=True),
'cpu_pinning_raw': obj_fields.DictOfIntegersField(nullable=True)
}
obj_relationships = {
'cpu_topology': [('1.2', '1.0')]
}
cpu_pinning = obj_fields.DictProxyField('cpu_pinning_raw')
def __init__(self, **kwargs):
super(InstanceNUMACell, self).__init__(**kwargs)
if 'cpu_topology' not in kwargs:
self.cpu_topology = None
if 'cpu_pinning' not in kwargs:
self.cpu_pinning = None
def __len__(self):
return len(self.cpuset)
def _to_dict(self):
# NOTE(sahid): Used as legacy, could be renamed in
# _legacy_to_dict_ to the future to avoid confusing.
@ -53,6 +73,29 @@ class InstanceNUMACell(base.NovaObject):
return cls(id=cell_id, cpuset=cpuset,
memory=memory, pagesize=pagesize)
@property
def siblings(self):
cpu_list = sorted(list(self.cpuset))
threads = 0
if self.cpu_topology:
threads = self.cpu_topology.threads
if threads == 1:
threads = 0
return map(set, zip(*[iter(cpu_list)] * threads))
def pin(self, vcpu, pcpu):
if vcpu not in self.cpuset:
return
pinning_dict = self.cpu_pinning or {}
pinning_dict[vcpu] = pcpu
self.cpu_pinning = pinning_dict
def pin_vcpus(self, *cpu_pairs):
for vcpu, pcpu in cpu_pairs:
self.pin(vcpu, pcpu)
class InstanceNUMATopology(base.NovaObject):
# Version 1.0: Initial version
@ -62,9 +105,9 @@ class InstanceNUMATopology(base.NovaObject):
fields = {
# NOTE(danms): The 'id' field is no longer used and should be
# removed in the future when convenient
'id': fields.IntegerField(),
'instance_uuid': fields.UUIDField(),
'cells': fields.ListOfObjectsField('InstanceNUMACell'),
'id': obj_fields.IntegerField(),
'instance_uuid': obj_fields.UUIDField(),
'cells': obj_fields.ListOfObjectsField('InstanceNUMACell'),
}
@classmethod

View File

@ -92,6 +92,44 @@ class _TestInstanceNUMATopology(object):
objects.InstanceNUMATopology.get_by_instance_uuid,
self.context, 'fake_uuid')
def test_siblings(self):
topo = objects.VirtCPUTopology(sockets=1, cores=3, threads=0)
inst_cell = objects.InstanceNUMACell(
cpuset=set([0, 1, 2]), topology=topo)
self.assertEqual([], inst_cell.siblings)
# One thread actually means no threads
topo = objects.VirtCPUTopology(sockets=1, cores=3, threads=1)
inst_cell = objects.InstanceNUMACell(
cpuset=set([0, 1, 2]), cpu_topology=topo)
self.assertEqual([], inst_cell.siblings)
topo = objects.VirtCPUTopology(sockets=1, cores=2, threads=2)
inst_cell = objects.InstanceNUMACell(
cpuset=set([0, 1, 2, 3]), cpu_topology=topo)
self.assertEqual([set([0, 1]), set([2, 3])], inst_cell.siblings)
topo = objects.VirtCPUTopology(sockets=1, cores=1, threads=4)
inst_cell = objects.InstanceNUMACell(
cpuset=set([0, 1, 2, 3]), cpu_topology=topo)
self.assertEqual([set([0, 1, 2, 3])], inst_cell.siblings)
def test_pin(self):
inst_cell = objects.InstanceNUMACell(cpuset=set([0, 1, 2, 3]),
cpu_pinning=None)
inst_cell.pin(0, 14)
self.assertEqual({0: 14}, inst_cell.cpu_pinning)
inst_cell.pin(12, 14)
self.assertEqual({0: 14}, inst_cell.cpu_pinning)
inst_cell.pin(1, 16)
self.assertEqual({0: 14, 1: 16}, inst_cell.cpu_pinning)
def test_pin_vcpus(self):
inst_cell = objects.InstanceNUMACell(cpuset=set([0, 1, 2, 3]),
cpu_pinning=None)
inst_cell.pin_vcpus((0, 14), (1, 15), (2, 16), (3, 17))
self.assertEqual({0: 14, 1: 15, 2: 16, 3: 17}, inst_cell.cpu_pinning)
class TestInstanceNUMATopology(test_objects._LocalTest,
_TestInstanceNUMATopology):

View File

@ -1103,7 +1103,7 @@ object_data = {
'InstanceGroupList': '1.6-c6b78f3c9d9080d33c08667e80589817',
'InstanceInfoCache': '1.5-ef64b604498bfa505a8c93747a9d8b2f',
'InstanceList': '1.13-179093360c48747a41694cc2f326d75d',
'InstanceNUMACell': '1.1-8d2a13c8360cc9ea1b68c9c6c4476857',
'InstanceNUMACell': '1.2-5d2dfa36e9ecca9b63f24bf3bc958ea4',
'InstanceNUMATopology': '1.1-86b95d263c4c68411d44c6741b8d2bb0',
'InstancePCIRequest': '1.1-e082d174f4643e5756ba098c47c1510f',
'InstancePCIRequests': '1.1-bc7c6684d8579ee49d6a3b8aef756918',
@ -1152,6 +1152,7 @@ object_relationships = {
'TagList': '1.0',
'SecurityGroupList': '1.0',
'InstancePCIRequests': '1.1'},
'InstanceNUMACell': {'VirtCPUTopology': '1.0'},
'MyObj': {'MyOwnedObject': '1.0'},
'SecurityGroupRule': {'SecurityGroup': '1.1'},
'Service': {'ComputeNode': '1.6'},