Make use of 'InstanceNUMACell.cpu_policy' field

Fix the "magic" used to guess whether CPU pinning was requested by the
guest. This requires some minor reworking of tests.

Change-Id: Ic41360641d48c7560489ef8bc23a29874755a91f
Implements: blueprint virt-driver-cpu-thread-pinning
This commit is contained in:
Stephen Finucane 2015-07-14 14:31:48 +01:00
parent bba739a6e6
commit dfe6545329
4 changed files with 95 additions and 76 deletions

View File

@ -110,7 +110,7 @@ class InstanceNUMACell(base.NovaObject,
@property
def cpu_pinning_requested(self):
return self.cpu_pinning is not None
return self.cpu_policy == obj_fields.CPUAllocationPolicy.DEDICATED
def pin(self, vcpu, pcpu):
if vcpu not in self.cpuset:

View File

@ -18,6 +18,7 @@ from oslo_serialization import jsonutils
from nova import exception
from nova import objects
from nova.objects import fields
from nova.tests.unit.objects import test_objects
fake_instance_uuid = str(uuid.uuid4())
@ -149,14 +150,14 @@ class _TestInstanceNUMATopology(object):
inst_cell = objects.InstanceNUMACell(cpuset=set([0, 1, 2, 3]),
cpu_pinning=None)
self.assertFalse(inst_cell.cpu_pinning_requested)
inst_cell.cpu_pinning = {}
inst_cell.cpu_policy = fields.CPUAllocationPolicy.DEDICATED
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)))
cell.cpu_policy = fields.CPUAllocationPolicy.DEDICATED
self.assertTrue(fake_topo_obj.cpu_pinning_requested)

View File

