package org.ovirt.engine.core.bll.validator;
import java.util.Collections;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.ovirt.engine.core.bll.CpuFlagsManagerHandler;
import org.ovirt.engine.core.bll.ValidationResult;
import org.ovirt.engine.core.bll.utils.VersionSupport;
import org.ovirt.engine.core.common.FeatureSupported;
import org.ovirt.engine.core.common.businessentities.ArchitectureType;
import org.ovirt.engine.core.common.businessentities.Cluster;
import org.ovirt.engine.core.common.businessentities.StoragePool;
import org.ovirt.engine.core.common.businessentities.VmRngDevice;
import org.ovirt.engine.core.common.config.Config;
import org.ovirt.engine.core.common.config.ConfigValues;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.dal.dbbroker.DbFacade;
import org.ovirt.engine.core.dao.ClusterDao;
import org.ovirt.engine.core.dao.StoragePoolDao;
public class ClusterValidator {
public static final Set<VmRngDevice.Source> ALLOWED_ADDITIONAL_RNG_SOURCES =
Collections.singleton(VmRngDevice.Source.HWRNG);
private final Cluster cluster;
private final ClusterDao clusterDao;
private final StoragePoolDao dataCenterDao;
private StoragePool dataCenter;
private final CpuFlagsManagerHandler cpuFlagsManagerHandler;
public ClusterValidator(DbFacade dbFacade, Cluster cluster, CpuFlagsManagerHandler cpuFlagsManagerHandler) {
this.cluster = cluster;
this.clusterDao = dbFacade.getClusterDao();
this.dataCenterDao = dbFacade.getStoragePoolDao();
this.cpuFlagsManagerHandler = cpuFlagsManagerHandler;
}
public ValidationResult nameNotUsed() {
return ValidationResult.failWith(EngineMessage.CLUSTER_CANNOT_DO_ACTION_NAME_IN_USE)
.unless(clusterDao.getByName(cluster.getName(), false).isEmpty());
}
/**
* CPU check is required only if the cluster supports Virt service
*/
public ValidationResult cpuTypeSupportsVirtService() {
return ValidationResult.failWith(EngineMessage.ACTION_TYPE_FAILED_CPU_NOT_FOUND)
.when(cluster.supportsVirtService() && !cpuExists());
}
protected boolean cpuExists() {
return cpuFlagsManagerHandler.checkIfCpusExist(cluster.getCpuName(), cluster.getCompatibilityVersion());
}
public ValidationResult versionSupported() {
return ValidationResult.failWith(VersionSupport.getUnsupportedVersionMessage())
.unless(VersionSupport.checkVersionSupported(cluster.getCompatibilityVersion()));
}
public ValidationResult dataCenterVersionMismatch() {
StoragePool dataCenter = getDataCenter();
return ValidationResult
.failWith(EngineMessage.CLUSTER_CANNOT_ADD_COMPATIBILITY_VERSION_WITH_LOWER_STORAGE_POOL)
.when(dataCenter != null && cluster.supportsVirtService() &&
dataCenter.getCompatibilityVersion().compareTo(cluster.getCompatibilityVersion()) > 0);
}
public ValidationResult dataCenterExists() {
return ValidationResult.failWith(EngineMessage.ACTION_TYPE_FAILED_STORAGE_POOL_NOT_EXIST)
.when(cluster.getStoragePoolId() != null && getDataCenter() == null);
}
public ValidationResult localStoragePoolAttachedToSingleCluster() {
StoragePool dataCenter = getDataCenter();
return ValidationResult.failWith(EngineMessage.CLUSTER_CANNOT_ADD_MORE_THEN_ONE_HOST_TO_LOCAL_STORAGE)
.when(dataCenter != null && dataCenter.isLocal()
&& !clusterDao.getAllForStoragePool(cluster.getStoragePoolId()).isEmpty());
}
public ValidationResult clusterServiceDefined() {
return ValidationResult.failWith(EngineMessage.CLUSTER_AT_LEAST_ONE_SERVICE_MUST_BE_ENABLED)
.unless(cluster.supportsGlusterService() || cluster.supportsVirtService());
}
public ValidationResult mixedClusterServicesSupported() {
boolean mixedClusterEnabled = Config.<Boolean> getValue(ConfigValues.AllowClusterWithVirtGlusterEnabled);
return ValidationResult.failWith(EngineMessage.CLUSTER_ENABLING_BOTH_VIRT_AND_GLUSTER_SERVICES_NOT_ALLOWED)
.when(cluster.supportsGlusterService() && cluster.supportsVirtService() && !mixedClusterEnabled);
}
public ValidationResult attestationServerConfigured() {
return ValidationResult.failWith(EngineMessage.CLUSTER_CANNOT_SET_TRUSTED_ATTESTATION_SERVER_NOT_CONFIGURED)
.when(cluster.supportsTrustedService() && !attestationServerEnabled());
}
public ValidationResult migrationSupported(ArchitectureType arch) {
return ValidationResult.failWith(EngineMessage.MIGRATION_ON_ERROR_IS_NOT_SUPPORTED)
.unless(migrationSupportedForArch(arch));
}
public ValidationResult rngSourcesAllowed() {
return ValidationResult.failWith(EngineMessage.ACTION_TYPE_FAILED_RANDOM_RNG_SOURCE_CANT_BE_ADDED_TO_CLUSTER_ADDITIONAL_RNG_SOURCES)
.unless(ALLOWED_ADDITIONAL_RNG_SOURCES.containsAll(cluster.getAdditionalRngSources()));
}
public ValidationResult memoryOptimizationConfiguration() {
//if maxVdsMemoryOverCommit is set to a value <=0, it is later translated to maxVdsMemoryOverCommit = 100
//so we need to allow it here
return ValidationResult.failWith(EngineMessage.CLUSTER_TO_ALLOW_MEMORY_OPTIMIZATION_YOU_MUST_ALLOW_KSM_OR_BALLOONING)
.when(cluster.getMaxVdsMemoryOverCommit() > 100
&& !(cluster.isEnableKsm() || cluster.isEnableBallooning()));
}
protected boolean migrationSupportedForArch(ArchitectureType arch) {
return FeatureSupported.isMigrationSupported(arch, cluster.getCompatibilityVersion());
}
private boolean attestationServerEnabled() {
String attestationServer = Config.getValue(ConfigValues.AttestationServer);
return StringUtils.isNotEmpty(attestationServer);
}
private StoragePool getDataCenter() {
if (dataCenter == null && cluster.getStoragePoolId() != null) {
dataCenter = dataCenterDao.get(cluster.getStoragePoolId());
}
return dataCenter;
}
}