Mixed Dedicated and Shared cpu instances

Tests deploying an instance mapped to shared PCPUs and dedicated PCPUs
on the host [1]

New test method deploys an instance using a flavor with a mixed
dedicated policy. Currently deploys with a mask that excludes core id
0 of the guest instance from mapping its cores to dedicated PCPUs from
  the host.

[1] https://specs.openstack.org/openstack/nova-specs/specs/victoria/implemented/use-pcpu-vcpu-in-one-instance.html

Change-Id: Id9a32f1439ee8b646f35988675f352e789deaf12
This commit is contained in:
James Parker
2021-08-18 12:05:31 -04:00
parent d184526a29
commit 0276f52886
4 changed files with 71 additions and 2 deletions

View File

@@ -86,7 +86,7 @@
vars:
# NOTE(artom) We can't have this on the parent job, otherwise the two
# -cpupinnig jobs will inherit it as well.
tempest_exclude_regex: test_live_migrate_and_reboot
tempest_exclude_regex: test_live_migrate_and_reboot|test_shared_pinned_and_unpinned_guest
- job:
name: whitebox-devstack-multinode-cpupinning
@@ -95,7 +95,7 @@
Runs the CPU pinning tests on single-NUMA, non-SMT, nested virt VMs. Uses
[compute]cpu_dedicated_set to configure host CPUs for pinning.
vars:
tempest_test_regex: 'test_live_migrate_and_reboot'
tempest_test_regex: test_live_migrate_and_reboot|test_shared_pinned_and_unpinned_guest
devstack_local_conf:
post-config:
$NOVA_CONF:

View File

@@ -28,3 +28,14 @@ class NUMAHelperMixin(object):
for pin in vcpupins:
pinset |= hardware.parse_cpu_spec(pin.get('cpuset'))
return pinset
def get_host_pcpus_for_guest_vcpu(self, server_id, instance_cpu_id):
"""Search the xml vcpu element of the provided instance for its cpuset.
Convert cpuset found into a set of integers.
"""
xml_cpu_search = "./cputune/vcpupin[@vcpu='%s']" % instance_cpu_id
root = self.get_server_xml(server_id)
cpus = root.find(xml_cpu_search)
cpuset = cpus.attrib.get('cpuset')
return hardware.parse_cpu_spec(cpuset)

View File

@@ -1335,3 +1335,50 @@ class NUMARebuildTest(BasePinningTest):
db_topo_rebuilt = self._get_db_numa_topology(server['id'])
self.assertEqual(db_topo_orig, db_topo_rebuilt,
"NUMA topology doesn't match")
class MixedCPUPolicyTest(BasePinningTest, numa_helper.NUMAHelperMixin):
vcpus = 2
mixed_cpu_policy = {'hw:cpu_policy': 'mixed',
'hw:cpu_dedicated_mask': '^0'}
def test_shared_pinned_and_unpinned_guest(self):
flavor = self.create_flavor(vcpus=self.vcpus,
extra_specs=self.mixed_cpu_policy)
server = self.create_test_server(flavor=flavor['id'])
host = self.get_host_for_server(server['id'])
host_sm = clients.NovaServiceManager(host, 'nova-compute',
self.os_admin.services_client)
# Gather the current hosts cpu dedicated and shared set values
host_dedicated_cpus = host_sm.get_cpu_dedicated_set()
host_shared_cpus = host_sm.get_cpu_shared_set()
# Find the PCPU's currently mapped to core 0 of the guest
guest_shared_cpus = self.get_host_pcpus_for_guest_vcpu(server['id'], 0)
# Validate the PCPUs mapped to core 0 are a subset of the cpu shared
# set of the host
self.assertItemsEqual(guest_shared_cpus, host_shared_cpus,
'Shared CPU Set %s of shared server %s is '
'not equal to shared set of host %s' %
(guest_shared_cpus, server['id'],
host_shared_cpus))
# Find the PCPU pinned to core 1 of the guest
guest_dedicated_cpus = \
self.get_host_pcpus_for_guest_vcpu(server['id'], 1)
# Confirm only one PCPU is mapped to core 1 of the guest
self.assertEqual(1, len(guest_dedicated_cpus), 'Only one PCPU should '
'be pinned to the guest CPU ID 1, but instead '
'found %s' % guest_dedicated_cpus)
# Validate PCPU pinned to core 1 is a subset of the cpu dedicated set
# of the host
self.assertTrue(guest_dedicated_cpus.issubset(host_dedicated_cpus),
'PCPU %s pinned to CPU id 1 of instance %s located on '
'host %s is not a subset of the dedicated set %s' %
(guest_dedicated_cpus, server['id'], host,
host_dedicated_cpus))

View File

@@ -26,6 +26,7 @@ from tempest.lib import exceptions as tempest_libexc
from whitebox_tempest_plugin.common import waiters
from whitebox_tempest_plugin import exceptions
from whitebox_tempest_plugin import hardware
from whitebox_tempest_plugin import utils as whitebox_utils
CONF = config.CONF
@@ -233,6 +234,16 @@ class NovaServiceManager(ServiceManager):
'down')
return result
def get_cpu_shared_set(self):
shared_set = self.get_conf_opt('compute', 'cpu_shared_set')
return hardware.parse_cpu_spec(shared_set)
def get_cpu_dedicated_set(self):
dedicated_set = self.get_conf_opt('compute', 'cpu_dedicated_set')
dedicated_set = (dedicated_set if dedicated_set is not None else
self.get_conf_opt('DEFAULT', 'vcpu_pin_set'))
return hardware.parse_cpu_spec(dedicated_set)
class NUMAClient(SSHClient):
"""A client to get host NUMA information. `numactl` needs to be installed