package org.ovirt.engine.core.bll;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import org.apache.commons.lang.StringUtils;
import org.ovirt.engine.core.bll.context.CommandContext;
import org.ovirt.engine.core.bll.job.ExecutionHandler;
import org.ovirt.engine.core.bll.utils.VersionSupport;
import org.ovirt.engine.core.common.action.SetNonOperationalVdsParameters;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.action.VdsActionParameters;
import org.ovirt.engine.core.common.businessentities.Cluster;
import org.ovirt.engine.core.common.businessentities.NonOperationalReason;
import org.ovirt.engine.core.common.businessentities.SupportedAdditionalClusterFeature;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.VDSStatus;
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.compat.RpmVersion;
import org.ovirt.engine.core.compat.Version;
import org.ovirt.engine.core.dao.ClusterFeatureDao;
import org.ovirt.engine.core.dao.SupportedHostFeatureDao;
@InternalCommandAttribute
@NonTransactiveCommandAttribute
public class HandleVdsVersionCommand<T extends VdsActionParameters> extends VdsCommand<T> {
@Inject
private ClusterFeatureDao clusterFeatureDao;
@Inject
private SupportedHostFeatureDao hostFeatureDao;
public HandleVdsVersionCommand(T parameters, CommandContext cmdContext) {
super(parameters, cmdContext);
}
@Override
protected boolean validate() {
if (getVds() == null) {
return failValidation(EngineMessage.VDS_INVALID_SERVER_ID);
}
if (getVds().getStatus() == VDSStatus.Connecting || getVds().getStatus() == VDSStatus.NonResponsive) {
return failValidation(EngineMessage.VDS_CANNOT_CHECK_VERSION_HOST_NON_RESPONSIVE);
}
return true;
}
@Override
protected void executeCommand() {
VDS vds = getVds();
Cluster cluster = getCluster();
boolean isEngineSupportedByVdsm = false;
// partialVdcVersion will hold the engine's version (minor and major parts),
// this will be compared to vdsm supported engines to see if vdsm can be added
// to cluster
Version partialVdcVersion = new Version(new Version(Config.getValue(ConfigValues.VdcVersion)).toString(2));
RpmVersion vdsVersion = vds.getVersion();
Version vdsmVersion = new Version(vdsVersion.getMajor(), vdsVersion.getMinor());
if (!StringUtils.isEmpty(vds.getSupportedEngines())) {
isEngineSupportedByVdsm = vds.getSupportedENGINESVersionsSet().contains(partialVdcVersion);
}
// If vdsm doesn't support the engine's version (engine's version is not included
// vdsm supprtedEngineVersions list) we move on and check if engine
// and cluster supports the specific vdsm version. which is sufficient
if (!isEngineSupportedByVdsm &&
!Config.<HashSet<Version>> getValue(ConfigValues.SupportedVDSMVersions).contains(vdsmVersion)) {
reportNonOperationReason(NonOperationalReason.VERSION_INCOMPATIBLE_WITH_CLUSTER,
Config.<HashSet<Version>> getValue(ConfigValues.SupportedVDSMVersions).toString(),
vdsmVersion.toString());
}
else if (!VersionSupport.checkClusterVersionSupported(cluster.getCompatibilityVersion(), vds)) {
reportNonOperationReason(NonOperationalReason.CLUSTER_VERSION_INCOMPATIBLE_WITH_CLUSTER,
cluster.getCompatibilityVersion().toString(),
vds.getSupportedClusterLevels());
} else {
checkClusterAdditionalFeaturesSupported(cluster, vds);
}
setSucceeded(true);
}
private void checkClusterAdditionalFeaturesSupported(Cluster cluster, VDS vds) {
Set<SupportedAdditionalClusterFeature> clusterSupportedFeatures =
clusterFeatureDao.getSupportedFeaturesByClusterId(cluster.getId());
Set<String> hostSupportedFeatures =
hostFeatureDao.getSupportedHostFeaturesByHostId(vds.getId());
for (SupportedAdditionalClusterFeature feature : clusterSupportedFeatures) {
if (feature.isEnabled() && !hostSupportedFeatures.contains(feature.getFeature().getName())) {
Map<String, String> customLogValues = new HashMap<>();
customLogValues.put("UnSupportedFeature", feature.getFeature().getName());
reportNonOperationReason(NonOperationalReason.HOST_FEATURES_INCOMPATIBILE_WITH_CLUSTER, customLogValues);
return;
}
}
}
private void reportNonOperationReason(NonOperationalReason reason, String compatibleVersions,
String vdsSupportedVersions) {
Map<String, String> customLogValues = new HashMap<>();
customLogValues.put("CompatibilityVersion", compatibleVersions);
customLogValues.put("VdsSupportedVersions", vdsSupportedVersions);
reportNonOperationReason(reason, customLogValues);
}
private void reportNonOperationReason(NonOperationalReason reason, Map<String, String> customLogValues) {
SetNonOperationalVdsParameters tempVar = new SetNonOperationalVdsParameters(getVdsId(),
reason,
customLogValues);
runInternalAction(VdcActionType.SetNonOperationalVds, tempVar, ExecutionHandler.createInternalJobContext(getContext()));
}
}