package org.ovirt.engine.core.bll; import java.util.List; 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.common.AuditLogType; import org.ovirt.engine.core.common.FeatureSupported; import org.ovirt.engine.core.common.action.ManagementNetworkOnClusterOperationParameters; 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.ArchitectureType; import org.ovirt.engine.core.common.businessentities.Cluster; import org.ovirt.engine.core.common.businessentities.MigrateOnErrorOptions; import org.ovirt.engine.core.common.businessentities.NonOperationalReason; import org.ovirt.engine.core.common.businessentities.ServerCpu; import org.ovirt.engine.core.common.errors.EngineMessage; import org.ovirt.engine.core.compat.TransactionScopeOption; import org.ovirt.engine.core.dao.ClusterDao; @NonTransactiveCommandAttribute public class HandleVdsCpuFlagsOrClusterChangedCommand<T extends VdsActionParameters> extends VdsCommand<T> { @Inject private ClusterDao clusterDao; private boolean _hasFlags = true; private boolean architectureMatch = true; private boolean foundCPU = true; public HandleVdsCpuFlagsOrClusterChangedCommand(T parameters, CommandContext cmdContext) { super(parameters, cmdContext); } @Override protected boolean validate() { boolean result = true; if (getVds() == null) { addValidationMessage(EngineMessage.VDS_INVALID_SERVER_ID); result = false; } return result; } @Override protected void executeCommand() { String clusterCpuName = getVds().getClusterCpuName(); Cluster grp = clusterDao.get(getVds().getClusterId()); ServerCpu sc = getCpuFlagsManagerHandler().findMaxServerCpuByFlags(getVds().getCpuFlags(), getVds() .getClusterCompatibilityVersion()); if (sc == null) { // if there are flags and no cpu found, mark to be non // operational if (!StringUtils.isEmpty(getVds().getCpuFlags())) { foundCPU = false; } else { _hasFlags = false; } log.error("Could not find server cpu for server '{}' ({}), flags: '{}'", getVds().getName(), getVdsId(), getVds().getCpuFlags()); } // Checks whether the host and the cluster have the same architecture if (_hasFlags && foundCPU) { if (grp.getArchitecture() != ArchitectureType.undefined && sc.getArchitecture() != grp.getArchitecture()) { architectureMatch = false; addCustomValue("VdsArchitecture", sc.getArchitecture().name()); addCustomValue("ClusterArchitecture", grp.getArchitecture().name()); SetNonOperationalVdsParameters tempVar = new SetNonOperationalVdsParameters(getVdsId(), NonOperationalReason.ARCHITECTURE_INCOMPATIBLE_WITH_CLUSTER); runInternalAction(VdcActionType.SetNonOperationalVds, tempVar, ExecutionHandler.createInternalJobContext(getContext())); } else { // if cluster doesn't have cpu then get the cpu from the vds if (StringUtils.isEmpty(clusterCpuName)) { // update group with the cpu name grp.setCpuName(sc.getCpuName()); grp.setArchitecture(sc.getArchitecture()); updateMigrateOnError(grp); // use suppress in order to update group even if action fails // (out of the transaction) ManagementNetworkOnClusterOperationParameters tempVar = new ManagementNetworkOnClusterOperationParameters(grp); tempVar.setTransactionScopeOption(TransactionScopeOption.Suppress); tempVar.setIsInternalCommand(true); runInternalAction(VdcActionType.UpdateCluster, tempVar); clusterCpuName = sc.getCpuName(); } } } // If the host CPU name is not found by the CpuFlagsManagerHandler class, report an error if (architectureMatch) { List<String> missingFlags = getCpuFlagsManagerHandler().missingServerCpuFlags(clusterCpuName, getVds() .getCpuFlags(), getVds().getClusterCompatibilityVersion()); if (!StringUtils.isEmpty(getVds().getCpuFlags()) && (!foundCPU || missingFlags != null)) { if (missingFlags != null) { addCustomValue("CpuFlags", StringUtils.join(missingFlags, ", ")); if (missingFlags.contains("nx")) { auditLogDirector.log(this, AuditLogType.CPU_FLAGS_NX_IS_MISSING); } } SetNonOperationalVdsParameters tempVar2 = new SetNonOperationalVdsParameters(getVdsId(), NonOperationalReason.CPU_TYPE_INCOMPATIBLE_WITH_CLUSTER); runInternalAction(VdcActionType.SetNonOperationalVds, tempVar2, ExecutionHandler.createInternalJobContext(getContext())); } else { // if no need to change to non operational then don't log the command setCommandShouldBeLogged(false); } } setSucceeded(true); } private void updateMigrateOnError(Cluster group) { ArchitectureType arch = getArchitecture(group); boolean isMigrationSupported = FeatureSupported.isMigrationSupported(arch, group.getCompatibilityVersion()); if (!isMigrationSupported) { group.setMigrateOnError(MigrateOnErrorOptions.NO); } } protected ArchitectureType getArchitecture(Cluster group) { if (StringUtils.isNotEmpty(group.getCpuName())) { return getCpuFlagsManagerHandler().getArchitectureByCpuName(group.getCpuName(), group.getCompatibilityVersion()); } return group.getArchitecture(); } @Override public AuditLogType getAuditLogTypeValue() { if (!foundCPU) { return AuditLogType.CPU_TYPE_UNSUPPORTED_IN_THIS_CLUSTER_VERSION; } else if (!architectureMatch) { return AuditLogType.VDS_ARCHITECTURE_NOT_SUPPORTED_FOR_CLUSTER; } else if (!_hasFlags) { return AuditLogType.VDS_CPU_RETRIEVE_FAILED; } else { return AuditLogType.VDS_CPU_LOWER_THAN_CLUSTER; } } }