package org.ovirt.engine.core.bll.storage;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.ovirt.engine.core.bll.context.CommandContext;
import org.ovirt.engine.core.bll.pm.FenceVdsBaseCommand;
import org.ovirt.engine.core.bll.utils.PermissionSubject;
import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.VdcObjectType;
import org.ovirt.engine.core.common.action.FenceVdsManualyParameters;
import org.ovirt.engine.core.common.action.LockProperties;
import org.ovirt.engine.core.common.action.LockProperties.Scope;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.action.VdsActionParameters;
import org.ovirt.engine.core.common.businessentities.StorageDomain;
import org.ovirt.engine.core.common.businessentities.StorageDomainStatus;
import org.ovirt.engine.core.common.businessentities.StorageDomainType;
import org.ovirt.engine.core.common.businessentities.StoragePoolStatus;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.VDSStatus;
import org.ovirt.engine.core.common.businessentities.VdsSpmStatus;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.common.utils.Pair;
import org.ovirt.engine.core.common.vdscommands.ResetIrsVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AlertDirector;
import org.ovirt.engine.core.dao.StorageDomainDao;
import org.ovirt.engine.core.dao.VdsDao;
/**
* Confirm a host has been rebooted, clear spm flag, its VMs(optional) and alerts.
*
* This command should be run mutually exclusive from other fence actions to prevent same action or other fence actions
* to clear the VMs and start them.
*
* @see RestartVdsCommand
*/
public class FenceVdsManualyCommand<T extends FenceVdsManualyParameters> extends StorageHandlingCommandBase<T> {
@Inject
private VdsDao vdsDao;
@Inject
private StorageDomainDao storageDomainDao;
@Inject
private AlertDirector alertDirector;
private VDS problematicVds;
/**
* Constructor for command creation when compensation is applied on startup
*/
public FenceVdsManualyCommand(Guid commandId) {
super(commandId);
}
public FenceVdsManualyCommand(T parameters, CommandContext commandContext) {
super(parameters, commandContext);
}
@Override
public void init() {
super.init();
problematicVds = vdsDao.get(getParameters().getVdsId());
}
@Override
protected LockProperties applyLockProperties(LockProperties lockProperties) {
return lockProperties.withScope(Scope.Execution);
}
public Guid getProblematicVdsId() {
return problematicVds.getId();
}
@Override
protected boolean validate() {
// check problematic vds status
if (isLegalStatus(problematicVds.getStatus())) {
if (problematicVds.getSpmStatus() == VdsSpmStatus.SPM) {
if(!getStoragePool().isLocal()) {
if (!initializeVds()) {
return false;
}
}
if (getStoragePool().getStatus() != StoragePoolStatus.NotOperational
&& getStoragePool().getStatus() != StoragePoolStatus.NonResponsive
&& getStoragePool().getStatus() != StoragePoolStatus.Maintenance) {
return failValidation(EngineMessage.ACTION_TYPE_FAILED_STORAGE_POOL_STATUS_ILLEGAL);
}
}
} else {
return failValidation(EngineMessage.ACTION_TYPE_FAILED_VDS_NOT_MATCH_VALID_STATUS);
}
return true;
}
@Override
protected void executeCommand() {
setVdsName(problematicVds.getName());
if (problematicVds.getSpmStatus() == VdsSpmStatus.SPM) {
activateDataCenter();
}
if (getParameters().getClearVMs()) {
VdsActionParameters tempVar = new VdsActionParameters(problematicVds.getId());
tempVar.setSessionId(getParameters().getSessionId());
runInternalActionWithTasksContext(
VdcActionType.ClearNonResponsiveVdsVms,
tempVar);
}
setSucceeded(true);
// Remove all alerts except NOT CONFIG alert
alertDirector.removeAllVdsAlerts(problematicVds.getId(), false);
}
@Override
public AuditLogType getAuditLogTypeValue() {
if (isInternalExecution()) {
return getSucceeded()
? AuditLogType.VDS_AUTO_FENCE_STATUS
: AuditLogType.VDS_AUTO_FENCE_STATUS_FAILED;
} else {
return getSucceeded()
? AuditLogType.VDS_MANUAL_FENCE_STATUS
: AuditLogType.VDS_MANUAL_FENCE_STATUS_FAILED;
}
}
/**
* Determines whether VDS [is legal status] [the specified status].
*
* @param status
* The status.
* @return <c>true</c> if [is legal status] [the specified status];
* otherwise, <c>false</c>.
*/
private static boolean isLegalStatus(VDSStatus status) {
boolean result;
switch (status) {
case Down:
case InstallFailed:
case Maintenance:
case NonOperational:
case NonResponsive:
case Reboot:
case Installing:
case Connecting:
case Kdumping:
result = true;
break;
default:
result = false;
break;
}
return result;
}
private void activateDataCenter() {
StorageDomain masterDomain =
storageDomainDao.getStorageDomains(getStoragePool().getId(), StorageDomainType.Master).stream().findFirst().orElse(null);
calcStoragePoolStatusByDomainsStatus();
// fence spm if moving from not operational and master domain is active
if (masterDomain != null
&& masterDomain.getStatus() != null
&& (masterDomain.getStatus() == StorageDomainStatus.Active
|| masterDomain.getStatus() == StorageDomainStatus.Unknown || masterDomain.getStatus() == StorageDomainStatus.Inactive)) {
resetIrs();
}
}
private void resetIrs() {
if (getStoragePool().getSpmVdsId() != null) {
ResetIrsVDSCommandParameters tempVar =
new ResetIrsVDSCommandParameters(getStoragePool()
.getId(), getStoragePool().getSpmVdsId());
tempVar.setVdsAlreadyRebooted(true);
runVdsCommand(VDSCommandType.ResetIrs, tempVar);
}
}
@Override
protected Map<String, Pair<String, String>> getExclusiveLocks() {
return FenceVdsBaseCommand.createFenceExclusiveLocksMap(getProblematicVdsId());
}
@Override
public List<PermissionSubject> getPermissionCheckSubjects() {
return Collections.singletonList(new PermissionSubject(getParameters().getVdsId(), VdcObjectType.VDS,
getActionType().getActionGroup()));
}
@Override
protected void setActionMessageParameters() {
addValidationMessage(EngineMessage.VAR__ACTION__MANUAL_FENCE);
addValidationMessage(EngineMessage.VAR__TYPE__HOST);
}
@Override
protected void freeLock() {
if (getParameters().getParentCommand() != VdcActionType.RestartVds) {
super.freeLock();
}
}
}