@ -1020,7 +1020,8 @@ class NUMATopologyTest(test.NoDBTestCase):
# NUMA + CPU pinning requested in the flavor
"flavor": objects.Flavor(vcpus=4, memory_mb=2048,
extra_specs={
"hw:numa_nodes": 2, "hw:cpu_policy": "dedicated"
"hw:numa_nodes": 2,
"hw:cpu_policy": fields.CPUAllocationPolicy.DEDICATED
}),
"image": {
},
@ -1028,16 +1029,16 @@ class NUMATopologyTest(test.NoDBTestCase):
[
objects.InstanceNUMACell(
id=0, cpuset=set([0, 1]), memory=1024,
cpu_pinning={}),
cpu_policy=fields.CPUAllocationPolicy.DEDICATED),
objects.InstanceNUMACell(
id=1, cpuset=set([2, 3]), memory=1024,
cpu_pinning={})])
cpu_policy=fields.CPUAllocationPolicy.DEDICATED)])
},
{
# no NUMA + CPU pinning requested in the flavor
"flavor": objects.Flavor(vcpus=4, memory_mb=2048,
extra_specs={
"hw:cpu_policy": "dedicated"
"hw:cpu_policy": fields.CPUAllocationPolicy.DEDICATED
}),
"image": {
},
@ -1045,7 +1046,7 @@ class NUMATopologyTest(test.NoDBTestCase):
[
objects.InstanceNUMACell(
id=0, cpuset=set([0, 1, 2, 3]), memory=2048,
cpu_pinning={})])
cpu_policy=fields.CPUAllocationPolicy.DEDICATED)])
},
{
# NUMA + CPU pinning requested in the image
@ -1055,16 +1056,16 @@ class NUMATopologyTest(test.NoDBTestCase):
}),
"image": {
"properties": {
"hw_cpu_policy": "dedicated"}
},
"hw_cpu_policy": fields.CPUAllocationPolicy.DEDICATED
}},
"expect": objects.InstanceNUMATopology(cells=
[
objects.InstanceNUMACell(
id=0, cpuset=set([0, 1]), memory=1024,
cpu_pinning={}),
cpu_policy=fields.CPUAllocationPolicy.DEDICATED),
objects.InstanceNUMACell(
id=1, cpuset=set([2, 3]), memory=1024,
cpu_pinning={})])
cpu_policy=fields.CPUAllocationPolicy.DEDICATED)])
},
{
# no NUMA + CPU pinning requested in the image
@ -1072,23 +1073,24 @@ class NUMATopologyTest(test.NoDBTestCase):
extra_specs={}),
"image": {
"properties": {
"hw_cpu_policy": "dedicated"}
},
"hw_cpu_policy": fields.CPUAllocationPolicy.DEDICATED
}},
"expect": objects.InstanceNUMATopology(cells=
[
objects.InstanceNUMACell(
id=0, cpuset=set([0, 1, 2, 3]), memory=2048,
cpu_pinning={})])
cpu_policy=fields.CPUAllocationPolicy.DEDICATED)])
},
{
# Invalid CPU pinning override
"flavor": objects.Flavor(vcpus=4, memory_mb=2048,
extra_specs={
"hw:numa_nodes": 2, "hw:cpu_policy": "shared"
}),
"hw:numa_nodes": 2,
"hw:cpu_policy": fields.CPUAllocationPolicy.SHARED
}),
"image": {
"properties": {
"hw_cpu_policy": "dedicated"}
"hw_cpu_policy": fields.CPUAllocationPolicy.DEDICATED}
},
"expect": exception.ImageCPUPinningForbidden,
},
@ -1096,9 +1098,9 @@ class NUMATopologyTest(test.NoDBTestCase):
# Invalid CPU pinning policy with realtime
"flavor": objects.Flavor(vcpus=4, memory_mb=2048,
extra_specs={
"hw:cpu_policy": "shared",
"hw:cpu_realtime": "yes",
}),
"hw:cpu_policy": fields.CPUAllocationPolicy.SHARED,
"hw:cpu_realtime": "yes",
}),
"image": {
"properties": {}
},
@ -1108,13 +1110,14 @@ class NUMATopologyTest(test.NoDBTestCase):
# Invalid CPU thread pinning override
"flavor": objects.Flavor(vcpus=4, memory_mb=2048,
extra_specs={
"hw:numa_nodes": 2, "hw:cpu_policy": "dedicated",
"hw:numa_nodes": 2,
"hw:cpu_policy": fields.CPUAllocationPolicy.DEDICATED,
"hw:cpu_thread_policy":
fields.CPUThreadAllocationPolicy.ISOLATE,
}),
}),
"image": {
"properties": {
"hw_cpu_policy": "dedicated",
"hw_cpu_policy": fields.CPUAllocationPolicy.DEDICATED,
"hw_cpu_thread_policy":
fields.CPUThreadAllocationPolicy.REQUIRE,
}
@ -1125,10 +1128,10 @@ class NUMATopologyTest(test.NoDBTestCase):
# Invalid CPU pinning policy with CPU thread pinning
"flavor": objects.Flavor(vcpus=4, memory_mb=2048,
extra_specs={
"hw:cpu_policy": "shared",
"hw:cpu_policy": fields.CPUAllocationPolicy.SHARED,
"hw:cpu_thread_policy":
fields.CPUThreadAllocationPolicy.ISOLATE,
}),
}),
"image": {
"properties": {}
},
@ -2183,7 +2186,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
)
inst_topo = objects.InstanceNUMATopology(
cells=[objects.InstanceNUMACell(
cpuset=set([0, 1]), memory=2048, cpu_pinning={})])
cpuset=set([0, 1]), memory=2048,
cpu_policy=fields.CPUAllocationPolicy.DEDICATED)])
inst_topo = hw.numa_fit_instance_to_host(host_topo, inst_topo)
@ -2201,7 +2205,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
mempages=[], pinned_cpus=set([]))])
inst_topo = objects.InstanceNUMATopology(
cells=[objects.InstanceNUMACell(
cpuset=set([0, 1]), memory=2048, cpu_pinning={})])
cpuset=set([0, 1]), memory=2048,
cpu_policy=fields.CPUAllocationPolicy.DEDICATED)])
inst_topo = hw.numa_fit_instance_to_host(host_topo, inst_topo)
@ -2217,9 +2222,9 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
pinned_cpus=set([2]), memory_usage=0,
siblings=[], mempages=[])])
inst_topo = objects.InstanceNUMATopology(
cells=[objects.InstanceNUMACell(cpuset=set([0, 1]),
memory=2048,
cpu_pinning={})])
cells=[objects.InstanceNUMACell(
cpuset=set([0, 1]), memory=2048,
cpu_policy=fields.CPUAllocationPolicy.DEDICATED)])
inst_topo = hw.numa_fit_instance_to_host(host_topo, inst_topo)
self.assertIsNone(inst_topo)
@ -2235,10 +2240,12 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
siblings=[], mempages=[],
pinned_cpus=set([]))])
inst_topo = objects.InstanceNUMATopology(
cells=[objects.InstanceNUMACell(cpuset=set([0, 1]),
memory=2048, cpu_pinning={}),
objects.InstanceNUMACell(cpuset=set([2, 3]),
memory=2048, cpu_pinning={})])
cells=[objects.InstanceNUMACell(
cpuset=set([0, 1]), memory=2048,
cpu_policy=fields.CPUAllocationPolicy.DEDICATED),
objects.InstanceNUMACell(
cpuset=set([2, 3]), memory=2048,
cpu_policy=fields.CPUAllocationPolicy.DEDICATED)])
inst_topo = hw.numa_fit_instance_to_host(host_topo, inst_topo)
for cell in inst_topo.cells:
@ -2259,10 +2266,12 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
siblings=[], mempages=[],
pinned_cpus=set([10, 11]))])
inst_topo = objects.InstanceNUMATopology(
cells=[objects.InstanceNUMACell(cpuset=set([0, 1]),
memory=2048, cpu_pinning={}),
objects.InstanceNUMACell(cpuset=set([2, 3]),
memory=2048, cpu_pinning={})])
cells=[objects.InstanceNUMACell(
cpuset=set([0, 1]), memory=2048,
cpu_policy=fields.CPUAllocationPolicy.DEDICATED),
objects.InstanceNUMACell(
cpuset=set([2, 3]), memory=2048,
cpu_policy=fields.CPUAllocationPolicy.DEDICATED)])
inst_topo = hw.numa_fit_instance_to_host(host_topo, inst_topo)
for cell in inst_topo.cells:
@ -2279,10 +2288,12 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
siblings=[], mempages=[],
pinned_cpus=set([4, 5, 6]))])
inst_topo = objects.InstanceNUMATopology(
cells=[objects.InstanceNUMACell(cpuset=set([0, 1]),
memory=2048, cpu_pinning={}),
objects.InstanceNUMACell(cpuset=set([2, 3]),
memory=2048, cpu_pinning={})])
cells=[objects.InstanceNUMACell(
cpuset=set([0, 1]), memory=2048,
cpu_policy=fields.CPUAllocationPolicy.DEDICATED),
objects.InstanceNUMACell(
cpuset=set([2, 3]), memory=2048,
cpu_policy=fields.CPUAllocationPolicy.DEDICATED)])
inst_topo = hw.numa_fit_instance_to_host(host_topo, inst_topo)
self.assertIsNone(inst_topo)
@ -2297,12 +2308,15 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
siblings=[], mempages=[],
pinned_cpus=set([]))])
inst_topo = objects.InstanceNUMATopology(
cells=[objects.InstanceNUMACell(cpuset=set([0, 1]),
memory=1024, cpu_pinning={}),
objects.InstanceNUMACell(cpuset=set([2, 3]),
memory=1024, cpu_pinning={}),
objects.InstanceNUMACell(cpuset=set([4, 5]),
memory=1024, cpu_pinning={})])
cells=[objects.InstanceNUMACell(
cpuset=set([0, 1]), memory=1024,
cpu_policy=fields.CPUAllocationPolicy.DEDICATED),
objects.InstanceNUMACell(
cpuset=set([2, 3]), memory=1024,
cpu_policy=fields.CPUAllocationPolicy.DEDICATED),
objects.InstanceNUMACell(
cpuset=set([4, 5]), memory=1024,
cpu_policy=fields.CPUAllocationPolicy.DEDICATED)])
inst_topo = hw.numa_fit_instance_to_host(host_topo, inst_topo)
self.assertIsNone(inst_topo)
@ -2314,12 +2328,14 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
mempages=[], pinned_cpus=set([]))])
inst_pin_1 = objects.InstanceNUMATopology(
cells=[objects.InstanceNUMACell(
cpuset=set([0, 1]), id=0, cpu_pinning={0: 0, 1: 3},
memory=2048)])
cpuset=set([0, 1]), id=0, memory=2048,
cpu_pinning={0: 0, 1: 3},
cpu_policy=fields.CPUAllocationPolicy.DEDICATED)])
inst_pin_2 = objects.InstanceNUMATopology(
cells = [objects.InstanceNUMACell(
cpuset=set([0, 1]), id=0, cpu_pinning={0: 1, 1: 2},
memory=2048)])
cpuset=set([0, 1]), id=0, memory=2048,
cpu_pinning={0: 1, 1: 2},
cpu_policy=fields.CPUAllocationPolicy.DEDICATED)])
host_pin = hw.numa_usage_from_instances(
host_pin, [inst_pin_1, inst_pin_2])
@ -2334,11 +2350,13 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
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)])
cpuset=set([0]), memory=1024, cpu_pinning={0: 1}, id=0,
cpu_policy=fields.CPUAllocationPolicy.DEDICATED)])
inst_pin_2 = objects.InstanceNUMATopology(
cells=[objects.InstanceNUMACell(
cpuset=set([0, 1]), memory=1024, id=0,
cpu_pinning={0: 0, 1: 3})])
cpuset=set([0, 1]), memory=1024, id=0,
cpu_pinning={0: 0, 1: 3},
cpu_policy=fields.CPUAllocationPolicy.DEDICATED)])
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)
@ -2352,11 +2370,13 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
inst_pin_1 = objects.InstanceNUMATopology(
cells=[objects.InstanceNUMACell(
cpuset=set([0, 1]), memory=2048, id=0,
cpu_pinning={0: 0, 1: 3})])
cpu_pinning={0: 0, 1: 3},
cpu_policy=fields.CPUAllocationPolicy.DEDICATED)])
inst_pin_2 = objects.InstanceNUMATopology(
cells = [objects.InstanceNUMACell(
cpuset=set([0, 1]), id=0, memory=2048,
cpu_pinning={0: 0, 1: 2})])
cpu_pinning={0: 0, 1: 2},
cpu_policy=fields.CPUAllocationPolicy.DEDICATED)])
self.assertRaises(exception.CPUPinningInvalid,
hw.numa_usage_from_instances, host_pin,

View File

@ -1003,27 +1003,28 @@ def _numa_get_constraints_auto(nodes, flavor):
def _add_cpu_pinning_constraint(flavor, image_meta, numa_topology):
flavor_pinning = flavor.get('extra_specs', {}).get("hw:cpu_policy")
image_pinning = image_meta.properties.get("hw_cpu_policy")
if flavor_pinning == "dedicated":
requested = True
elif flavor_pinning == "shared":
if image_pinning == "dedicated":
flavor_policy = flavor.get('extra_specs', {}).get('hw:cpu_policy')
image_policy = image_meta.properties.get('hw_cpu_policy')
if flavor_policy == fields.CPUAllocationPolicy.DEDICATED:
cpu_policy = flavor_policy
elif flavor_policy == fields.CPUAllocationPolicy.SHARED:
if image_policy == fields.CPUAllocationPolicy.DEDICATED:
raise exception.ImageCPUPinningForbidden()
requested = False
cpu_policy = flavor_policy
elif image_policy == fields.CPUAllocationPolicy.DEDICATED:
cpu_policy = image_policy
else:
requested = image_pinning == "dedicated"
cpu_policy = fields.CPUAllocationPolicy.SHARED
rt = is_realtime_enabled(flavor)
pi = image_pinning or flavor_pinning
if rt and pi != "dedicated":
if (is_realtime_enabled(flavor) and
cpu_policy != fields.CPUAllocationPolicy.DEDICATED):
raise exception.RealtimeConfigurationInvalid()
flavor_thread_policy = flavor.get('extra_specs', {}).get(
'hw:cpu_thread_policy')
image_thread_policy = image_meta.properties.get('hw_cpu_thread_policy')
if not requested:
if cpu_policy == fields.CPUAllocationPolicy.SHARED:
if flavor_thread_policy or image_thread_policy:
raise exception.CPUThreadPolicyConfigurationInvalid()
return numa_topology
@ -1036,12 +1037,8 @@ def _add_cpu_pinning_constraint(flavor, image_meta, numa_topology):
cpu_thread_policy = flavor_thread_policy
if numa_topology:
# NOTE(ndipanov) Setting the cpu_pinning attribute to a non-None value
# means CPU pinning was requested
# TODO(sfinucan) Instead of using the "magic" described above, make use
# of the 'InstanceNUMACell.cpu_policy' parameter
for cell in numa_topology.cells:
cell.cpu_pinning = {}
cell.cpu_policy = cpu_policy
cell.cpu_thread_policy = cpu_thread_policy
return numa_topology
else:
@ -1049,7 +1046,7 @@ def _add_cpu_pinning_constraint(flavor, image_meta, numa_topology):
id=0,
cpuset=set(range(flavor.vcpus)),
memory=flavor.memory_mb,
cpu_pinning={},
cpu_policy=cpu_policy,
cpu_thread_policy=cpu_thread_policy)
numa_topology = objects.InstanceNUMATopology(cells=[single_cell])
return numa_topology
@ -1273,6 +1270,7 @@ def instance_topology_from_instance(instance):
memory=cell['memory'],
pagesize=cell.get('pagesize'),
cpu_pinning=cell.get('cpu_pinning_raw'),
cpu_policy=cell.get('cpu_policy'),
cpu_thread_policy=cell.get('cpu_thread_policy'))
for cell in dict_cells]
instance_numa_topology = objects.InstanceNUMATopology(