Skip to content

Commit ba3388d

Browse files
committed
objects: Introduce the 'CPUAllocationPolicy.MIXED' enum
Introduce a 'mixed' instance CPU allocation policy and will be worked with upcoming patches, for purpose of creating an instance combined shared CPUs with dedicated or realtime CPUs. In an instance mixed with different type of CPUs, the shared CPU shared CPU time slots with other instances, and also might be a CPU with less or un-guaranteed hardware resources, which implies to have no guarantee for the behavior of the workload running on it. If we call the shared CPU as 'low priority' CPU, then the realtime or dedicated CPU could be called as 'high priority' CPU, user could assign more hardware CPU resources or place some guaranteed resource to it to let the workload to entail high performance or stable service quality. Based on https://review.opendev.org/714704 Part of blueprint use-pcpu-and-vcpu-in-one-instance Change-Id: I99cfee14bb105a8792651129426c0c5a3749796d Signed-off-by: Wang Huaqiang <[email protected]>
1 parent d992eb2 commit ba3388d

File tree

17 files changed

+203
-20
lines changed

17 files changed

+203
-20
lines changed

doc/notification_samples/common_payloads/ImageMetaPropsPayload.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
"hw_architecture": "x86_64"
55
},
66
"nova_object.name": "ImageMetaPropsPayload",
7-
"nova_object.version": "1.3"
7+
"nova_object.version": "1.4"
88
}

doc/notification_samples/common_payloads/InstanceNUMACellPayload.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"nova_object.version": "1.1",
2+
"nova_object.version": "1.2",
33
"nova_object.namespace": "nova",
44
"nova_object.name": "InstanceNUMACellPayload",
55
"nova_object.data": {

nova/api/openstack/compute/servers.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@
8787
exception.PciRequestAliasNotDefined,
8888
exception.RealtimeConfigurationInvalid,
8989
exception.RealtimeMaskNotFoundOrInvalid,
90+
exception.RequiredMixedInstancePolicy,
91+
exception.RequiredMixedOrRealtimeCPUMask,
9092
)
9193

9294
MIN_COMPUTE_MOVE_BANDWIDTH = 39

nova/api/validation/extra_specs/hw.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,17 @@
6363
'CPUs can run on. If ``shared`` (default), guest CPUs can be '
6464
'overallocated but cannot float across host cores. If '
6565
'``dedicated``, guest CPUs cannot be overallocated but are '
66-
'individually pinned to their own host core.'
66+
'individually pinned to their own host core. ``mixed`` is a '
67+
'policy with which the guest is mixing the overallocated and '
68+
'pinned guest CPUs.'
6769
),
6870
value={
6971
'type': str,
7072
'description': 'The CPU policy.',
7173
'enum': [
7274
'dedicated',
73-
'shared'
75+
'shared',
76+
'mixed',
7477
],
7578
},
7679
),

nova/exception.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2314,3 +2314,14 @@ class AcceleratorRequestOpFailed(NovaException):
23142314

23152315
class InvalidLibvirtGPUConfig(NovaException):
23162316
msg_fmt = _('Invalid configuration for GPU devices: %(reason)s')
2317+
2318+
2319+
class RequiredMixedInstancePolicy(Invalid):
2320+
msg_fmt = _("Cannot specify 'hw:cpu_dedicated_mask' without the "
2321+
"'mixed' policy.")
2322+
2323+
2324+
class RequiredMixedOrRealtimeCPUMask(Invalid):
2325+
msg_fmt = _("Must specify either 'hw:cpu_dedicated_mask' or "
2326+
"'hw:cpu_realtime_mask' when using 'mixed' CPU policy"
2327+
" instance.")

nova/notifications/objects/image.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ class ImageMetaPropsPayload(base.NotificationPayloadBase):
120120
# Version 1.1: Added 'gop', 'virtio' and 'none' to hw_video_model field
121121
# Version 1.2: Added hw_pci_numa_affinity_policy field
122122
# Version 1.3: Added hw_mem_encryption, hw_pmu and hw_time_hpet fields
123-
VERSION = '1.3'
123+
# Version 1.4: Added 'mixed' to hw_cpu_policy field
124+
VERSION = '1.4'
124125

125126
SCHEMA = {
126127
k: ('image_meta_props', k) for k in image_meta.ImageMetaProps.fields}

