package org.ovirt.engine.core.bll;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.ovirt.engine.core.bll.interfaces.BackendInternal;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.action.VmSlaPolicyParameters;
import org.ovirt.engine.core.common.businessentities.VM;
import org.ovirt.engine.core.common.businessentities.profiles.CpuProfile;
import org.ovirt.engine.core.common.businessentities.profiles.DiskProfile;
import org.ovirt.engine.core.common.businessentities.qos.CpuQos;
import org.ovirt.engine.core.common.businessentities.qos.StorageQos;
import org.ovirt.engine.core.common.businessentities.storage.Disk;
import org.ovirt.engine.core.common.businessentities.storage.DiskImage;
import org.ovirt.engine.core.common.businessentities.storage.DiskStorageType;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dao.DiskDao;
import org.ovirt.engine.core.dao.DiskImageDao;
import org.ovirt.engine.core.dao.VmDao;
import org.ovirt.engine.core.dao.profiles.CpuProfileDao;
import org.ovirt.engine.core.dao.profiles.DiskProfileDao;
import org.ovirt.engine.core.dao.qos.CpuQosDao;
import org.ovirt.engine.core.dao.qos.StorageQosDao;
import org.ovirt.engine.core.utils.threadpool.ThreadPoolUtil;
@Singleton
public class VmSlaPolicyUtils {
@Inject
private CpuProfileDao cpuProfileDao;
@Inject
private DiskProfileDao diskProfileDao;
@Inject
private DiskImageDao diskImageDao;
@Inject
private CpuQosDao cpuQosDao;
@Inject
private DiskDao diskDao;
@Inject
private VmDao vmDao;
@Inject
private StorageQosDao storageQosDao;
@Inject
private BackendInternal backend;
public List<Guid> getRunningVmsWithCpuProfiles(Collection<Guid> cpuProfileIds) {
return vmDao.getAllForCpuProfiles(cpuProfileIds).stream()
.filter(vm -> vm.getStatus().isQualifiedForQosChange())
.map(VM::getId)
.collect(Collectors.toList());
}
public List<Guid> getRunningVmsWithCpuQos(Guid cpuQosId) {
List<Guid> cpuProfileIds = cpuProfileDao.getAllForQos(cpuQosId).stream()
.map(CpuProfile::getId)
.collect(Collectors.toList());
if (cpuProfileIds.isEmpty()) {
return Collections.emptyList();
}
return getRunningVmsWithCpuProfiles(cpuProfileIds);
}
public Map<Guid, List<DiskImage>> getRunningVmDiskImageMapWithProfiles(Collection<Guid> diskProfileIds) {
Map<Guid, List<DiskImage>> vmDiskMap = new HashMap<>();
List<Guid> vmIds = vmDao.getAllForDiskProfiles(diskProfileIds).stream()
.filter(vm -> vm.getStatus().isQualifiedForQosChange())
.map(VM::getId)
.collect(Collectors.toList());
if (vmIds.isEmpty()) {
return Collections.emptyMap();
}
Map<Guid, List<Disk>> attachedDisks = diskDao.getAllForVms(vmIds);
for (Guid vmId : vmIds) {
List<DiskImage> updatedDisks = attachedDisks.get(vmId).stream()
.filter(disk -> (disk.getDiskStorageType() == DiskStorageType.IMAGE) && disk.getPlugged())
.map(DiskImage.class::cast)
.filter(disk -> disk.getActive() && diskProfileIds.contains(disk.getDiskProfileId()))
.collect(Collectors.toList());
vmDiskMap.put(vmId, updatedDisks);
}
return vmDiskMap;
}
public Map<Guid, List<DiskImage>> getRunningVmDiskImageMapWithQos(Guid storageQosId) {
Set<Guid> profileIds = diskProfileDao.getAllForQos(storageQosId).stream()
.map(DiskProfile::getId)
.collect(Collectors.toSet());
if (profileIds.isEmpty()) {
return Collections.emptyMap();
}
return getRunningVmDiskImageMapWithProfiles(profileIds);
}
public void refreshVmsCpuQos(List<Guid> vmIds, CpuQos newQos) {
for (Guid vmId : vmIds) {
ThreadPoolUtil.execute(() ->
backend.runInternalAction(VdcActionType.VmSlaPolicy,
new VmSlaPolicyParameters(vmId, newQos)));
}
}
public void refreshRunningVmsWithCpuQos(Guid cpuQosId, CpuQos newQos) {
refreshVmsCpuQos(getRunningVmsWithCpuQos(cpuQosId), newQos);
}
public void refreshRunningVmsWithCpuProfile(Guid profileId, CpuQos newQos) {
refreshVmsCpuQos(
getRunningVmsWithCpuProfiles(Collections.singleton(profileId)),
newQos);
}
/**
* Refresh CPU QoS of a running VM.
*/
public void refreshCpuQosOfRunningVm(VM vm) {
if (!vm.getStatus().isQualifiedForQosChange()) {
// It only makes sense to try a QoS live change on a running VM.
throw new IllegalArgumentException(
String.format("VM %s is not running. Can't perform a live QoS upgrade", vm.getId())
);
}
Guid vmId = vm.getId();
List<Guid> vmIds = Arrays.asList(vmId);
CpuQos cpuQos = cpuQosDao.getCpuQosByVmIds(vmIds).get(vmId);
if (cpuQos == null) {
refreshVmsCpuQos(Arrays.asList(vmId), new CpuQos());
} else {
refreshVmsCpuQos(Arrays.asList(vmId), cpuQos);
}
}
public void refreshVmsStorageQos(Map<Guid, List<DiskImage>> vmDiskMap, StorageQos newQos) {
// No QoS means default QoS which means unlimited
if (newQos == null) {
newQos = new StorageQos();
}
for (Map.Entry<Guid, List<DiskImage>> entry : vmDiskMap.entrySet()) {
VmSlaPolicyParameters cmdParams = new VmSlaPolicyParameters(entry.getKey());
for (DiskImage img : entry.getValue()) {
cmdParams.getStorageQos().put(img, newQos);
}
ThreadPoolUtil.execute(() -> backend.runInternalAction(VdcActionType.VmSlaPolicy, cmdParams));
}
}
public void refreshRunningVmsWithStorageQos(Guid storageQosId, StorageQos newQos) {
refreshVmsStorageQos(getRunningVmDiskImageMapWithQos(storageQosId), newQos);
}
public void refreshRunningVmsWithDiskProfile(Guid diskProfileId) {
refreshVmsStorageQos(
getRunningVmDiskImageMapWithProfiles(Collections.singleton(diskProfileId)),
storageQosDao.getQosByDiskProfileId(diskProfileId)
);
}
}