package org.ovirt.engine.core.bll.validator.storage;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.ovirt.engine.core.bll.Backend;
import org.ovirt.engine.core.bll.ValidationResult;
import org.ovirt.engine.core.common.businessentities.StorageDomain;
import org.ovirt.engine.core.common.businessentities.VM;
import org.ovirt.engine.core.common.businessentities.VMStatus;
import org.ovirt.engine.core.common.businessentities.VmDevice;
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.common.businessentities.storage.DiskVmElement;
import org.ovirt.engine.core.common.businessentities.storage.LunDisk;
import org.ovirt.engine.core.common.businessentities.storage.ScsiGenericIO;
import org.ovirt.engine.core.common.businessentities.storage.StorageType;
import org.ovirt.engine.core.common.businessentities.storage.VolumeType;
import org.ovirt.engine.core.common.constants.StorageConstants;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.common.interfaces.VDSBrokerFrontend;
import org.ovirt.engine.core.common.utils.Pair;
import org.ovirt.engine.core.dal.dbbroker.DbFacade;
import org.ovirt.engine.core.dao.StorageDomainDao;
import org.ovirt.engine.core.dao.VmDao;
import org.ovirt.engine.core.di.Injector;
import org.ovirt.engine.core.utils.ReplacementUtils;
/**
* A validator for the {@link Disk} class.
*
*/
public class DiskValidator {
private final Disk disk;
protected static final String DISK_NAME_VARIABLE = "DiskName";
protected static final String VM_LIST = "VmList";
protected static final String VM_NAME_VARIABLE = "VmName";
public DiskValidator(Disk disk) {
this.disk = disk;
}
public ValidationResult isDiskPluggedToVmsThatAreNotDown(boolean checkOnlyVmsSnapshotPluggedTo, List<Pair<VM, VmDevice>> vmsForDisk) {
if (vmsForDisk == null) {
vmsForDisk = getVmDao().getVmsWithPlugInfo(disk.getId());
}
for (Pair<VM, VmDevice> pair : vmsForDisk) {
VmDevice vmDevice = pair.getSecond();
if (checkOnlyVmsSnapshotPluggedTo && vmDevice.getSnapshotId() == null) {
continue;
}
VM currVm = pair.getFirst();
if (VMStatus.Down != currVm.getStatus()) {
if (vmDevice.isPlugged()) {
return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_VM_IS_NOT_DOWN);
}
}
}
return ValidationResult.VALID;
}
public ValidationResult isDiskUsedAsOvfStore() {
if (disk.isOvfStore()) {
return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_OVF_DISK_NOT_SUPPORTED);
}
return ValidationResult.VALID;
}
protected VmDao getVmDao() {
return DbFacade.getInstance().getVmDao();
}
public ValidationResult validateUnsupportedDiskStorageType(DiskStorageType... diskStorageTypes) {
List<DiskStorageType> diskStorageTypeList = Arrays.asList(diskStorageTypes);
if (diskStorageTypeList.contains(disk.getDiskStorageType())) {
return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_NOT_SUPPORTED_DISK_STORAGE_TYPE,
String.format("$diskStorageType %s", disk.getDiskStorageType()));
}
return ValidationResult.VALID;
}
protected VDSBrokerFrontend getVdsBroker() {
return Backend.getInstance().getResourceManager();
}
public ValidationResult validateNotHostedEngineDisk() {
return isHostedEngineDirectLunDisk() ? new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_HOSTED_ENGINE_DISK) :
ValidationResult.VALID;
}
private boolean isHostedEngineDirectLunDisk() {
return disk.getDiskStorageType() == DiskStorageType.LUN &&
StorageConstants.HOSTED_ENGINE_LUN_DISK_ALIAS.equals(disk.getDiskAlias());
}
public ValidationResult isUsingScsiReservationValid(VM vm, DiskVmElement dve, LunDisk lunDisk) {
if (vm != null) {
// scsi reservation can be enabled only when sgio is unfiltered
if (dve.isUsingScsiReservation() && lunDisk.getSgio() == ScsiGenericIO.FILTERED) {
return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_SGIO_IS_FILTERED);
}
}
return ValidationResult.VALID;
}
public ValidationResult validRemovableHostedEngineDisks(VM vm) {
return isHostedEngineDirectLunDisk() || !vm.isHostedEngine()
? ValidationResult.VALID
: new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_HOSTED_ENGINE_DISK);
}
public ValidationResult isDiskExists() {
if (disk == null) {
return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_DISK_NOT_EXIST);
}
return ValidationResult.VALID;
}
public ValidationResult isDiskAttachedToVm(VM vm) {
List<VM> vms = getVmDao().getVmsListForDisk(disk.getId(), true);
String[] replacements = {ReplacementUtils.createSetVariableString(DISK_NAME_VARIABLE, disk.getDiskAlias()),
ReplacementUtils.createSetVariableString(VM_NAME_VARIABLE, vm.getName())};
return ValidationResult.failWith(EngineMessage.ACTION_TYPE_FAILED_DISK_NOT_ATTACHED_TO_VM, replacements).
when(vms.stream().noneMatch(vm1 -> vm1.getId().equals(vm.getId())));
}
public ValidationResult isDiskAttachedToAnyVm() {
List<VM> vms = getVmDao().getVmsListForDisk(disk.getId(), true);
if (!vms.isEmpty()) {
return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_DISK_ATTACHED_TO_VMS,
ReplacementUtils.createSetVariableString(DISK_NAME_VARIABLE, disk.getDiskAlias()),
ReplacementUtils.createSetVariableString(VM_LIST,
vms.stream().map(VM::getName).collect(Collectors.joining(","))));
}
return ValidationResult.VALID;
}
public ValidationResult isVmNotContainsBootDisk(VM vm) {
Disk bootDisk = DbFacade.getInstance().getDiskDao().getVmBootActiveDisk(vm.getId());
if (bootDisk != null) {
return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_DISK_BOOT_IN_USE,
ReplacementUtils.createSetVariableString("VmName", vm.getName()),
ReplacementUtils.createSetVariableString("DiskName", bootDisk.getDiskAlias()));
}
return ValidationResult.VALID;
}
public ValidationResult isSparsifySupported() {
if (disk.getDiskStorageType() != DiskStorageType.IMAGE) {
return new ValidationResult(
EngineMessage.ACTION_TYPE_FAILED_DISK_SPARSIFY_NOT_SUPPORTED_BY_DISK_STORAGE_TYPE,
getDiskAliasVarReplacement(),
ReplacementUtils.createSetVariableString("diskStorageType", disk.getDiskStorageType()));
}
if (((DiskImage) disk).getImage().getVolumeType() == VolumeType.Preallocated) {
return new ValidationResult(
EngineMessage.ACTION_TYPE_FAILED_DISK_SPARSIFY_NOT_SUPPORTED_FOR_PREALLOCATED,
getDiskAliasVarReplacement());
}
StorageDomain diskStorageDomain =
Injector.get(StorageDomainDao.class).get(((DiskImage) disk).getStorageIds().get(0));
StorageType domainStorageType = diskStorageDomain.getStorageType();
if (!domainStorageType.isFileDomain() && !domainStorageType.isBlockDomain()) {
return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_DISK_SPARSIFY_NOT_SUPPORTED_BY_STORAGE_TYPE,
getDiskAliasVarReplacement(),
getStorageDomainNameVarReplacement(diskStorageDomain),
ReplacementUtils.createSetVariableString("storageType", domainStorageType));
}
if (domainStorageType.isBlockDomain() && disk.isWipeAfterDelete()
&& !diskStorageDomain.getSupportsDiscardZeroesData()) {
return new ValidationResult(
EngineMessage.ACTION_TYPE_FAILED_DISK_SPARSIFY_NOT_SUPPORTED_BY_UNDERLYING_STORAGE_WHEN_WAD_IS_ENABLED,
getStorageDomainNameVarReplacement(diskStorageDomain),
getDiskAliasVarReplacement());
}
return ValidationResult.VALID;
}
private String getDiskAliasVarReplacement() {
return ReplacementUtils.createSetVariableString("diskAlias", disk.getDiskAlias());
}
private String getStorageDomainNameVarReplacement(StorageDomain storageDomain) {
return ReplacementUtils.createSetVariableString("storageDomainName", storageDomain.getName());
}
}