nova/notifications/objects/request_spec.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ def __init__(self, numa_topology):
144144
class InstanceNUMACellPayload(base.NotificationPayloadBase):
145145
# Version 1.0: Initial version
146146
# Version 1.1: Added pcpuset field
147-
VERSION = '1.1'
147+
# Version 1.2: Added 'mixed' to cpu_policy field
148+
VERSION = '1.2'
148149

149150
SCHEMA = {
150151
'id': ('numa_cell', 'id'),

nova/objects/fields.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,9 @@ class CPUAllocationPolicy(BaseNovaEnum):
272272

273273
DEDICATED = "dedicated"
274274
SHARED = "shared"
275+
MIXED = "mixed"
275276

276-
ALL = (DEDICATED, SHARED)
277+
ALL = (DEDICATED, SHARED, MIXED)
277278

278279

279280
class CPUThreadAllocationPolicy(BaseNovaEnum):

nova/objects/image_meta.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,14 +175,22 @@ class ImageMetaProps(base.NovaObject):
175175
# Version 1.23: Added 'hw_pmu' field
176176
# Version 1.24: Added 'hw_mem_encryption' field
177177
# Version 1.25: Added 'hw_pci_numa_affinity_policy' field
178+
# Version 1.26: Added 'mixed' to 'hw_cpu_policy' field
178179
# NOTE(efried): When bumping this version, the version of
179180
# ImageMetaPropsPayload must also be bumped. See its docstring for details.
180-
VERSION = '1.25'
181+
VERSION = '1.26'
181182

182183
def obj_make_compatible(self, primitive, target_version):
183184
super(ImageMetaProps, self).obj_make_compatible(primitive,
184185
target_version)
185186
target_version = versionutils.convert_version_to_tuple(target_version)
187+
if target_version < (1, 26):
188+
policy = primitive.get('hw_cpu_policy', None)
189+
if policy == fields.CPUAllocationPolicy.MIXED:
190+
raise exception.ObjectActionError(
191+
action='obj_make_compatible',
192+
reason='hw_cpu_policy=%s not supported in version %s' %
193+
(policy, target_version))
186194
if target_version < (1, 25):
187195
primitive.pop('hw_pci_numa_affinity_policy', None)
188196
if target_version < (1, 24):

nova/objects/instance_numa.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
from nova.db import api as db
2121
from nova import exception
22+
from nova.i18n import _
2223
from nova.objects import base
2324
from nova.objects import fields as obj_fields
2425
from nova.virt import hardware
@@ -34,12 +35,22 @@ class InstanceNUMACell(base.NovaEphemeralObject,
3435
# Version 1.3: Add cpu_policy and cpu_thread_policy fields
3536
# Version 1.4: Add cpuset_reserved field
3637
# Version 1.5: Add pcpuset field
37-
VERSION = '1.5'
38+
# Version 1.6: Add 'mixed' to cpu_policy field
39+
VERSION = '1.6'
3840

3941
def obj_make_compatible(self, primitive, target_version):
4042
super(InstanceNUMACell, self).obj_make_compatible(primitive,
4143
target_version)
4244
target_version = versionutils.convert_version_to_tuple(target_version)
45+
# Instance with a 'mixed' CPU policy could not provide a backward
46+
# compatibility.
47+
if target_version < (1, 6):
48+
if primitive['cpu_policy'] == obj_fields.CPUAllocationPolicy.MIXED:
49+
raise exception.ObjectActionError(
50+
action='obj_make_compatible',
51+
reason=_('mixed instance is not supported in version %s') %
52+
target_version)
53+
4354
# NOTE(huaqiang): Since version 1.5, 'cpuset' is modified to track the
4455
# unpinned CPUs only, with pinned CPUs tracked via 'pcpuset' instead.
4556
# For a backward compatibility, move the 'dedicated' instance CPU list

nova/tests/functional/notification_sample_tests/test_instance.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,7 +1249,7 @@ def test_rebuild_server(self):
12491249
'nova_object.data': {},
12501250
'nova_object.name': 'ImageMetaPropsPayload',
12511251
'nova_object.namespace': 'nova',
1252-
'nova_object.version': u'1.3'},
1252+
'nova_object.version': u'1.4'},
12531253
'image.size': 58145823,
12541254
'image.tags': [],
12551255
'scheduler_hints': {'_nova_check_type': ['rebuild']},
@@ -1344,7 +1344,7 @@ def test_rebuild_server_with_trusted_cert(self):
13441344
'nova_object.data': {},
13451345
'nova_object.name': 'ImageMetaPropsPayload',
13461346
'nova_object.namespace': 'nova',
1347-
'nova_object.version': u'1.3'},
1347+
'nova_object.version': u'1.4'},
13481348
'image.size': 58145823,
13491349
'image.tags': [],
13501350
'scheduler_hints': {'_nova_check_type': ['rebuild']},

