Merge "hardware: create 'mixed' instance for realtime CPUs"
This commit is contained in:
commit
97b0d251f7
@ -221,10 +221,12 @@ use pinned CPUs. To configure a flavor to use the ``shared`` CPU policy, run:
|
||||
$ openstack flavor set [FLAVOR_ID] --property hw:cpu_policy=shared
|
||||
|
||||
The ``mixed`` CPU policy is used to specify that an instance use pinned CPUs
|
||||
along with unpinned CPUs. The instance pinned CPU is specified in the
|
||||
``hw:cpu_dedicated_mask`` extra spec. For example, to configure a flavor to
|
||||
use the ``mixed`` CPU policy with 4 vCPUs in total and the first 2 vCPUs as
|
||||
pinned CPUs:
|
||||
along with unpinned CPUs. The instance pinned CPU could be specified in the
|
||||
``hw:cpu_dedicated_mask`` or, if real-time is enabled
|
||||
(``hw:cpu_realtime``\ = yes), in the ``hw:cpu_realtime_mask`` extra spec. For
|
||||
example, to configure a flavor to use the ``mixed`` CPU policy with 4 vCPUs in
|
||||
total and the first 2 vCPUs as pinned CPUs, with the ``hw:cpu_realtime_mask``
|
||||
extra spec, run:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
@ -233,13 +235,21 @@ pinned CPUs:
|
||||
--property hw:cpu_policy=mixed \
|
||||
--property hw:cpu_dedicated_mask=0-1
|
||||
|
||||
For more information about the syntax for ``hw:cpu_dedicated_mask``, refer
|
||||
to the :doc:`/user/flavors` guide.
|
||||
To create the mixed instance with the real-time extra specs, run:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ openstack flavor set [FLAVOR_ID] \
|
||||
--vcpus=4 \
|
||||
--property hw:cpu_policy=mixed \
|
||||
--property hw:cpu_realtime=yes \
|
||||
--property hw:cpu_realtime_mask=0-1
|
||||
|
||||
.. note::
|
||||
|
||||
For more information about the syntax for ``hw:cpu_policy``, refer to the
|
||||
:doc:`/admin/flavors` guide.
|
||||
For more information about the syntax for ``hw:cpu_policy``,
|
||||
``hw:cpu_dedicated_mask``, ``hw:realtime_cpu`` and ``hw:cpu_realtime_mask``,
|
||||
refer to the :doc:`/user/flavors` guide.
|
||||
|
||||
It is also possible to configure the CPU policy via image metadata. This can
|
||||
be useful when packaging applications that require real-time or near real-time
|
||||
|
@ -467,7 +467,8 @@ CPU pinning policy
|
||||
.. note::
|
||||
|
||||
The ``hw:cpu_dedicated_mask`` option is only valid if ``hw:cpu_policy``
|
||||
is set to ``mixed``.
|
||||
is set to ``mixed`` and cannot be configured with ``hw:cpu_realtime_mask``
|
||||
at the same time.
|
||||
|
||||
Valid CPU-THREAD-POLICY values are:
|
||||
|
||||
|
@ -2326,9 +2326,11 @@ class RequiredMixedInstancePolicy(Invalid):
|
||||
|
||||
|
||||
class RequiredMixedOrRealtimeCPUMask(Invalid):
|
||||
msg_fmt = _("Must specify either 'hw:cpu_dedicated_mask' or "
|
||||
"'hw:cpu_realtime_mask' when using 'mixed' CPU policy"
|
||||
" instance.")
|
||||
msg_fmt = _("Dedicated CPU set can be specified from either "
|
||||
"'hw:cpu_dedicated_mask' or 'hw:cpu_realtime_mask' when "
|
||||
"using 'mixed' CPU policy. 'hw:cpu_dedicated_mask' and "
|
||||
"'hw:cpu_realtime_mask' can not be specified at the same "
|
||||
"time, or be specified with none of them.")
|
||||
|
||||
|
||||
class MixedInstanceNotSupportByComputeService(NovaException):
|
||||
|
@ -280,11 +280,13 @@ class ResourceRequest(object):
|
||||
|
||||
if cpu_policy == obj_fields.CPUAllocationPolicy.MIXED:
|
||||
# Get dedicated CPU list from flavor extra spec. For a mixed
|
||||
# instance a non-empty 'hw:cpu_dedicated_mask' configuration must
|
||||
# exist, which is already ensured in the API layer.
|
||||
# instance a non-empty 'hw:cpu_dedicated_mask' or realtime CPU
|
||||
# mask configuration must exist, which is already ensured in
|
||||
# the API layer.
|
||||
dedicated_cpus = hardware.get_dedicated_cpu_constraint(flavor)
|
||||
realtime_cpus = hardware.get_realtime_cpu_constraint(flavor, image)
|
||||
|
||||
pcpus = len(dedicated_cpus)
|
||||
pcpus = len(dedicated_cpus or realtime_cpus)
|
||||
vcpus = flavor.vcpus - pcpus
|
||||
|
||||
# apply for the VCPU resource of a 'mixed' instance
|
||||
|
@ -1080,17 +1080,10 @@ class TestUtils(TestUtilsBase):
|
||||
self.assertResourceRequestsEqual(expected, rr)
|
||||
self.assertFalse(rr.cpu_pinning_requested)
|
||||
|
||||
def test_resource_request_init_with_mixed_cpus(self):
|
||||
"""Ensure the mixed instance properly requests the PCPU, VCPU,
|
||||
MEMORY_MB, DISK_GB resources.
|
||||
"""
|
||||
def _test_resource_request_init_with_mixed_cpus(self, extra_specs):
|
||||
flavor = objects.Flavor(
|
||||
vcpus=4, memory_mb=1024, root_gb=10, ephemeral_gb=5, swap=0,
|
||||
extra_specs={
|
||||
'hw:cpu_policy': 'mixed',
|
||||
'hw:cpu_dedicated_mask': '2,3'
|
||||
})
|
||||
|
||||
extra_specs=extra_specs)
|
||||
rs = objects.RequestSpec(flavor=flavor)
|
||||
expected = FakeResourceRequest()
|
||||
expected._rg_by_id[None] = objects.RequestGroup(
|
||||
@ -1106,19 +1099,33 @@ class TestUtils(TestUtilsBase):
|
||||
rr = utils.ResourceRequest(rs)
|
||||
self.assertResourceRequestsEqual(expected, rr)
|
||||
|
||||
def test_resource_request_init_with_mixed_cpus_isolate_emulator(self):
|
||||
"""Ensure the mixed instance properly requests the PCPU, VCPU,
|
||||
MEMORY_MB, DISK_GB resources, ensure an extra PCPU resource is
|
||||
requested due to a ISOLATE emulator thread policy.
|
||||
def test_resource_request_init_with_mixed_cpus_dedicated(self):
|
||||
"""Ensure the mixed instance, which is generated through
|
||||
'hw:cpu_dedicated_mask' extra spec, properly requests the PCPU, VCPU,
|
||||
MEMORY_MB and DISK_GB resources.
|
||||
"""
|
||||
extra_specs = {
|
||||
'hw:cpu_policy': 'mixed',
|
||||
'hw:cpu_dedicated_mask': '2,3'
|
||||
}
|
||||
self._test_resource_request_init_with_mixed_cpus(extra_specs)
|
||||
|
||||
def test_resource_request_init_with_mixed_cpus_realtime(self):
|
||||
"""Ensure the mixed instance, which is generated through real-time CPU
|
||||
interface, properly requests the PCPU, VCPU, MEMORY_BM and DISK_GB
|
||||
resources.
|
||||
"""
|
||||
extra_specs = {
|
||||
'hw:cpu_policy': 'mixed',
|
||||
"hw:cpu_realtime": "yes",
|
||||
"hw:cpu_realtime_mask": '2,3'
|
||||
}
|
||||
self._test_resource_request_init_with_mixed_cpus(extra_specs)
|
||||
|
||||
def _test_resource_request_init_with_mixed_cpus_iso_emu(self, extra_specs):
|
||||
flavor = objects.Flavor(
|
||||
vcpus=4, memory_mb=1024, root_gb=10, ephemeral_gb=5, swap=0,
|
||||
extra_specs={
|
||||
'hw:cpu_policy': 'mixed',
|
||||
'hw:cpu_dedicated_mask': '2,3',
|
||||
'hw:emulator_threads_policy': 'isolate',
|
||||
})
|
||||
|
||||
extra_specs=extra_specs)
|
||||
rs = objects.RequestSpec(flavor=flavor)
|
||||
expected = FakeResourceRequest()
|
||||
expected._rg_by_id[None] = objects.RequestGroup(
|
||||
@ -1136,6 +1143,33 @@ class TestUtils(TestUtilsBase):
|
||||
rr = utils.ResourceRequest(rs)
|
||||
self.assertResourceRequestsEqual(expected, rr)
|
||||
|
||||
def test_resource_request_init_with_mixed_cpus_iso_emu_realtime(self):
|
||||
"""Ensure the mixed instance, which is generated through the
|
||||
'hw:cpu_dedicated_mask' extra spec, specs, properly requests the PCPU,
|
||||
VCPU, MEMORY_MB, DISK_GB resources, ensure an extra PCPU resource is
|
||||
requested due to a ISOLATE emulator thread policy.
|
||||
"""
|
||||
extra_specs = {
|
||||
'hw:cpu_policy': 'mixed',
|
||||
'hw:cpu_dedicated_mask': '2,3',
|
||||
'hw:emulator_threads_policy': 'isolate',
|
||||
}
|
||||
self._test_resource_request_init_with_mixed_cpus_iso_emu(extra_specs)
|
||||
|
||||
def test_resource_request_init_with_mixed_cpus_iso_emu_dedicated(self):
|
||||
"""Ensure the mixed instance, which is generated through realtime extra
|
||||
specs, properly requests the PCPU, VCPU, MEMORY_MB, DISK_GB resources,
|
||||
ensure an extra PCPU resource is requested due to a ISOLATE emulator
|
||||
thread policy.
|
||||
"""
|
||||
extra_specs = {
|
||||
'hw:cpu_policy': 'mixed',
|
||||
"hw:cpu_realtime": "yes",
|
||||
"hw:cpu_realtime_mask": '2,3',
|
||||
'hw:emulator_threads_policy': 'isolate',
|
||||
}
|
||||
self._test_resource_request_init_with_mixed_cpus_iso_emu(extra_specs)
|
||||
|
||||
def test_resource_request_init_is_bfv(self):
|
||||
flavor = objects.Flavor(
|
||||
vcpus=1, memory_mb=1024, root_gb=10, ephemeral_gb=5, swap=1555)
|
||||
|
@ -1729,6 +1729,37 @@ class NUMATopologyTest(test.NoDBTestCase):
|
||||
]
|
||||
),
|
||||
},
|
||||
{
|
||||
"flavor": objects.Flavor(vcpus=6, memory_mb=2048,
|
||||
extra_specs={
|
||||
"hw:cpu_policy": fields.CPUAllocationPolicy.MIXED,
|
||||
"hw:cpu_realtime": "yes",
|
||||
"hw:cpu_realtime_mask": "^0-2",
|
||||
}),
|
||||
"image": {
|
||||
"properties": {},
|
||||
},
|
||||
"expect": objects.InstanceNUMATopology(
|
||||
cells=[
|
||||
objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([0, 1, 2]),
|
||||
pcpuset=set([3, 4, 5]), memory=2048,
|
||||
cpu_policy=fields.CPUAllocationPolicy.MIXED)]),
|
||||
},
|
||||
{ # Create 'mixed' instance with the 'ISOLATE' emulator
|
||||
# thread policy
|
||||
"flavor": objects.Flavor(vcpus=4, memory_mb=2048,
|
||||
extra_specs={
|
||||
"hw:cpu_policy": "mixed",
|
||||
"hw:cpu_dedicated_mask": "3",
|
||||
"hw:cpu_realtime": "yes",
|
||||
"hw:cpu_realtime_mask": "^0-2"
|
||||
}),
|
||||
"image": {
|
||||
"properties": {}
|
||||
},
|
||||
"expect": exception.RequiredMixedOrRealtimeCPUMask,
|
||||
},
|
||||
{
|
||||
# Invalid CPU thread pinning override
|
||||
"flavor": objects.Flavor(
|
||||
|
@ -1894,7 +1894,7 @@ def numa_get_constraints(flavor, image_meta):
|
||||
|
||||
cpu_policy = get_cpu_policy_constraint(flavor, image_meta)
|
||||
cpu_thread_policy = get_cpu_thread_policy_constraint(flavor, image_meta)
|
||||
rt_mask = get_realtime_cpu_constraint(flavor, image_meta)
|
||||
realtime_cpus = get_realtime_cpu_constraint(flavor, image_meta)
|
||||
dedicated_cpus = get_dedicated_cpu_constraint(flavor)
|
||||
emu_threads_policy = get_emulator_thread_policy_constraint(flavor)
|
||||
|
||||
@ -1966,7 +1966,7 @@ def numa_get_constraints(flavor, image_meta):
|
||||
if dedicated_cpus:
|
||||
raise exception.RequiredMixedInstancePolicy()
|
||||
|
||||
if rt_mask:
|
||||
if realtime_cpus:
|
||||
raise exception.RealtimeConfigurationInvalid()
|
||||
elif cpu_policy == fields.CPUAllocationPolicy.DEDICATED:
|
||||
# 'hw:cpu_dedicated_mask' should not be defined in a flavor with
|
||||
@ -1974,9 +1974,16 @@ def numa_get_constraints(flavor, image_meta):
|
||||
if dedicated_cpus:
|
||||
raise exception.RequiredMixedInstancePolicy()
|
||||
else: # MIXED
|
||||
if dedicated_cpus is None:
|
||||
if realtime_cpus and dedicated_cpus:
|
||||
raise exception.RequiredMixedOrRealtimeCPUMask()
|
||||
|
||||
if not (realtime_cpus or dedicated_cpus):
|
||||
raise exception.RequiredMixedOrRealtimeCPUMask()
|
||||
|
||||
# NOTE(huaquiang): If using mixed with realtime, then cores listed in
|
||||
# the realtime mask are dedicated and everything else is shared.
|
||||
dedicated_cpus = dedicated_cpus or realtime_cpus
|
||||
|
||||
nodes = _get_numa_node_count_constraint(flavor, image_meta)
|
||||
pagesize = _get_numa_pagesize_constraint(flavor, image_meta)
|
||||
vpmems = get_vpmems(flavor)
|
||||
|
Loading…
x
Reference in New Issue
Block a user