numa: add numa constraints for emulator threads policy

This commit updates the part responsible to build the NUMA topology
constraints to take into account the emulator threads request.

implements blueprint libvirt-emulator-threads-policy

Change-Id: If2141e9c0b3558bec9122d8f273a7f39b6ded179
This commit is contained in:
Sahid Orentino Ferdjaoui
2016-10-11 08:40:12 -04:00
parent 5cf6bbf374
commit 338b3eaa08
3 changed files with 118 additions and 7 deletions

View File

@@ -1198,6 +1198,30 @@ def _numa_get_constraints_auto(nodes, flavor):
return objects.InstanceNUMATopology(cells=cells)
def get_emulator_threads_constraint(flavor, image_meta):
"""Determines the emulator threads policy"""
emu_threads_policy = flavor.get('extra_specs', {}).get(
'hw:emulator_threads_policy')
LOG.debug("emulator threads policy constraint: %s", emu_threads_policy)
if not emu_threads_policy:
return
if emu_threads_policy not in fields.CPUEmulatorThreadsPolicy.ALL:
raise exception.InvalidEmulatorThreadsPolicy(
requested=emu_threads_policy,
available=str(fields.CPUEmulatorThreadsPolicy.ALL))
if emu_threads_policy == fields.CPUEmulatorThreadsPolicy.ISOLATE:
# In order to make available emulator threads policy, a dedicated
# CPU policy is necessary.
cpu_policy = _get_cpu_policy_constraints(flavor, image_meta)
if cpu_policy != fields.CPUAllocationPolicy.DEDICATED:
raise exception.BadRequirementEmulatorThreadsPolicy()
return emu_threads_policy
def _validate_numa_nodes(nodes):
"""Validate NUMA nodes number
@@ -1300,6 +1324,7 @@ def numa_get_constraints(flavor, image_meta):
cpu_policy = _get_cpu_policy_constraints(flavor, image_meta)
cpu_thread_policy = _get_cpu_thread_policy_constraints(flavor, image_meta)
rt_mask = _get_realtime_mask(flavor, image_meta)
emu_thread_policy = get_emulator_threads_constraint(flavor, image_meta)
# sanity checks
@@ -1322,13 +1347,16 @@ def numa_get_constraints(flavor, image_meta):
cell.cpu_thread_policy = cpu_thread_policy
else:
single_cell = objects.InstanceNUMACell(
id=0,
cpuset=set(range(flavor.vcpus)),
memory=flavor.memory_mb,
cpu_policy=cpu_policy,
cpu_thread_policy=cpu_thread_policy)
id=0,
cpuset=set(range(flavor.vcpus)),
memory=flavor.memory_mb,
cpu_policy=cpu_policy,
cpu_thread_policy=cpu_thread_policy)
numa_topology = objects.InstanceNUMATopology(cells=[single_cell])
if emu_thread_policy:
numa_topology.emulator_threads_policy = emu_thread_policy
return numa_topology
@@ -1365,6 +1393,10 @@ def numa_fit_instance_to_host(
'actual': len(host_topology)})
return
emulator_threads_policy = None
if 'emulator_threads_policy' in instance_topology:
emulator_threads_policy = instance_topology.emulator_threads_policy
# TODO(ndipanov): We may want to sort permutations differently
# depending on whether we want packing/spreading over NUMA nodes
for host_cell_perm in itertools.permutations(
@@ -1389,7 +1421,9 @@ def numa_fit_instance_to_host(
if not pci_requests or ((pci_stats is not None) and
pci_stats.support_requests(pci_requests, cells)):
return objects.InstanceNUMATopology(cells=cells)
return objects.InstanceNUMATopology(
cells=cells,
emulator_threads_policy=emulator_threads_policy)
def numa_get_reserved_huge_pages():
@@ -1563,8 +1597,11 @@ def instance_topology_from_instance(instance):
cpu_thread_policy=cell.get('cpu_thread_policy'),
cpuset_reserved=cell.get('cpuset_reserved'))
for cell in dict_cells]
emulator_threads_policy = instance_numa_topology.get(
'emulator_threads_policy')
instance_numa_topology = objects.InstanceNUMATopology(
cells=cells)
cells=cells,
emulator_threads_policy=emulator_threads_policy)
return instance_numa_topology