Skip to content

Commit

Permalink
core: validate amount of sockets equal to that of numa nodes
Browse files Browse the repository at this point in the history
When running a VM with 'Resize and Pin' CPU pinning policy, the algorithm
expects the host to have the same number of sockets and NUMA nodes. That
way the algorithm fits the topology and leaves the first core on each
socket free to the host.

This patch filters out hosts that don't have an equal number of  sockets
and NUMA nodes in the NUMA filter policy when trying to run a VM with CPU
pinning policy `Resize and Pin`.

Change-Id: Icdc1ac910eb733f6edd861d0505fb90a581224b5
Bug-Url: https://bugzilla.redhat.com/1955388
Signed-off-by: Liran Rotenberg <lrotenbe@redhat.com>
  • Loading branch information
liranr23 committed Jan 3, 2022
1 parent b162672 commit 7f61d6e
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.ovirt.engine.core.common.scheduling.PerHostMessages;
import org.ovirt.engine.core.common.scheduling.PolicyUnit;
import org.ovirt.engine.core.common.scheduling.PolicyUnitType;
import org.ovirt.engine.core.common.utils.VmCpuCountHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -36,9 +37,8 @@ public NumaPolicyUnit(PolicyUnit policyUnit,

@Override
public List<VDS> filter(SchedulingContext context, List<VDS> hosts, List<VM> vmGroup, PerHostMessages messages) {
boolean vmNumaPinned = vmGroup.stream()
.flatMap(vm -> vm.getvNumaNodeList().stream())
.anyMatch(node -> !node.getVdsNumaNodeList().isEmpty());
boolean vmNumaPinned = vmGroup.stream().anyMatch(vm -> vm.getvNumaNodeList().stream()
.anyMatch(node -> !node.getVdsNumaNodeList().isEmpty()) || VmCpuCountHelper.isAutoPinning(vm));

// If no VM numa node is pinned, all hosts are accepted.
//
Expand All @@ -48,7 +48,7 @@ public List<VDS> filter(SchedulingContext context, List<VDS> hosts, List<VM> vmG
}

List<VM> vmsToCheck = vmGroup.stream()
.filter(vm -> !vm.getvNumaNodeList().isEmpty())
.filter(vm -> !vm.getvNumaNodeList().isEmpty() || VmCpuCountHelper.isAutoPinning(vm))
.collect(Collectors.toList());

if (vmsToCheck.isEmpty()) {
Expand All @@ -57,6 +57,14 @@ public List<VDS> filter(SchedulingContext context, List<VDS> hosts, List<VM> vmG

List<VDS> result = new ArrayList<>();
for (VDS host: hosts) {
if (vmsToCheck.stream().anyMatch(VmCpuCountHelper::isAutoPinning) &&
host.getCpuSockets() != host.getNumaNodeList().size()) {
log.debug("Host '{}' is not qualified for the 'Resize and Pin' CPU pinning policy," +
" number of sockets is not equal to number of NUMA nodes", host.getName());
messages.addMessage(host.getId(), EngineMessage.VAR__DETAIL__SOCKETS_UNEQUAL_NUMA.toString());
continue;
}

List<VM> vmsToCheckOnHost = new ArrayList<>(vmsToCheck.size());
boolean skipHostCheck = true;
for (VM vm : vmsToCheck) {
Expand All @@ -66,6 +74,14 @@ public List<VDS> filter(SchedulingContext context, List<VDS> hosts, List<VM> vmG
}
skipHostCheck = false;

if (VmCpuCountHelper.isAutoPinning(vm)) {
boolean vmIsSet = initiateAutoPinToHost(vm, host);
if (!vmIsSet) {
// The host will fail on CPU policy. No need to check this VM.
continue;
}
}

// If the NUMA mode is PREFERRED, a host with any NUMA configuration is accepted.
if (vm.getvNumaNodeList().stream().map(VmNumaNode::getNumaTuneMode)
.allMatch(tune -> tune != NumaTuneMode.PREFERRED)) {
Expand Down Expand Up @@ -104,4 +120,12 @@ public List<VDS> filter(SchedulingContext context, List<VDS> hosts, List<VM> vmG

return result;
}

private boolean initiateAutoPinToHost(VM vm, VDS host) {
if (host.getCpuCores() / host.getCpuSockets() <= 1) {
return false;
}
NumaPinningHelper.applyAutoPinningPolicy(vm, host.getDynamicData(), host.getNumaNodeList());
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1538,6 +1538,7 @@ public enum EngineMessage {
VAR__DETAIL__NOT_ENOUGH_HUGE_PAGES,
VAR__DETAIL__NUMA_NOT_SUPPORTED,
VAR__DETAIL__NOT_MEMORY_PINNED_NUMA,
VAR__DETAIL__SOCKETS_UNEQUAL_NUMA,
VAR__DETAIL__NOT_ENOUGH_CORES,
VAR__DETAIL__VM_PINNING_PCPU_DOES_NOT_EXIST,
VAR__DETAIL__NUMA_PINNING_FAILED,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2683,6 +2683,8 @@ public interface AppErrors extends ConstantsWithLookup {

String VAR__DETAIL__NOT_MEMORY_PINNED_NUMA();

String VAR__DETAIL__SOCKETS_UNEQUAL_NUMA();

String VAR__DETAIL__NOT_ENOUGH_CORES();

String VAR__DETAIL__VM_PINNING_PCPU_DOES_NOT_EXIST();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1279,6 +1279,7 @@ VAR__DETAIL__HE_HOST_NOT_POSITIVE_SCORE=$detailMessage it doesn't have a positiv
VAR__DETAIL__HE_HOST_LOW_SCORE=$detailMessage it has much lower Hosted Engine score than the current host.
VAR__DETAIL__NUMA_NOT_SUPPORTED=$detailMessage does not support NUMA
VAR__DETAIL__NOT_MEMORY_PINNED_NUMA=$detailMessage cannot accommodate memory of VM's pinned virtual NUMA nodes within host's physical NUMA nodes.
VAR__DETAIL__SOCKETS_UNEQUAL_NUMA=$detailMessage cannot apply the CPU pinning policy 'Resize and Pin' on a host with different amount of CPU sockets and NUMA nodes
VAR__DETAIL__NO_SUITABLE_VF=$detailMessage there are no free virtual functions which are suitable for virtual nic(s) ${vnicNames}. A virtual function is considered as suitable if the VF's configuration of its physical function contains the virtual nic's network/network label
VAR__DETAIL__NOT_PINNED_TO_HOST=$detailMessage the host is not present in the pinning list.
VAR__DETAIL__NUMA_PINNING_FAILED=$detailMessage it has insufficient NUMA node free memory to run the VM
Expand Down

0 comments on commit 7f61d6e

Please sign in to comment.