nova/tests/unit/api/validation/extra_specs/test_validators.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ def test_value__str(self):
6969
('hw:cpu_thread_policy', 'prefer'),
7070
('hw:emulator_threads_policy', 'isolate'),
7171
('hw:pci_numa_affinity_policy', 'legacy'),
72+
('hw:cpu_policy', 'mixed'),
7273
)
7374
for key, value in valid_specs:
7475
validators.validate(key, value)

nova/tests/unit/compute/test_compute.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13352,10 +13352,17 @@ def test_image_blockdevicemapping_min_disk(self):
1335213352
self.context, image['id'],
1335313353
image, self.instance_type, root_bdm)
1335413354

13355-
def test_cpu_policy(self):
13355+
@mock.patch('nova.virt.hardware.get_dedicated_cpu_constraint')
13356+
def test_cpu_policy(self, dedicated_cpu_mock):
1335613357
image = {'id': uuids.image_id, 'status': 'active'}
1335713358
for v in obj_fields.CPUAllocationPolicy.ALL:
1335813359
image['properties'] = {'hw_cpu_policy': v}
13360+
# 'mixed' policy requires a definition of 'cpu_dedicated_mask'
13361+
if v == obj_fields.CPUAllocationPolicy.MIXED:
13362+
dedicated_cpu_mock.return_value = set([0])
13363+
else:
13364+
dedicated_cpu_mock.return_value = None
13365+
1335913366
self.compute_api._validate_flavor_image(
1336013367
self.context, image['id'], image, self.instance_type, None)
1336113368
image['properties'] = {'hw_cpu_policy': 'bar'}

