package org.ovirt.engine.core.bll.storage;
import java.util.Collections;
import java.util.Map;
import org.ovirt.engine.core.bll.Backend;
import org.ovirt.engine.core.bll.LockIdNameAttribute;
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.VdcActionType;
import org.ovirt.engine.core.common.action.VdsActionParameters;
import org.ovirt.engine.core.common.businessentities.SpmStatusResult;
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.StorageType;
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.businessentities.storage_domains;
import org.ovirt.engine.core.common.vdscommands.FenceSpmStorageVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.ResetIrsVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.SpmStatusVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.compat.LogCompat;
import org.ovirt.engine.core.compat.LogFactoryCompat;
import org.ovirt.engine.core.dal.VdcBllMessages;
import org.ovirt.engine.core.dal.dbbroker.DbFacade;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AlertDirector;
import org.ovirt.engine.core.utils.linq.LinqUtils;
import org.ovirt.engine.core.utils.linq.Predicate;
@LockIdNameAttribute(fieldName = "ProblematicVdsId")
public class FenceVdsManualyCommand<T extends FenceVdsManualyParameters> extends StorageHandlingCommandBase<T> {
private final VDS _problematicVds;
/**
* Constructor for command creation when compensation is applied on startup
*
* @param commandId
*/
protected FenceVdsManualyCommand(Guid commandId) {
super(commandId);
_problematicVds = null;
}
public FenceVdsManualyCommand(T parameters) {
super(parameters);
_problematicVds = DbFacade.getInstance().getVdsDAO().get(parameters.getVdsId());
}
public Guid getProblematicVdsId() {
return _problematicVds.getvds_id();
}
@Override
protected boolean canDoAction() {
boolean returnValue = true;
addCanDoActionMessage(VdcBllMessages.VAR__TYPE__HOST);
addCanDoActionMessage(VdcBllMessages.VAR__ACTION__MANUAL_FENCE);
// check problematic vds status
if (IsLegalStatus(_problematicVds.getstatus())) {
if (_problematicVds.getspm_status() == VdsSpmStatus.SPM) {
if(getStoragePool().getstorage_pool_type() != StorageType.LOCALFS) {
returnValue = returnValue && InitializeVds();
}
if (returnValue && getStoragePool().getstatus() != StoragePoolStatus.NotOperational
&& getStoragePool().getstatus() != StoragePoolStatus.Problematic
&& getStoragePool().getstatus() != StoragePoolStatus.Maintanance) {
returnValue = false;
addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_STORAGE_POOL_STATUS_ILLEGAL);
}
}
} else {
if (_problematicVds.getstatus() == VDSStatus.Problematic) {
returnValue = false;
addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_VDS_INTERMITENT_CONNECTIVITY);
} else {
returnValue = false;
addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_VDS_NOT_MATCH_VALID_STATUS);
}
}
return returnValue;
}
@Override
protected void executeCommand() {
boolean result = true;
setVdsName(_problematicVds.getvds_name());
if (_problematicVds.getspm_status() == VdsSpmStatus.SPM) {
result = ActivateDataCenter();
}
if ((getParameters()).getClearVMs() && result) {
VdsActionParameters tempVar = new VdsActionParameters(_problematicVds.getvds_id());
tempVar.setSessionId(getParameters().getSessionId());
Backend.getInstance().runInternalAction(VdcActionType.ClearNonResponsiveVdsVms,
tempVar);
}
setSucceeded(result);
if (getSucceeded()) {
// Remove all alerts except NOT CONFIG alert
AlertDirector.RemoveAllVdsAlerts(_problematicVds.getvds_id(), false);
}
}
@Override
public AuditLogType getAuditLogTypeValue() {
return _fenceSpmCalled != null && !_fenceSpmCalled ? AuditLogType.VDS_MANUAL_FENCE_FAILED_CALL_FENCE_SPM
: 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:
result = true;
break;
default:
result = false;
break;
}
return result;
}
private Boolean _fenceSpmCalled;
private boolean ActivateDataCenter() {
boolean result = false;
_fenceSpmCalled = false;
// storage_domains masterDomain = null; // LINQ 32934
// DbFacade.Instance.GetStorageDomainsByStoragePoolId(StoragePool.id)
// LINQ 32934 .Where(a => a.storage_domain_type ==
// StorageDomainType.Master).FirstOrDefault();
storage_domains masterDomain = LinqUtils.firstOrNull(
DbFacade.getInstance().getStorageDomainDAO().getAllForStoragePool(getStoragePool().getId()),
new Predicate<storage_domains>() {
@Override
public boolean eval(storage_domains a) {
return a.getstorage_domain_type() == StorageDomainType.Master;
}
});
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)) {
if (getStoragePool().getstorage_pool_type() != StorageType.LOCALFS) {
for (VDS vds : getAllRunningVdssInPool()) {
try {
SpmStatusResult statusResult = (SpmStatusResult) Backend
.getInstance()
.getResourceManager()
.RunVdsCommand(VDSCommandType.SpmStatus,
new SpmStatusVDSCommandParameters(vds.getvds_id(), getStoragePool().getId()))
.getReturnValue();
log.infoFormat("Trying to fence spm {0} via vds {1}",
_problematicVds.getvds_name(),
vds.getvds_name());
if (Backend
.getInstance()
.getResourceManager()
.RunVdsCommand(
VDSCommandType.FenceSpmStorage,
new FenceSpmStorageVDSCommandParameters(vds.getvds_id(),
getStoragePool().getId(),
statusResult.getSpmId(),
statusResult.getSpmLVER()))
.getSucceeded()) {
resetIrs();
result = true;
_fenceSpmCalled = true;
break;
}
} catch (java.lang.Exception e) {
log.warnFormat("Could not fence spm on vds {0}", vds.getvds_name());
}
}
} else {
resetIrs();
result = true;
}
} else {
result = true;
}
return result;
}
private void resetIrs() {
if (getStoragePool().getspm_vds_id() != null) {
VDS currentSPMVds =
DbFacade.getInstance().getVdsDAO().get(getStoragePool().getspm_vds_id());
ResetIrsVDSCommandParameters tempVar =
new ResetIrsVDSCommandParameters(getStoragePool()
.getId(), currentSPMVds.gethost_name(), currentSPMVds.getvds_id());
tempVar.setIgnoreStopFailed(true);
Backend.getInstance()
.getResourceManager()
.RunVdsCommand(VDSCommandType.ResetIrs, tempVar);
}
}
private static LogCompat log = LogFactoryCompat.getLog(FenceVdsManualyCommand.class);
@Override
public Map<Guid, VdcObjectType> getPermissionCheckSubjects() {
return Collections.singletonMap(getParameters().getVdsId(), VdcObjectType.VDS);
}
}