Merge "hardware: Differentiate between shared and dedicated CPUs"

This commit is contained in:
Zuul 2019-09-19 20:15:33 +00:00 committed by Gerrit Code Review
commit 9b2e00e015
8 changed files with 562 additions and 356 deletions

View File

@ -75,17 +75,19 @@ class NUMACell(base.NovaObject):
return not (self == other)
@property
def free_cpus(self):
return self.cpuset - self.pinned_cpus or set()
def free_pcpus(self):
"""Return available dedicated CPUs."""
return self.pcpuset - self.pinned_cpus or set()
@property
def free_siblings(self):
return [sibling_set & self.free_cpus
for sibling_set in self.siblings]
"""Return available dedicated CPUs in their sibling set form."""
return [sibling_set & self.free_pcpus for sibling_set in self.siblings]
@property
def avail_cpus(self):
return len(self.free_cpus)
def avail_pcpus(self):
"""Return number of available dedicated CPUs."""
return len(self.free_pcpus)
@property
def avail_memory(self):
@ -97,23 +99,27 @@ class NUMACell(base.NovaObject):
return any(len(sibling_set) > 1 for sibling_set in self.siblings)
def pin_cpus(self, cpus):
if cpus - self.cpuset:
if cpus - self.pcpuset:
raise exception.CPUPinningUnknown(requested=list(cpus),
available=list(self.cpuset))
available=list(self.pcpuset))
if self.pinned_cpus & cpus:
available = list(self.pcpuset - self.pinned_cpus)
raise exception.CPUPinningInvalid(requested=list(cpus),
available=list(self.cpuset -
self.pinned_cpus))
available=available)
self.pinned_cpus |= cpus
def unpin_cpus(self, cpus):
if cpus - self.cpuset:
if cpus - self.pcpuset:
raise exception.CPUUnpinningUnknown(requested=list(cpus),
available=list(self.cpuset))
available=list(self.pcpuset))
if (self.pinned_cpus & cpus) != cpus:
raise exception.CPUUnpinningInvalid(requested=list(cpus),
available=list(
self.pinned_cpus))
self.pinned_cpus -= cpus
def pin_cpus_with_siblings(self, cpus):

View File

