package org.ovirt.engine.core.bll;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.ovirt.engine.core.bll.context.CommandContext;
import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.action.VmSlaPolicyParameters;
import org.ovirt.engine.core.common.businessentities.qos.StorageQos;
import org.ovirt.engine.core.common.businessentities.storage.DiskImage;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.common.vdscommands.UpdateVmPolicyVDSParams;
import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
import org.ovirt.engine.core.common.vdscommands.VDSReturnValue;
import org.ovirt.engine.core.vdsbroker.vdsbroker.IoTuneUtils;
/**
* VmSlaPolicyCommand, This command will push SLA parameters such as CPU, RAM and IO
* tuning to the VM. This Command runs as a hot plug (when the VM is running).
*
* The execute will never throw an exception. it will rather wrap a return value in case
* of failure.
*/
@NonTransactiveCommandAttribute
public class VmSlaPolicyCommand<T extends VmSlaPolicyParameters> extends VmCommand<T> {
public static final String LOGABLE_FIELD_CPU_LIMIT = "cpuLimit";
public static final String LOGABLE_FIELD_DISK_LIST = "diskList";
public VmSlaPolicyCommand(T parameters, CommandContext commandContext) {
super(parameters, commandContext);
}
@Override
protected boolean validate() {
if (getVm() == null) {
return failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_NOT_FOUND);
}
if (!getVm().getStatus().isQualifiedForQosChange()) {
return failVmStatusIllegal();
}
if (getParameters().isEmpty()) {
return failValidation(EngineMessage.VM_SLA_POLICY_UNCHANGED);
}
return true;
}
/**
* Execution shall perform a call to VDSM to set the SLA parameters.
*/
@Override
protected void executeCommand() {
Integer cpuLimit = null;
if (getParameters().getCpuQos() != null) {
cpuLimit = getParameters().getCpuQos().getCpuLimit();
cpuLimit = (cpuLimit != null) ? cpuLimit : 100;
}
UpdateVmPolicyVDSParams params = new UpdateVmPolicyVDSParams(getVm().getRunOnVds(), getVmId(), cpuLimit);
for (Map.Entry<DiskImage, StorageQos> entry : getParameters().getStorageQos().entrySet()) {
DiskImage diskImage = entry.getKey();
Map<String, Long> ioTuneStruct = IoTuneUtils.ioTuneMapFrom(entry.getValue());
params.addIoTuneParams(diskImage, ioTuneStruct);
}
VDSReturnValue vdsReturnValue = runVdsCommand(VDSCommandType.UpdateVmPolicy, params);
setSucceeded(vdsReturnValue.getSucceeded());
}
@Override
public AuditLogType getAuditLogTypeValue() {
// It can't happen that this will stay 0, the validation prevents running the command without changed CPU or
// storage QoS.
int logId = 0;
if (getParameters().getCpuQos() != null) {
Integer limit = getParameters().getCpuQos().getCpuLimit();
addCustomValue(LOGABLE_FIELD_CPU_LIMIT, (limit != null) ? String.valueOf(limit): "unlimited");
logId += 1;
}
if (getParameters().getStorageQos() != null && !getParameters().getStorageQos().isEmpty()) {
Set<DiskImage> diskImages = getParameters().getStorageQos().keySet();
String diskNames = diskImages.stream().map(d -> d.getDiskAlias()).collect(Collectors.joining(", "));
addCustomValue(LOGABLE_FIELD_DISK_LIST, diskNames);
logId += 2;
}
final AuditLogType[] logTypes = {
AuditLogType.UNASSIGNED, // This can't happen
AuditLogType.VM_SLA_POLICY_CPU,
AuditLogType.VM_SLA_POLICY_STORAGE,
AuditLogType.VM_SLA_POLICY_CPU_STORAGE
};
return getSucceeded() ? logTypes[logId] : AuditLogType.FAILED_VM_SLA_POLICY;
}
@Override
protected void setActionMessageParameters() {
addValidationMessage(EngineMessage.VAR__ACTION__UPDATE_SLA_POLICY);
addValidationMessage(EngineMessage.VAR__TYPE__VM);
}
}