nova/tests/unit/notifications/objects/test_notification.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ def test_payload_is_not_generated_if_notification_format_is_unversioned(
387387
# ImageMetaProps, so when you see a fail here for that reason, you must
388388
# *also* bump the version of ImageMetaPropsPayload. See its docstring for
389389
# more information.
390-
'ImageMetaPropsPayload': '1.3-9c200c895932163a4e14e6bb385fa1e0',
390+
'ImageMetaPropsPayload': '1.4-036c794843b95a3a39ee70830f5f6557',
391391
'InstanceActionNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
392392
'InstanceActionPayload': '1.8-4fa3da9cbf0761f1f700ae578f36dc2f',
393393
'InstanceActionRebuildNotification':
@@ -411,7 +411,7 @@ def test_payload_is_not_generated_if_notification_format_is_unversioned(
411411
'InstanceActionSnapshotPayload': '1.9-c3e0bbaaefafdfa2f8e6e504c2c9b12c',
412412
'InstanceExistsNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
413413
'InstanceExistsPayload': '1.2-e082c02438ee57164829afaeee3bf7f8',
414-
'InstanceNUMACellPayload': '1.1-2a24ab42bf5e8dfa98291402725bf278',
414+
'InstanceNUMACellPayload': '1.2-a367add3378c71c21c817ab2b23db3bf',
415415
'InstanceNUMATopologyPayload': '1.0-247361b152047c18ae9ad1da2544a3c9',
416416
'InstancePCIRequestPayload': '1.0-12d0d61baf183daaafd93cbeeed2956f',
417417
'InstancePCIRequestsPayload': '1.0-6751cffe0c0fabd212aad624f672429a',

nova/tests/unit/objects/test_objects.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,7 @@ def obj_name(cls):
10771077
'HyperVLiveMigrateData': '1.4-e265780e6acfa631476c8170e8d6fce0',
10781078
'IDEDeviceBus': '1.0-29d4c9f27ac44197f01b6ac1b7e16502',
10791079
'ImageMeta': '1.8-642d1b2eb3e880a367f37d72dd76162d',
1080-
'ImageMetaProps': '1.25-66fc973af215eb5701ed4034bb6f0685',
1080+
'ImageMetaProps': '1.26-b9f136cd10a2b5ffb3ae44332f2f687d',
10811081
'Instance': '2.7-d187aec68cad2e4d8b8a03a68e4739ce',
10821082
'InstanceAction': '1.2-9a5abc87fdd3af46f45731960651efb5',
10831083
'InstanceActionEvent': '1.4-5b1f361bd81989f8bb2c20bb7e8a4cb4',
@@ -1093,7 +1093,7 @@ def obj_name(cls):
10931093
'InstanceList': '2.6-238f125650c25d6d12722340d726f723',
10941094
'InstanceMapping': '1.2-3bd375e65c8eb9c45498d2f87b882e03',
10951095
'InstanceMappingList': '1.3-d34b6ebb076d542ae0f8b440534118da',
1096-
'InstanceNUMACell': '1.5-d6f884326eba8cae60930e06047fc7d9',
1096+
'InstanceNUMACell': '1.6-25d9120d83a18356f4146f2a6fe2cc8d',
10971097
'InstanceNUMATopology': '1.3-ec0030cb0402a49c96da7051c037082a',
10981098
'InstancePCIRequest': '1.3-f6d324f1c337fad4f34892ed5f484c9a',
10991099
'InstancePCIRequests': '1.1-65e38083177726d806684cb1cc0136d2',

nova/tests/unit/virt/test_hardware.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,10 +932,75 @@ def test_cpu_policy_constraint(self):
932932
),
933933
"image": {
934934
"properties": {
935+
"hw_cpu_policy": "shared"
935936
}
936937
},
937938
"expect": fields.CPUAllocationPolicy.DEDICATED
938939
},
940+
{
941+
"flavor": objects.Flavor(
942+
extra_specs={
943+
"hw:cpu_policy": "dedicated"
944+
}
945+
),
946+
"image": {
947+
"properties": {
948+
}
949+
},
950+
"expect": fields.CPUAllocationPolicy.DEDICATED
951+
},
952+
{
953+
954+
"flavor": objects.Flavor(
955+
extra_specs={
956+
"hw:cpu_policy": "mixed"
957+
}
958+
),
959+
"image": {
960+
"properties": {
961+
"hw_cpu_policy": "dedicated"
962+
}
963+
},
964+
"expect": exception.ImageCPUPinningForbidden
965+
},
966+
{
967+
"flavor": objects.Flavor(
968+
extra_specs={
969+
"hw:cpu_policy": "mixed"
970+
}
971+
),
972+
"image": {
973+
"properties": {
974+
"hw_cpu_policy": "mixed"
975+
}
976+
},
977+
"expect": fields.CPUAllocationPolicy.MIXED
978+
},
979+
{
980+
"flavor": objects.Flavor(
981+
extra_specs={
982+
"hw:cpu_policy": "mixed"
983+
}
984+
),
985+
"image": {
986+
"properties": {
987+
"hw_cpu_policy": "shared"
988+
}
989+
},
990+
"expect": fields.CPUAllocationPolicy.MIXED
991+
},
992+
{
993+
"flavor": objects.Flavor(
994+
extra_specs={
995+
"hw:cpu_policy": "mixed"
996+
}
997+
),
998+
"image": {
999+
"properties": {
1000+
}
1001+
},
1002+
"expect": fields.CPUAllocationPolicy.MIXED
1003+
},
9391004
{
9401005
"flavor": objects.Flavor(
9411006
extra_specs={
@@ -949,6 +1014,19 @@ def test_cpu_policy_constraint(self):
9491014
},
9501015
"expect": exception.ImageCPUPinningForbidden
9511016
},
1017+
{
1018+
"flavor": objects.Flavor(
1019+
extra_specs={
1020+
"hw:cpu_policy": "shared"
1021+
}
1022+
),
1023+
"image": {
1024+
"properties": {
1025+
"hw_cpu_policy": "mixed"
1026+
}
1027+
},
1028+
"expect": exception.ImageCPUPinningForbidden
1029+
},
9521030
{
9531031
"flavor": objects.Flavor(
9541032
extra_specs={
@@ -983,6 +1061,15 @@ def test_cpu_policy_constraint(self):
9831061
},
9841062
"expect": fields.CPUAllocationPolicy.DEDICATED
9851063
},
1064+
{
1065+
"flavor": objects.Flavor(),
1066+
"image": {
1067+
"properties": {
1068+
"hw_cpu_policy": "mixed"
1069+
}
1070+
},
1071+
"expect": fields.CPUAllocationPolicy.MIXED
1072+
},
9861073
{
9871074
"flavor": objects.Flavor(),
9881075
"image": {

0 commit comments

Comments
 (0)