@ -5701,8 +5701,8 @@ class ComputeTestCase(BaseTestCase,
# are used
cell1 = objects.NUMACell(
id=0,
cpuset=set([1, 2]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([1, 2]),
memory=512,
pagesize=2048,
cpu_usage=2,
@ -5715,8 +5715,8 @@ class ComputeTestCase(BaseTestCase,
# are free (on current host)
cell2 = objects.NUMACell(
id=1,
cpuset=set([3, 4]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([3, 4]),
pinned_cpus=set(),
memory=512,
pagesize=2048,
@ -5765,7 +5765,6 @@ class ComputeTestCase(BaseTestCase,
# after confirming resize all cpus on currect host must be free
self.assertEqual(2, len(updated_topology.cells))
for cell in updated_topology.cells:
self.assertEqual(0, cell.cpu_usage)
self.assertEqual(set(), cell.pinned_cpus)
def _test_resize_with_pci(self, method, expected_pci_addr):

View File

@ -45,8 +45,8 @@ class _TestNUMACell(object):
def test_free_cpus(self):
cell_a = objects.NUMACell(
id=0,
cpuset=set([1, 2]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([1, 2]),
memory=512,
cpu_usage=2,
memory_usage=256,
@ -55,8 +55,8 @@ class _TestNUMACell(object):
mempages=[])
cell_b = objects.NUMACell(
id=1,
cpuset=set([3, 4]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([3, 4]),
memory=512,
cpu_usage=1,
memory_usage=128,
@ -64,14 +64,14 @@ class _TestNUMACell(object):
siblings=[set([3]), set([4])],
mempages=[])
self.assertEqual(set([2]), cell_a.free_cpus)
self.assertEqual(set([3, 4]), cell_b.free_cpus)
self.assertEqual(set([2]), cell_a.free_pcpus)
self.assertEqual(set([3, 4]), cell_b.free_pcpus)
def test_pinning_logic(self):
numacell = objects.NUMACell(
id=0,
cpuset=set([1, 2, 3, 4]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([1, 2, 3, 4]),
memory=512,
cpu_usage=2,
memory_usage=256,
@ -79,7 +79,7 @@ class _TestNUMACell(object):
siblings=[set([1]), set([2]), set([3]), set([4])],
mempages=[])
numacell.pin_cpus(set([2, 3]))
self.assertEqual(set([4]), numacell.free_cpus)
self.assertEqual(set([4]), numacell.free_pcpus)
expect_msg = exception.CPUPinningUnknown.msg_fmt % {
'requested': r'\[1, 55\]', 'available': r'\[1, 2, 3, 4\]'}
@ -99,13 +99,13 @@ class _TestNUMACell(object):
self.assertRaises(exception.CPUUnpinningInvalid,
numacell.unpin_cpus, set([1, 4]))
numacell.unpin_cpus(set([1, 2, 3]))
self.assertEqual(set([1, 2, 3, 4]), numacell.free_cpus)
self.assertEqual(set([1, 2, 3, 4]), numacell.free_pcpus)
def test_pinning_with_siblings(self):
numacell = objects.NUMACell(
id=0,
cpuset=set([1, 2, 3, 4]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([1, 2, 3, 4]),
memory=512,
cpu_usage=2,
memory_usage=256,
@ -114,9 +114,9 @@ class _TestNUMACell(object):
mempages=[])
numacell.pin_cpus_with_siblings(set([1, 2]))
self.assertEqual(set(), numacell.free_cpus)
self.assertEqual(set(), numacell.free_pcpus)
numacell.unpin_cpus_with_siblings(set([1]))
self.assertEqual(set([1, 3]), numacell.free_cpus)
self.assertEqual(set([1, 3]), numacell.free_pcpus)
self.assertRaises(exception.CPUUnpinningInvalid,
numacell.unpin_cpus_with_siblings,
set([3]))
@ -126,15 +126,15 @@ class _TestNUMACell(object):
self.assertRaises(exception.CPUUnpinningInvalid,
numacell.unpin_cpus_with_siblings,
set([3, 4]))
self.assertEqual(set([1, 3]), numacell.free_cpus)
self.assertEqual(set([1, 3]), numacell.free_pcpus)
numacell.unpin_cpus_with_siblings(set([4]))
self.assertEqual(set([1, 2, 3, 4]), numacell.free_cpus)
self.assertEqual(set([1, 2, 3, 4]), numacell.free_pcpus)
def test_pinning_with_siblings_no_host_siblings(self):
numacell = objects.NUMACell(
id=0,
cpuset=set([1, 2, 3, 4]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([1, 2, 3, 4]),
memory=512,
cpu_usage=0,
memory_usage=256,

View File

@ -28,8 +28,8 @@ from nova.scheduler import host_manager
NUMA_TOPOLOGY = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([1, 2]),
pcpuset=set(),
cpuset=set([0, 1]),
pcpuset=set([2, 3]),
memory=512,
cpu_usage=0,
memory_usage=0,
@ -37,11 +37,11 @@ NUMA_TOPOLOGY = objects.NUMATopology(cells=[
mempages=[
objects.NUMAPagesTopology(size_kb=16, total=387184, used=0),
objects.NUMAPagesTopology(size_kb=2048, total=512, used=0)],
siblings=[set([0]), set([1])]),
siblings=[set([0]), set([1]), set([2]), set([3])]),
objects.NUMACell(
id=1,
cpuset=set([3, 4]),
pcpuset=set(),
cpuset=set([4, 5]),
pcpuset=set([6, 7]),
memory=512,
cpu_usage=0,
memory_usage=0,
@ -49,14 +49,14 @@ NUMA_TOPOLOGY = objects.NUMATopology(cells=[
mempages=[
objects.NUMAPagesTopology(size_kb=4, total=1548736, used=0),
objects.NUMAPagesTopology(size_kb=2048, total=512, used=0)],
siblings=[set([2]), set([3])])])
siblings=[set([4]), set([5]), set([6]), set([7])])])
NUMA_TOPOLOGIES_W_HT = [
objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([1, 2, 5, 6]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([1, 2, 5, 6]),
memory=512,
cpu_usage=0,
memory_usage=0,
@ -65,8 +65,8 @@ NUMA_TOPOLOGIES_W_HT = [
siblings=[set([1, 5]), set([2, 6])]),
objects.NUMACell(
id=1,
cpuset=set([3, 4, 7, 8]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([3, 4, 7, 8]),
memory=512,
cpu_usage=0,
memory_usage=0,
@ -87,8 +87,8 @@ NUMA_TOPOLOGIES_W_HT = [
siblings=[]),
objects.NUMACell(
id=1,
cpuset=set([1, 2, 5, 6]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([1, 2, 5, 6]),
memory=512,
cpu_usage=0,
memory_usage=0,
@ -97,8 +97,8 @@ NUMA_TOPOLOGIES_W_HT = [
siblings=[set([1, 5]), set([2, 6])]),
objects.NUMACell(
id=2,
cpuset=set([3, 4, 7, 8]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([3, 4, 7, 8]),
memory=512,
cpu_usage=0,
memory_usage=0,

View File

@ -2757,6 +2757,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
@mock.patch.object(
host.Host, "is_cpu_control_policy_capable", return_value=True)
def test_get_guest_config_numa_host_instance_fits(self, is_able):
self.flags(cpu_shared_set=None, cpu_dedicated_set=None,
group='compute')
instance_ref = objects.Instance(**self.test_instance)
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
flavor = objects.Flavor(memory_mb=1, vcpus=2, root_gb=496,
@ -2779,7 +2781,10 @@ class LibvirtConnTestCase(test.NoDBTestCase,
mock.patch.object(host.Host, 'has_min_version',
return_value=True),
mock.patch.object(host.Host, "get_capabilities",
return_value=caps)):
return_value=caps),
mock.patch.object(host.Host, 'get_online_cpus',
return_value=set([0, 1])),
):
cfg = drvr._get_guest_config(instance_ref, [],
image_meta, disk_info)
self.assertIsNone(cfg.cpuset)
@ -2812,18 +2817,14 @@ class LibvirtConnTestCase(test.NoDBTestCase,
with test.nested(
mock.patch.object(host.Host, "get_capabilities",
return_value=caps),
mock.patch.object(
hardware, 'get_vcpu_pin_set', return_value=set([3])),
mock.patch.object(random, 'choice'),
mock.patch.object(drvr, '_has_numa_support',
return_value=False)
) as (get_host_cap_mock,
get_vcpu_pin_set_mock, choice_mock,
_has_numa_support_mock):
) as (_, choice_mock, _):
cfg = drvr._get_guest_config(instance_ref, [],
image_meta, disk_info)
self.assertFalse(choice_mock.called)
self.assertEqual(set([3]), cfg.cpuset)
self.assertIsNone(cfg.cpuset)
self.assertEqual(0, len(cfg.cputune.vcpupin))
self.assertIsNone(cfg.cpu.numa)
@ -3197,6 +3198,9 @@ class LibvirtConnTestCase(test.NoDBTestCase,
host.Host, "is_cpu_control_policy_capable", return_value=True)
def test_get_guest_config_numa_host_instance_pci_no_numa_info(
self, is_able):
self.flags(cpu_shared_set='3', cpu_dedicated_set=None,
group='compute')
instance_ref = objects.Instance(**self.test_instance)
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
flavor = objects.Flavor(memory_mb=1, vcpus=2, root_gb=496,
@ -3228,12 +3232,10 @@ class LibvirtConnTestCase(test.NoDBTestCase,
with test.nested(
mock.patch.object(host.Host, 'has_min_version',
return_value=True),
mock.patch.object(
host.Host, "get_capabilities", return_value=caps),
mock.patch.object(
hardware, 'get_vcpu_pin_set', return_value=set([3])),
mock.patch.object(host.Host, "get_capabilities",
return_value=caps),
mock.patch.object(host.Host, 'get_online_cpus',
return_value=set(range(8))),
return_value=set([3])),
mock.patch.object(pci_manager, "get_instance_pci_devs",
return_value=[pci_device])):
cfg = conn._get_guest_config(instance_ref, [],
@ -3247,6 +3249,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
@mock.patch.object(
host.Host, "is_cpu_control_policy_capable", return_value=True)
def test_get_guest_config_numa_host_instance_2pci_no_fit(self, is_able):
self.flags(cpu_shared_set='3', cpu_dedicated_set=None,
group='compute')
instance_ref = objects.Instance(**self.test_instance)
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
flavor = objects.Flavor(memory_mb=4096, vcpus=4, root_gb=496,
@ -3279,16 +3283,14 @@ class LibvirtConnTestCase(test.NoDBTestCase,
with test.nested(
mock.patch.object(
host.Host, "get_capabilities", return_value=caps),
mock.patch.object(
hardware, 'get_vcpu_pin_set', return_value=set([3])),
mock.patch.object(host.Host, 'get_online_cpus',
return_value=set([3])),
mock.patch.object(random, 'choice'),
mock.patch.object(pci_manager, "get_instance_pci_devs",
return_value=[pci_device, pci_device2]),
mock.patch.object(conn, '_has_numa_support',
return_value=False)
) as (get_host_cap_mock,
get_vcpu_pin_set_mock, choice_mock, pci_mock,
_has_numa_support_mock):
) as (_, _, choice_mock, pci_mock, _):
cfg = conn._get_guest_config(instance_ref, [],
image_meta, disk_info)
self.assertFalse(choice_mock.called)
@ -3368,6 +3370,9 @@ class LibvirtConnTestCase(test.NoDBTestCase,
host.Host, "is_cpu_control_policy_capable", return_value=True)
def test_get_guest_config_numa_host_instance_fit_w_cpu_pinset(
self, is_able):
self.flags(cpu_shared_set='2-3', cpu_dedicated_set=None,
group='compute')
instance_ref = objects.Instance(**self.test_instance)
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
flavor = objects.Flavor(memory_mb=1024, vcpus=2, root_gb=496,
@ -3389,14 +3394,11 @@ class LibvirtConnTestCase(test.NoDBTestCase,
with test.nested(
mock.patch.object(host.Host, 'has_min_version',
return_value=True),
mock.patch.object(host.Host, "get_capabilities",
mock.patch.object(host.Host, 'get_capabilities',
return_value=caps),
mock.patch.object(
hardware, 'get_vcpu_pin_set', return_value=set([2, 3])),
mock.patch.object(host.Host, 'get_online_cpus',
return_value=set(range(8)))
) as (has_min_version_mock, get_host_cap_mock,
get_vcpu_pin_set_mock, get_online_cpus_mock):
return_value=set([2, 3])),
):
cfg = drvr._get_guest_config(instance_ref, [],
image_meta, disk_info)
# NOTE(ndipanov): we make sure that pin_set was taken into account
@ -3456,6 +3458,9 @@ class LibvirtConnTestCase(test.NoDBTestCase,
@mock.patch.object(
host.Host, "is_cpu_control_policy_capable", return_value=True)
def test_get_guest_config_numa_host_instance_topo(self, is_able):
self.flags(cpu_shared_set='0-5', cpu_dedicated_set=None,
group='compute')
instance_topology = objects.InstanceNUMATopology(
cells=[objects.InstanceNUMACell(
id=1, cpuset=set([0, 1]), memory=1024, pagesize=None),
@ -3489,9 +3494,6 @@ class LibvirtConnTestCase(test.NoDBTestCase,
return_value=True),
mock.patch.object(host.Host, "get_capabilities",
return_value=caps),
mock.patch.object(
hardware, 'get_vcpu_pin_set',
return_value=set([2, 3, 4, 5])),
mock.patch.object(host.Host, 'get_online_cpus',
return_value=set(range(8))),
):
@ -3686,6 +3688,9 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual("strict", memnode.mode)
def test_get_guest_config_numa_host_mempages_shared(self):
self.flags(cpu_shared_set='2-5', cpu_dedicated_set=None,
group='compute')
instance_topology = objects.InstanceNUMATopology(
cells=[
objects.InstanceNUMACell(
@ -3724,11 +3729,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
return_value=True),
mock.patch.object(host.Host, "get_capabilities",
return_value=caps),
mock.patch.object(
hardware, 'get_vcpu_pin_set',
return_value=set([2, 3, 4, 5])),
mock.patch.object(host.Host, 'get_online_cpus',
return_value=set(range(8))),
return_value=set([2, 3, 4, 5])),
):
cfg = drvr._get_guest_config(instance_ref, [],
image_meta, disk_info)
@ -3759,13 +3761,20 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(set([2, 3, 4, 5]), cfg.cputune.emulatorpin.cpuset)
def test_get_guest_config_numa_host_instance_cpu_pinning_realtime(self):
self.flags(cpu_shared_set=None, cpu_dedicated_set='4-7',
group='compute')
instance_topology = objects.InstanceNUMATopology(
cells=[
objects.InstanceNUMACell(
id=2, cpuset=set([0, 1]),
cpu_policy=fields.CPUAllocationPolicy.DEDICATED,
cpu_pinning={0: 4, 1: 5},
memory=1024, pagesize=2048),
objects.InstanceNUMACell(
id=3, cpuset=set([2, 3]),
cpu_policy=fields.CPUAllocationPolicy.DEDICATED,
cpu_pinning={2: 6, 3: 7},
memory=1024, pagesize=2048)])
instance_ref = objects.Instance(**self.test_instance)
instance_ref.numa_topology = instance_topology
@ -3773,6 +3782,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
flavor = objects.Flavor(memory_mb=2048, vcpus=4, root_gb=496,
ephemeral_gb=8128, swap=33550336, name='fake',
extra_specs={
"hw:numa_nodes": "2",
"hw:cpu_realtime": "yes",
"hw:cpu_policy": "dedicated",
"hw:cpu_realtime_mask": "^0-1"
@ -3801,9 +3811,6 @@ class LibvirtConnTestCase(test.NoDBTestCase,
return_value=True),
mock.patch.object(host.Host, "get_capabilities",
return_value=caps),
mock.patch.object(
hardware, 'get_vcpu_pin_set',
return_value=set([4, 5, 6, 7])),
mock.patch.object(host.Host, 'get_online_cpus',
return_value=set(range(8))),
):
@ -3835,12 +3842,10 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(1, len(cfg.cputune.vcpusched))
self.assertEqual("fifo", cfg.cputune.vcpusched[0].scheduler)
# Ensure vCPUs 0-1 are pinned on host CPUs 4-5 and 2-3 are
# set on host CPUs 6-7 according the realtime mask ^0-1
self.assertEqual(set([4, 5]), cfg.cputune.vcpupin[0].cpuset)
self.assertEqual(set([4, 5]), cfg.cputune.vcpupin[1].cpuset)
self.assertEqual(set([6, 7]), cfg.cputune.vcpupin[2].cpuset)
self.assertEqual(set([6, 7]), cfg.cputune.vcpupin[3].cpuset)
self.assertEqual(set([4]), cfg.cputune.vcpupin[0].cpuset)
self.assertEqual(set([5]), cfg.cputune.vcpupin[1].cpuset)
self.assertEqual(set([6]), cfg.cputune.vcpupin[2].cpuset)
self.assertEqual(set([7]), cfg.cputune.vcpupin[3].cpuset)
# We ensure that emulator threads are pinned on host CPUs
# 4-5 which are "normal" vCPUs
@ -3851,6 +3856,9 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(set([2, 3]), cfg.cputune.vcpusched[0].vcpus)
def test_get_guest_config_numa_host_instance_isolated_emulthreads(self):
self.flags(cpu_shared_set=None, cpu_dedicated_set='4-8',
group='compute')
instance_topology = objects.InstanceNUMATopology(
emulator_threads_policy=(
fields.CPUEmulatorThreadsPolicy.ISOLATE),
@ -3889,9 +3897,6 @@ class LibvirtConnTestCase(test.NoDBTestCase,
return_value=True),
mock.patch.object(host.Host, "get_capabilities",
return_value=caps),
mock.patch.object(
hardware, 'get_vcpu_pin_set',
return_value=set([4, 5, 6, 7, 8])),
mock.patch.object(host.Host, 'get_online_cpus',
return_value=set(range(10))),
):
@ -3906,7 +3911,9 @@ class LibvirtConnTestCase(test.NoDBTestCase,
def test_get_guest_config_numa_host_instance_shared_emulthreads_err(
self):
self.flags(cpu_shared_set="48-50", group="compute")
self.flags(cpu_shared_set='48-50', cpu_dedicated_set='4-8',
group='compute')
instance_topology = objects.InstanceNUMATopology(
emulator_threads_policy=(
fields.CPUEmulatorThreadsPolicy.SHARE),
@ -3945,9 +3952,6 @@ class LibvirtConnTestCase(test.NoDBTestCase,
return_value=True),
mock.patch.object(host.Host, "get_capabilities",
return_value=caps),
mock.patch.object(
hardware, 'get_vcpu_pin_set',
return_value=set([4, 5, 6, 7, 8])),
mock.patch.object(host.Host, 'get_online_cpus',
return_value=set(range(10))),
):
@ -3957,7 +3961,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
def test_get_guest_config_numa_host_instance_shared_emulator_threads(
self):
self.flags(cpu_shared_set="48-50", group="compute")
self.flags(cpu_shared_set='0,1', cpu_dedicated_set='2-7',
group='compute')
instance_topology = objects.InstanceNUMATopology(
emulator_threads_policy=(
fields.CPUEmulatorThreadsPolicy.SHARE),
@ -3966,13 +3971,13 @@ class LibvirtConnTestCase(test.NoDBTestCase,
id=0, cpuset=set([0, 1]),
memory=1024, pagesize=2048,
cpu_policy=fields.CPUAllocationPolicy.DEDICATED,
cpu_pinning={0: 4, 1: 5},
cpu_pinning={0: 2, 1: 3},
cpuset_reserved=set([6])),
objects.InstanceNUMACell(
id=1, cpuset=set([2, 3]),
memory=1024, pagesize=2048,
cpu_policy=fields.CPUAllocationPolicy.DEDICATED,
cpu_pinning={2: 7, 3: 8})])
cpu_pinning={2: 4, 3: 5})])
instance_ref = objects.Instance(**self.test_instance)
instance_ref.numa_topology = instance_topology
@ -3996,23 +4001,18 @@ class LibvirtConnTestCase(test.NoDBTestCase,
return_value=True),
mock.patch.object(host.Host, "get_capabilities",
return_value=caps),
mock.patch.object(
hardware, 'get_vcpu_pin_set',
return_value=set([4, 5, 6, 7, 8])),
mock.patch.object(host.Host, 'get_online_cpus',
return_value=set(list(range(10)) +
[48, 50])),
return_value=set(range(8))),
):
cfg = drvr._get_guest_config(instance_ref, [],
image_meta, disk_info)
# cpu_shared_set is configured with [48, 49, 50] but only
# [48, 50] are online.
self.assertEqual(set([48, 50]), cfg.cputune.emulatorpin.cpuset)
self.assertEqual(set([4]), cfg.cputune.vcpupin[0].cpuset)
self.assertEqual(set([5]), cfg.cputune.vcpupin[1].cpuset)
self.assertEqual(set([7]), cfg.cputune.vcpupin[2].cpuset)
self.assertEqual(set([8]), cfg.cputune.vcpupin[3].cpuset)
# emulator threads should be mapped to cores from 'cpu_shared_set'
self.assertEqual(set([0, 1]), cfg.cputune.emulatorpin.cpuset)
self.assertEqual(set([2]), cfg.cputune.vcpupin[0].cpuset)
self.assertEqual(set([3]), cfg.cputune.vcpupin[1].cpuset)
self.assertEqual(set([4]), cfg.cputune.vcpupin[2].cpuset)
self.assertEqual(set([5]), cfg.cputune.vcpupin[3].cpuset)
def test_get_cpu_numa_config_from_instance(self):
topology = objects.InstanceNUMATopology(cells=[
@ -4073,7 +4073,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
with test.nested(
mock.patch.object(drvr, "_get_host_numa_topology",
return_value=host_topology),
mock.patch.object(hardware, 'get_vcpu_pin_set',
mock.patch.object(hardware, "get_cpu_shared_set",
return_value=[1, 2, 3, 4, 5, 6])):
guest_numa_config = drvr._get_guest_numa_config(
instance_topology, flavor={}, image_meta={})
@ -7207,11 +7207,15 @@ class LibvirtConnTestCase(test.NoDBTestCase,
'EPYC',
'EPYC-IBPB']
def fake_getCPUMap():
return (2, [True, True], 2)
# Make sure the host arch is mocked as x86_64
self.create_fake_libvirt_mock(getCapabilities=fake_getCapabilities,
baselineCPU=fake_baselineCPU,
getCPUModelNames=fake_getCPUModelNames,
getVersion=lambda: 1005001)
getVersion=lambda: 1005001,
getCPUMap=fake_getCPUMap)
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance_ref = objects.Instance(**self.test_instance)
@ -13805,6 +13809,9 @@ class LibvirtConnTestCase(test.NoDBTestCase,
'EPYC',
'EPYC-IBPB']
def fake_getCPUMap():
return (2, [True, True], 2)
# _fake_network_info must be called before create_fake_libvirt_mock(),
# as _fake_network_info calls importutils.import_class() and
# create_fake_libvirt_mock() mocks importutils.import_class().
@ -13813,7 +13820,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
getCapabilities=fake_getCapabilities,
getCPUModelNames=fake_getCPUModelNames,
getVersion=lambda: 1005001,
baselineCPU=fake_baselineCPU)
baselineCPU=fake_baselineCPU,
getCPUMap=fake_getCPUMap)
instance = objects.Instance(**self.test_instance)
instance.image_ref = uuids.image_ref
@ -16604,9 +16612,62 @@ class LibvirtConnTestCase(test.NoDBTestCase,
mock.call('0000:04:11.7', False)
])
# TODO(stephenfin): This only has one caller. Flatten it and remove the
# 'mempages=False' branches or add the missing test
def _test_get_host_numa_topology(self, mempages):
@mock.patch.object(host.Host, 'has_min_version',
new=mock.Mock(return_value=True))
def _test_get_host_numa_topology(self):
nodes = 4
sockets = 1
cores = 1
threads = 2
total_cores = nodes * sockets * cores * threads
caps = vconfig.LibvirtConfigCaps()
caps.host = vconfig.LibvirtConfigCapsHost()
caps.host.cpu = vconfig.LibvirtConfigCPU()
caps.host.cpu.arch = fields.Architecture.X86_64
caps.host.topology = fakelibvirt.NUMATopology(
cpu_nodes=nodes, cpu_sockets=sockets, cpu_cores=cores,
cpu_threads=threads)
for i, cell in enumerate(caps.host.topology.cells):
cell.mempages = fakelibvirt.create_mempages(
[(4, 1024 * i), (2048, i)])
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
with test.nested(
mock.patch.object(host.Host, 'get_capabilities',
return_value=caps),
mock.patch.object(host.Host, 'get_online_cpus',
return_value=set(range(total_cores))),
):
got_topo = drvr._get_host_numa_topology()
# there should be varying amounts of mempages for each cell
self.assertEqual(4, got_topo.cells[0].mempages[0].size_kb)
self.assertEqual(0, got_topo.cells[0].mempages[0].total)
self.assertEqual(2048, got_topo.cells[0].mempages[1].size_kb)
self.assertEqual(0, got_topo.cells[0].mempages[1].total)
self.assertEqual(4, got_topo.cells[1].mempages[0].size_kb)
self.assertEqual(1024, got_topo.cells[1].mempages[0].total)
self.assertEqual(2048, got_topo.cells[1].mempages[1].size_kb)
self.assertEqual(1, got_topo.cells[1].mempages[1].total)
# none of the topologies should have pinned CPUs yet
self.assertEqual(set([]), got_topo.cells[0].pinned_cpus)
self.assertEqual(set([]), got_topo.cells[1].pinned_cpus)
self.assertEqual(set([]), got_topo.cells[2].pinned_cpus)
self.assertEqual(set([]), got_topo.cells[3].pinned_cpus)
# return to caller for further checks
return got_topo
def test_get_host_numa_topology(self):
"""Check that the host NUMA topology is generated correctly for a
fairly complex configuration.
"""
self.flags(cpu_shared_set='0-1', cpu_dedicated_set='2-6',
group='compute')
self.flags(vcpu_pin_set=None)
self.flags(physnets=['foo', 'bar', 'baz'], group='neutron')
# we need to call the below again to ensure the updated 'physnets'
# value is read and the new groups created
@ -16616,68 +16677,122 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.flags(numa_nodes=[3], group='neutron_physnet_bar')
self.flags(numa_nodes=[1, 2, 3], group='neutron_physnet_baz')
caps = vconfig.LibvirtConfigCaps()
caps.host = vconfig.LibvirtConfigCapsHost()
caps.host.cpu = vconfig.LibvirtConfigCPU()
caps.host.cpu.arch = fields.Architecture.X86_64
caps.host.topology = fakelibvirt.NUMATopology()
if mempages:
for i, cell in enumerate(caps.host.topology.cells):
cell.mempages = fakelibvirt.create_mempages(
[(4, 1024 * i), (2048, i)])
got_topo = self._test_get_host_numa_topology()
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
# only cores 0 and 1 are configured as shared using the
# 'cpu_shared_set' config option
self.assertEqual(set([0, 1]), got_topo.cells[0].cpuset)
self.assertEqual(set(), got_topo.cells[0].pcpuset)
self.assertEqual(set(), got_topo.cells[1].cpuset)
self.assertEqual(set([2, 3]), got_topo.cells[1].pcpuset)
self.assertEqual(set(), got_topo.cells[2].cpuset)
self.assertEqual(set([4, 5]), got_topo.cells[2].pcpuset)
self.assertEqual(set(), got_topo.cells[3].cpuset)
self.assertEqual(set([6]), got_topo.cells[3].pcpuset)
with test.nested(
mock.patch.object(host.Host, "get_capabilities",
return_value=caps),
mock.patch.object(
hardware, 'get_vcpu_pin_set',
return_value=set([0, 1, 3, 4, 5])),
mock.patch.object(host.Host, 'get_online_cpus',
return_value=set([0, 1, 2, 3, 6])),
):
got_topo = drvr._get_host_numa_topology()
# all cells except the last one should have siblings
self.assertEqual([set([0, 1])], got_topo.cells[0].siblings)
self.assertEqual([set([2, 3])], got_topo.cells[1].siblings)
self.assertEqual([set([4, 5])], got_topo.cells[2].siblings)
self.assertEqual([set([6])], got_topo.cells[3].siblings)
if mempages:
# cells 0
self.assertEqual(4, got_topo.cells[0].mempages[0].size_kb)
self.assertEqual(0, got_topo.cells[0].mempages[0].total)
self.assertEqual(2048, got_topo.cells[0].mempages[1].size_kb)
self.assertEqual(0, got_topo.cells[0].mempages[1].total)
# cells 1
self.assertEqual(4, got_topo.cells[1].mempages[0].size_kb)
self.assertEqual(1024, got_topo.cells[1].mempages[0].total)
self.assertEqual(2048, got_topo.cells[1].mempages[1].size_kb)
self.assertEqual(1, got_topo.cells[1].mempages[1].total)
else:
self.assertEqual([], got_topo.cells[0].mempages)
self.assertEqual([], got_topo.cells[1].mempages)
self.assertEqual(set(),
got_topo.cells[0].network_metadata.physnets)
self.assertEqual(set(['foo', 'baz']),
got_topo.cells[1].network_metadata.physnets)
self.assertEqual(set(['baz']),
got_topo.cells[2].network_metadata.physnets)
self.assertEqual(set(['bar', 'baz']),
got_topo.cells[3].network_metadata.physnets)
self.assertEqual(set([]), got_topo.cells[0].pinned_cpus)
self.assertEqual(set([]), got_topo.cells[1].pinned_cpus)
self.assertEqual(set([]), got_topo.cells[2].pinned_cpus)
self.assertEqual(set([]), got_topo.cells[3].pinned_cpus)
self.assertEqual([set([0, 1])], got_topo.cells[0].siblings)
self.assertEqual([set([3])], got_topo.cells[1].siblings)
self.assertTrue(got_topo.cells[0].network_metadata.tunneled)
self.assertFalse(got_topo.cells[1].network_metadata.tunneled)
self.assertTrue(got_topo.cells[2].network_metadata.tunneled)
self.assertFalse(got_topo.cells[3].network_metadata.tunneled)
self.assertEqual(set(),
got_topo.cells[0].network_metadata.physnets)
self.assertEqual(set(['foo', 'baz']),
got_topo.cells[1].network_metadata.physnets)
self.assertEqual(set(['baz']),
got_topo.cells[2].network_metadata.physnets)
self.assertEqual(set(['bar', 'baz']),
got_topo.cells[3].network_metadata.physnets)
def test_get_host_numa_topology__vcpu_pin_set_fallback(self):
"""Check that the host NUMA topology will fall back to using
'vcpu_pin_set' if 'cpu_dedicated_set' is not defined.
"""
self.flags(cpu_shared_set='0-1', cpu_dedicated_set=None,
group='compute')
self.flags(vcpu_pin_set='2-6')
self.assertTrue(got_topo.cells[0].network_metadata.tunneled)
self.assertFalse(got_topo.cells[1].network_metadata.tunneled)
self.assertTrue(got_topo.cells[2].network_metadata.tunneled)
self.assertFalse(got_topo.cells[3].network_metadata.tunneled)
got_topo = self._test_get_host_numa_topology()
@mock.patch.object(host.Host, 'has_min_version', return_value=True)
def test_get_host_numa_topology(self, mock_version):
self._test_get_host_numa_topology(mempages=True)
# cores 0 and 1 are configured as shared using the 'cpu_shared_set'
# config option but because 'vcpu_pin_set' is configured this
# configuration is ignored. All the cores listed in 'vcpu_pin_set' are
# dual reported for upgrade reasons
self.assertEqual(set(), got_topo.cells[0].cpuset)
self.assertEqual(set(), got_topo.cells[0].pcpuset)
self.assertEqual(set([2, 3]), got_topo.cells[1].cpuset)
self.assertEqual(set([2, 3]), got_topo.cells[1].pcpuset)
self.assertEqual(set([4, 5]), got_topo.cells[2].cpuset)
self.assertEqual(set([4, 5]), got_topo.cells[2].pcpuset)
self.assertEqual(set([6]), got_topo.cells[3].cpuset)
self.assertEqual(set([6]), got_topo.cells[3].pcpuset)
# all cells except the first and last one should have siblings
self.assertEqual([], got_topo.cells[0].siblings)
self.assertEqual([set([2, 3])], got_topo.cells[1].siblings)
self.assertEqual([set([4, 5])], got_topo.cells[2].siblings)
self.assertEqual([set([6])], got_topo.cells[3].siblings)
def test_get_host_numa_topology__no_cpu_configuration(self):
"""Check that the host NUMA topology will fall back to using
'vcpu_pin_set' if 'cpu_dedicated_set' is not defined.
"""
self.flags(cpu_shared_set=None, cpu_dedicated_set=None,
group='compute')
self.flags(vcpu_pin_set=None)
got_topo = self._test_get_host_numa_topology()
# there's no CPU configuration so every core is dual-reported for
# upgrade reasons
self.assertEqual(set([0, 1]), got_topo.cells[0].cpuset)
self.assertEqual(set([0, 1]), got_topo.cells[0].pcpuset)
self.assertEqual(set([2, 3]), got_topo.cells[1].cpuset)
self.assertEqual(set([2, 3]), got_topo.cells[1].pcpuset)
self.assertEqual(set([4, 5]), got_topo.cells[2].cpuset)
self.assertEqual(set([4, 5]), got_topo.cells[2].pcpuset)
self.assertEqual(set([6, 7]), got_topo.cells[3].cpuset)
self.assertEqual(set([6, 7]), got_topo.cells[3].pcpuset)
# all cells should have siblings
self.assertEqual([set([0, 1])], got_topo.cells[0].siblings)
self.assertEqual([set([2, 3])], got_topo.cells[1].siblings)
self.assertEqual([set([4, 5])], got_topo.cells[2].siblings)
self.assertEqual([set([6, 7])], got_topo.cells[3].siblings)
def test_get_host_numa_topology__only_shared_cpus(self):
"""Check that the host NUMA topology does not use 'cpu_shared_set' if
'cpu_dedicated_set' is not defined.
"""
self.flags(cpu_shared_set='0-6', cpu_dedicated_set=None,
group='compute')
self.flags(vcpu_pin_set=None)
got_topo = self._test_get_host_numa_topology()
# only cores 0 and 1 are configured as shared using the
# 'cpu_shared_set' config option, but the rest are dual reported
# for upgrade reasons
self.assertEqual(set([0, 1]), got_topo.cells[0].cpuset)
self.assertEqual(set(), got_topo.cells[0].pcpuset)
self.assertEqual(set([2, 3]), got_topo.cells[1].cpuset)
self.assertEqual(set([]), got_topo.cells[1].pcpuset)
self.assertEqual(set([4, 5]), got_topo.cells[2].cpuset)
self.assertEqual(set([]), got_topo.cells[2].pcpuset)
self.assertEqual(set([6]), got_topo.cells[3].cpuset)
self.assertEqual(set([]), got_topo.cells[3].pcpuset)
# all cells except the lasat one should have siblings
self.assertEqual([set([0, 1])], got_topo.cells[0].siblings)
self.assertEqual([set([2, 3])], got_topo.cells[1].siblings)
self.assertEqual([set([4, 5])], got_topo.cells[2].siblings)
self.assertEqual([set([6])], got_topo.cells[3].siblings)
def test_get_host_numa_topology_empty(self):
caps = vconfig.LibvirtConfigCaps()
@ -16713,6 +16828,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
@mock.patch.object(host.Host, 'has_min_version', return_value=True)
def test_get_host_numa_topology_missing_network_metadata(self,
mock_version):
self.flags(cpu_shared_set='0-5', cpu_dedicated_set=None,
group='compute')
self.flags(physnets=['bar'], group='neutron')
# we need to call the below again to ensure the updated 'physnets'
# value is read and the new groups created
@ -16731,10 +16848,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
with test.nested(
mock.patch.object(host.Host, "get_capabilities",
return_value=caps),
mock.patch.object(hardware, 'get_vcpu_pin_set',
return_value=set([0, 1, 3, 4, 5])),
mock.patch.object(host.Host, 'get_online_cpus',
return_value=set([0, 1, 2, 3, 6])),
return_value=set(range(6)))
):
self.assertRaisesRegex(
exception.InvalidNetworkNUMAAffinity,
@ -16746,6 +16861,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
@mock.patch.object(host.Host, 'has_min_version', return_value=True)
def _test_get_host_numa_topology_invalid_network_affinity(self,
group_name, mock_version):
self.flags(cpu_shared_set='0-5', cpu_dedicated_set=None,
group='compute')
self.flags(physnets=['foo', 'bar'], group='neutron')
# we need to call the below again to ensure the updated 'physnets'
# value is read and the new groups created
@ -16769,10 +16886,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
with test.nested(
mock.patch.object(host.Host, "get_capabilities",
return_value=caps),
mock.patch.object(hardware, 'get_vcpu_pin_set',
return_value=set([0, 1, 3, 4, 5])),
mock.patch.object(host.Host, 'get_online_cpus',
return_value=set([0, 1, 2, 3, 6])),
return_value=set(range(6)))
):
self.assertRaisesRegex(
exception.InvalidNetworkNUMAAffinity,

View File

@ -2400,8 +2400,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_inst_too_large_cpu(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2]),
memory=2048,
memory_usage=0,
pinned_cpus=set(),
@ -2417,8 +2417,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_inst_too_large_mem(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2]),
memory=2048,
memory_usage=1024,
pinned_cpus=set(),
@ -2433,8 +2433,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_inst_not_avail(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=2048,
memory_usage=0,
pinned_cpus=set([0]),
@ -2450,8 +2450,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_no_sibling_fits_empty(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2]),
memory=2048,
memory_usage=0,
pinned_cpus=set(),
@ -2470,8 +2470,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_no_sibling_fits_w_usage(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=2048,
memory_usage=0,
pinned_cpus=set([1]),
@ -2488,8 +2488,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_instance_siblings_fits(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=2048,
memory_usage=0,
pinned_cpus=set(),
@ -2509,8 +2509,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_instance_siblings_host_siblings_fits_empty(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=2048,
memory_usage=0,
siblings=[set([0, 1]), set([2, 3])],
@ -2530,8 +2530,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_instance_siblings_host_siblings_fits_empty_2(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
memory=4096,
memory_usage=0,
pinned_cpus=set(),
@ -2551,8 +2551,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_instance_siblings_host_siblings_fits_w_usage(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
memory=4096,
memory_usage=0,
pinned_cpus=set([1, 2, 5, 6]),
@ -2571,8 +2571,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_host_siblings_fit_single_core(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
memory=4096,
memory_usage=0,
pinned_cpus=set(),
@ -2591,8 +2591,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_host_siblings_fit(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=4096,
memory_usage=0,
pinned_cpus=set(),
@ -2610,8 +2610,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_require_policy_no_siblings(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set(range(0, 8)),
pcpuset=set(),
cpuset=set(),
pcpuset=set(range(0, 8)),
memory=4096,
memory_usage=0,
pinned_cpus=set(),
@ -2628,8 +2628,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_require_policy_too_few_siblings(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
memory=4096,
memory_usage=0,
pinned_cpus=set([0, 1, 2]),
@ -2646,8 +2646,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_require_policy_fits(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=4096,
memory_usage=0,
pinned_cpus=set(),
@ -2666,8 +2666,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_require_policy_fits_w_usage(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
memory=4096,
memory_usage=0,
pinned_cpus=set([0, 1]),
@ -2686,8 +2686,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_host_siblings_instance_odd_fit(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
memory=4096,
memory_usage=0,
pinned_cpus=set(),
@ -2703,8 +2703,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_host_siblings_instance_fit_optimize_threads(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
memory=4096,
memory_usage=0,
pinned_cpus=set(),
@ -2720,8 +2720,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_host_siblings_instance_odd_fit_w_usage(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
memory=4096,
memory_usage=0,
pinned_cpus=set([0, 2, 5]),
@ -2737,8 +2737,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_host_siblings_instance_mixed_siblings(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
memory=4096,
memory_usage=0,
pinned_cpus=set([0, 1, 2, 5]),
@ -2754,8 +2754,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_host_siblings_instance_odd_fit_orphan_only(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
memory=4096,
memory_usage=0,
pinned_cpus=set([0, 2, 5, 6]),
@ -2771,9 +2771,9 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_host_siblings_large_instance_odd_fit(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15]),
memory=4096,
memory_usage=0,
pinned_cpus=set(),
@ -2791,8 +2791,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_isolate_policy_too_few_fully_free_cores(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=4096,
memory_usage=0,
pinned_cpus=set([1]),
@ -2809,8 +2809,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_isolate_policy_no_fully_free_cores(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=4096,
memory_usage=0,
pinned_cpus=set([1, 2]),
@ -2827,8 +2827,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_isolate_policy_fits(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=4096,
memory_usage=0,
pinned_cpus=set(),
@ -2847,8 +2847,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_isolate_policy_fits_ht_host(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=4096,
memory_usage=0,
pinned_cpus=set(),
@ -2867,8 +2867,8 @@ class CPUPinningCellTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
def test_get_pinning_isolate_policy_fits_w_usage(self):
host_pin = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3, 4, 5, 6, 7]),
memory=4096,
memory_usage=0,
pinned_cpus=set([0, 1]),
@ -2890,8 +2890,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
host_topo = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([0, 1]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1]),
memory=2048,
memory_usage=0,
pinned_cpus=set(),
@ -2899,8 +2899,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
siblings=[set([0]), set([1])]),
objects.NUMACell(
id=1,
cpuset=set([2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([2, 3]),
memory=2048,
memory_usage=0,
pinned_cpus=set(),
@ -2917,12 +2917,47 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
for cell in inst_topo.cells:
self.assertInstanceCellPinned(cell, cell_ids=(0, 1))
def test_host_numa_fit_instance_to_host_single_cell_w_usage(self):
# TODO(stephenfin): Remove in U
def test_host_numa_fit_instance_to_host_legacy_object(self):
"""Check that we're able to fit an instance NUMA topology to a legacy
host NUMA topology that doesn't have the 'pcpuset' field present.
"""
host_topo = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([0, 1]),
pcpuset=set(),
# we are explicitly not setting pcpuset here
memory=2048,
memory_usage=0,
pinned_cpus=set(),
mempages=[],
siblings=[set([0]), set([1])]),
objects.NUMACell(
id=1,
cpuset=set([2, 3]),
# we are explicitly not setting pcpuset here
memory=2048,
memory_usage=0,
pinned_cpus=set(),
mempages=[],
siblings=[set([2]), set([3])])
])
inst_topo = objects.InstanceNUMATopology(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)
for cell in inst_topo.cells:
self.assertInstanceCellPinned(cell, cell_ids=(0, 1))
def test_host_numa_fit_instance_to_host_single_cell_w_usage(self):
host_topo = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set(),
pcpuset=set([0, 1]),
memory=2048,
memory_usage=0,
pinned_cpus=set([0]),
@ -2930,8 +2965,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
siblings=[set([0]), set([1])]),
objects.NUMACell(
id=1,
cpuset=set([2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([2, 3]),
memory=2048,
memory_usage=0,
pinned_cpus=set(),
@ -2952,8 +2987,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
host_topo = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([0, 1]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1]),
memory=2048,
memory_usage=0,
pinned_cpus=set([0]),
@ -2961,8 +2996,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
siblings=[set([0]), set([1])]),
objects.NUMACell(
id=1,
cpuset=set([2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([2, 3]),
memory=2048,
memory_usage=0,
pinned_cpus=set([2]),
@ -2981,8 +3016,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
host_topo = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=2048,
memory_usage=0,
pinned_cpus=set(),
@ -2990,8 +3025,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
siblings=[set([0]), set([1]), set([2]), set([3])]),
objects.NUMACell(
id=1,
cpuset=set([4, 5, 6, 7]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([4, 5, 6, 7]),
memory=2048,
memory_usage=0,
pinned_cpus=set(),
@ -3014,8 +3049,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
host_topo = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=2048,
memory_usage=0,
pinned_cpus=set([0]),
@ -3023,8 +3058,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
siblings=[set([0]), set([1]), set([2]), set([3])]),
objects.NUMACell(
id=1,
cpuset=set([4, 5, 6, 7]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([4, 5, 6, 7]),
memory=2048,
memory_usage=0,
pinned_cpus=set([4, 5, 6]),
@ -3032,8 +3067,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
siblings=[set([4]), set([5]), set([6]), set([7])]),
objects.NUMACell(
id=2,
cpuset=set([8, 9, 10, 11]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([8, 9, 10, 11]),
memory=2048,
memory_usage=0,
pinned_cpus=set([10, 11]),
@ -3057,8 +3092,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
host_topo = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=4096,
memory_usage=0,
pinned_cpus=set([0]),
@ -3066,8 +3101,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
siblings=[set([0]), set([1]), set([2]), set([3])]),
objects.NUMACell(
id=1,
cpuset=set([4, 5, 6, 7]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([4, 5, 6, 7]),
memory=4096,
memory_usage=0,
pinned_cpus=set([4, 5, 6]),
@ -3088,8 +3123,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
host_topo = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=4096,
memory_usage=0,
pinned_cpus=set(),
@ -3097,8 +3132,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
siblings=[set([0]), set([1]), set([2]), set([3])]),
objects.NUMACell(
id=1,
cpuset=set([4, 5, 6, 7]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([4, 5, 6, 7]),
memory=4096,
memory_usage=0,
pinned_cpus=set(),
@ -3122,8 +3157,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
host_pin = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=4096,
cpu_usage=0,
memory_usage=0,
@ -3151,8 +3186,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
host_pin = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=4096,
cpu_usage=0,
memory_usage=0,
@ -3179,8 +3214,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
host_pin = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=4096,
cpu_usage=0,
memory_usage=0,
@ -3207,8 +3242,8 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
host_pin = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=4096,
cpu_usage=0,
memory_usage=0,
@ -3225,16 +3260,16 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
)])
new_cell = hw.numa_usage_from_instance_numa(host_pin, inst_pin_1)
self.assertEqual(host_pin.cells[0].cpuset,
self.assertEqual(host_pin.cells[0].pcpuset,
new_cell.cells[0].pinned_cpus)
self.assertEqual(new_cell.cells[0].cpu_usage, 4)
self.assertEqual(0, new_cell.cells[0].cpu_usage)
def test_host_usage_from_instances_isolate_free(self):
host_pin = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=4096,
cpu_usage=0,
memory_usage=0,
@ -3253,14 +3288,14 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
new_cell = hw.numa_usage_from_instance_numa(host_pin, inst_pin_1,
free=True)
self.assertEqual(set([]), new_cell.cells[0].pinned_cpus)
self.assertEqual(new_cell.cells[0].cpu_usage, 0)
self.assertEqual(0, new_cell.cells[0].cpu_usage)
def test_host_usage_from_instances_isolated_without_siblings(self):
host_pin = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=4096,
cpu_usage=0,
memory_usage=0,
@ -3279,16 +3314,16 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
new_cell = hw.numa_usage_from_instance_numa(host_pin, inst_pin)
self.assertEqual(inst_pin.cells[0].cpuset,
new_cell.cells[0].pinned_cpus)
self.assertEqual(new_cell.cells[0].cpu_usage, 3)
self.assertEqual(0, new_cell.cells[0].cpu_usage)
def test_host_usage_from_instances_isolated_without_siblings_free(self):
host_pin = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3]),
memory=4096,
cpu_usage=4,
cpu_usage=0,
memory_usage=0,
pinned_cpus=set([0, 1, 2, 3]),
siblings=[set([0]), set([1]), set([2]), set([3])],
@ -3305,15 +3340,15 @@ class CPUPinningTestCase(test.NoDBTestCase, _CPUPinningTestCaseBase):
new_cell = hw.numa_usage_from_instance_numa(host_pin, inst_pin,
free=True)
self.assertEqual(set([3]), new_cell.cells[0].pinned_cpus)
self.assertEqual(new_cell.cells[0].cpu_usage, 1)
self.assertEqual(0, new_cell.cells[0].cpu_usage)
class CPUSReservedCellTestCase(test.NoDBTestCase):
def _test_reserved(self, reserved):
host_cell = objects.NUMACell(
id=0,
cpuset=set([0, 1, 2]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2]),
memory=2048,
memory_usage=0,
pinned_cpus=set(),
@ -3379,8 +3414,8 @@ class EmulatorThreadsTestCase(test.NoDBTestCase):
return objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([0, 1]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1]),
memory=2048,
cpu_usage=0,
memory_usage=0,
@ -3390,8 +3425,8 @@ class EmulatorThreadsTestCase(test.NoDBTestCase):
size_kb=4, total=524288, used=0)]),
objects.NUMACell(
id=1,
cpuset=set([2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([2, 3]),
memory=2048,
cpu_usage=0,
memory_usage=0,
@ -3527,9 +3562,7 @@ class EmulatorThreadsTestCase(test.NoDBTestCase):
host_topo = hw.numa_usage_from_instance_numa(host_topo, inst_topo)
self.assertEqual(2, host_topo.cells[0].cpu_usage)
self.assertEqual(set([0, 1]), host_topo.cells[0].pinned_cpus)
self.assertEqual(0, host_topo.cells[1].cpu_usage)
self.assertEqual(set([]), host_topo.cells[1].pinned_cpus)
def test_isolate_full_usage(self):
@ -3556,15 +3589,14 @@ class EmulatorThreadsTestCase(test.NoDBTestCase):
host_topo = hw.numa_usage_from_instance_numa(host_topo, inst_topo1)
host_topo = hw.numa_usage_from_instance_numa(host_topo, inst_topo2)
self.assertEqual(2, host_topo.cells[0].cpu_usage)
self.assertEqual(set([0, 1]), host_topo.cells[0].pinned_cpus)
def test_isolate_w_isolate_thread_alloc(self):
host_topo = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3, 4, 5]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3, 4, 5]),
memory=2048,
cpu_usage=0,
memory_usage=0,
@ -3590,8 +3622,8 @@ class EmulatorThreadsTestCase(test.NoDBTestCase):
host_topo = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([0, 1, 2, 3, 4, 5]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([0, 1, 2, 3, 4, 5]),
memory=2048,
cpu_usage=0,
memory_usage=0,
@ -3625,8 +3657,8 @@ class EmulatorThreadsTestCase(test.NoDBTestCase):
host_topo = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([1, 2, 3]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([1, 2, 3]),
memory=2048,
cpu_usage=0,
memory_usage=0,
@ -3650,8 +3682,8 @@ class EmulatorThreadsTestCase(test.NoDBTestCase):
host_topo = objects.NUMATopology(cells=[
objects.NUMACell(
id=0,
cpuset=set([1, 2, 3, 4, 5]),
pcpuset=set(),
cpuset=set(),
pcpuset=set([1, 2, 3, 4, 5]),
memory=2048,
cpu_usage=0,
memory_usage=0,

View File

@ -999,14 +999,14 @@ def _numa_fit_instance_cell_with_pinning(host_cell, instance_cell,
or None if instance cannot be pinned to the given host
"""
required_cpus = len(instance_cell.cpuset) + num_cpu_reserved
if host_cell.avail_cpus < required_cpus:
if host_cell.avail_pcpus < required_cpus:
LOG.debug('Not enough available CPUs to schedule instance. '
'Oversubscription is not possible with pinned instances. '
'Required: %(required)d (%(vcpus)d + %(num_cpu_reserved)d), '
'actual: %(actual)d',
{'required': required_cpus,
'vcpus': len(instance_cell.cpuset),
'actual': host_cell.avail_cpus,
'actual': host_cell.avail_pcpus,
'num_cpu_reserved': num_cpu_reserved})
return
@ -1102,14 +1102,40 @@ def _numa_fit_instance_cell(host_cell, instance_cell, limit_cell=None,
'actual': host_cell.memory})
return
if len(instance_cell.cpuset) + cpuset_reserved > len(host_cell.cpuset):
LOG.debug('Not enough host cell CPUs to fit instance cell. Required: '
'%(required)d + %(cpuset_reserved)d as overhead, '
'actual: %(actual)d',
{'required': len(instance_cell.cpuset),
'actual': len(host_cell.cpuset),
'cpuset_reserved': cpuset_reserved})
return
# The 'pcpuset' field is only set by newer compute nodes, so if it's
# not present then we've received this object from a pre-Train compute
# node and need to query against the 'cpuset' field instead until the
# compute node has been upgraded and starts reporting things properly.
# TODO(stephenfin): Remove in U
if 'pcpuset' not in host_cell:
host_cell.pcpuset = host_cell.cpuset
# NOTE(stephenfin): As with memory, do not allow an instance to overcommit
# against itself on any NUMA cell
if instance_cell.cpu_pinning_requested:
# TODO(stephenfin): Is 'cpuset_reserved' present if consuming emulator
# threads from shared CPU pools? If so, we don't want to add this here
required_cpus = len(instance_cell.cpuset) + cpuset_reserved
if required_cpus > len(host_cell.pcpuset):
LOG.debug('Not enough host cell CPUs to fit instance cell; '
'required: %(required)d + %(cpuset_reserved)d as '
'overhead, actual: %(actual)d', {
'required': len(instance_cell.cpuset),
'actual': len(host_cell.pcpuset),
'cpuset_reserved': cpuset_reserved
})
return
else:
required_cpus = len(instance_cell.cpuset) + cpuset_reserved
if required_cpus > len(host_cell.cpuset):
LOG.debug('Not enough host cell CPUs to fit instance cell; '
'required: %(required)d + %(cpuset_reserved)d as '
'overhead, actual: %(actual)d', {
'required': len(instance_cell.cpuset),
'actual': len(host_cell.cpuset),
'cpuset_reserved': cpuset_reserved
})
return
if instance_cell.cpu_pinning_requested:
LOG.debug('Pinning has been requested')
@ -2026,14 +2052,28 @@ def numa_usage_from_instance_numa(host_topology, instance_topology,
cells = []
sign = -1 if free else 1
for host_cell in host_topology.cells:
memory_usage = host_cell.memory_usage
cpu_usage = host_cell.cpu_usage
shared_cpus_usage = host_cell.cpu_usage
# The 'pcpuset' field is only set by newer compute nodes, so if it's
# not present then we've received this object from a pre-Train compute
# node and need to dual-report all CPUS listed therein as both
# dedicated and shared until the compute node has been upgraded and
# starts reporting things properly.
# TODO(stephenfin): Remove in U
if 'pcpuset' not in host_cell:
shared_cpus = host_cell.cpuset
dedicated_cpus = host_cell.cpuset
else:
shared_cpus = host_cell.cpuset
dedicated_cpus = host_cell.pcpuset
new_cell = objects.NUMACell(
id=host_cell.id,
cpuset=host_cell.cpuset,
pcpuset=set(), # TODO(stephenfin): Start setting this
cpuset=shared_cpus,
pcpuset=dedicated_cpus,
memory=host_cell.memory,
cpu_usage=0,
memory_usage=0,
@ -2048,46 +2088,36 @@ def numa_usage_from_instance_numa(host_topology, instance_topology,
if instance_cell.id != host_cell.id:
continue
memory_usage = memory_usage + sign * instance_cell.memory
cpu_usage_diff = len(instance_cell.cpuset)
if (instance_cell.cpu_thread_policy ==
fields.CPUThreadAllocationPolicy.ISOLATE and
host_cell.siblings):
cpu_usage_diff *= max(map(len, host_cell.siblings))
cpu_usage += sign * cpu_usage_diff
if cellid == 0 and instance_topology.emulator_threads_isolated:
# The emulator threads policy when defined with 'isolate' makes
# the instance to consume an additional pCPU as overhead. That
# pCPU is mapped on the host NUMA node related to the guest
# NUMA node 0.
cpu_usage += sign * len(instance_cell.cpuset_reserved)
# Compute mempages usage
new_cell.mempages = _numa_pagesize_usage_from_cell(
new_cell, instance_cell, sign)
if instance_topology.cpu_pinning_requested:
pinned_cpus = set(instance_cell.cpu_pinning.values())
memory_usage = memory_usage + sign * instance_cell.memory
if instance_cell.cpuset_reserved:
pinned_cpus |= instance_cell.cpuset_reserved
if not instance_cell.cpu_pinning_requested:
shared_cpus_usage += sign * len(instance_cell.cpuset)
continue
if free:
if (instance_cell.cpu_thread_policy ==
fields.CPUThreadAllocationPolicy.ISOLATE):
new_cell.unpin_cpus_with_siblings(pinned_cpus)
else:
new_cell.unpin_cpus(pinned_cpus)
pinned_cpus = set(instance_cell.cpu_pinning.values())
if instance_cell.cpuset_reserved:
pinned_cpus |= instance_cell.cpuset_reserved
if free:
if (instance_cell.cpu_thread_policy ==
fields.CPUThreadAllocationPolicy.ISOLATE):
new_cell.unpin_cpus_with_siblings(pinned_cpus)
else:
if (instance_cell.cpu_thread_policy ==
fields.CPUThreadAllocationPolicy.ISOLATE):
new_cell.pin_cpus_with_siblings(pinned_cpus)
else:
new_cell.pin_cpus(pinned_cpus)
new_cell.unpin_cpus(pinned_cpus)
else:
if (instance_cell.cpu_thread_policy ==
fields.CPUThreadAllocationPolicy.ISOLATE):
new_cell.pin_cpus_with_siblings(pinned_cpus)
else:
new_cell.pin_cpus(pinned_cpus)
new_cell.cpu_usage = max(0, cpu_usage)
# NOTE(stephenfin): We don't need to set 'pinned_cpus' here since that
# was done in the above '(un)pin_cpus(_with_siblings)' functions
new_cell.memory_usage = max(0, memory_usage)
new_cell.cpu_usage = max(0, shared_cpus_usage)
cells.append(new_cell)
return objects.NUMATopology(cells=cells)

View File

@ -4813,7 +4813,12 @@ class LibvirtDriver(driver.ComputeDriver):
# mess up though, raise an exception
raise exception.NUMATopologyUnsupported()
allowed_cpus = hardware.get_vcpu_pin_set()
# We only pin an instance to some host cores if the user has provided
# configuration to suggest we should.
shared_cpus = None
if CONF.vcpu_pin_set or CONF.compute.cpu_shared_set:
shared_cpus = self._get_vcpu_available()
topology = self._get_host_numa_topology()
# We have instance NUMA so translate it to the config class
@ -4827,12 +4832,12 @@ class LibvirtDriver(driver.ComputeDriver):
# TODO(ndipanov): Attempt to spread the instance
# across NUMA nodes and expose the topology to the
# instance as an optimisation
return GuestNumaConfig(allowed_cpus, None, None, None)
return GuestNumaConfig(shared_cpus, None, None, None)
if not topology:
# No NUMA topology defined for host - This will only happen with
# some libvirt versions and certain platforms.
return GuestNumaConfig(allowed_cpus, None,
return GuestNumaConfig(shared_cpus, None,
guest_cpu_numa_config, None)
# Now get configuration from the numa_topology
@ -6990,12 +6995,22 @@ class LibvirtDriver(driver.ComputeDriver):
return
cells = []
allowed_cpus = hardware.get_vcpu_pin_set()
online_cpus = self._host.get_online_cpus()
if allowed_cpus:
allowed_cpus &= online_cpus
else:
allowed_cpus = online_cpus
available_shared_cpus = self._get_vcpu_available()
available_dedicated_cpus = self._get_pcpu_available()
# NOTE(stephenfin): In an ideal world, if the operator had not
# configured this host to report PCPUs using the '[compute]
# cpu_dedicated_set' option, then we should not be able to used pinned
# instances on this host. However, that would force operators to update
# their configuration as part of the Stein -> Train upgrade or be
# unable to schedule instances on the host. As a result, we need to
# revert to legacy behavior and use 'vcpu_pin_set' for both VCPUs and
# PCPUs.
# TODO(stephenfin): Remove this in U
if not available_dedicated_cpus and not (
CONF.compute.cpu_shared_set and not CONF.vcpu_pin_set):
available_dedicated_cpus = available_shared_cpus
def _get_reserved_memory_for_cell(self, cell_id, page_size):
cell = self._reserved_hugepages.get(cell_id, {})
@ -7042,14 +7057,19 @@ class LibvirtDriver(driver.ComputeDriver):
tunnel_affinities = _get_tunnel_numa_affinity()
for cell in topology.cells:
cpuset = set(cpu.id for cpu in cell.cpus)
cpus = set(cpu.id for cpu in cell.cpus)
cpuset = cpus & available_shared_cpus
pcpuset = cpus & available_dedicated_cpus
siblings = sorted(map(set,
set(tuple(cpu.siblings)
if cpu.siblings else ()
for cpu in cell.cpus)
))
cpuset &= allowed_cpus
siblings = [sib & allowed_cpus for sib in siblings]
cpus &= available_shared_cpus | available_dedicated_cpus
siblings = [sib & cpus for sib in siblings]
# Filter out empty sibling sets that may be left
siblings = [sib for sib in siblings if len(sib) > 0]
@ -7066,15 +7086,19 @@ class LibvirtDriver(driver.ComputeDriver):
physnets=physnet_affinities[cell.id],
tunneled=tunnel_affinities[cell.id])
# NOTE(stephenfin): Note that we don't actually return any usage
# information here. This is because this is handled by the resource
# tracker via the 'update_available_resource' periodic task, which
# loops through all instances and calculated usage accordingly
cell = objects.NUMACell(
id=cell.id,
cpuset=cpuset,
pcpuset=set(), # TODO(stephenfin): Start setting this
pcpuset=pcpuset,
memory=cell.memory / units.Ki,
cpu_usage=0,
pinned_cpus=set(),
memory_usage=0,
siblings=siblings,
pinned_cpus=set([]),
mempages=mempages,
network_metadata=network_metadata)
cells.append(cell)