package org.ovirt.engine.core.bll.pm;
import static org.ovirt.engine.core.common.errors.EngineMessage.VAR__ACTION__STOP;
import java.util.List;
import javax.inject.Inject;
import org.ovirt.engine.core.bll.NonTransactiveCommandAttribute;
import org.ovirt.engine.core.bll.RestartVdsVmsOperation;
import org.ovirt.engine.core.bll.context.CommandContext;
import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.action.FenceVdsActionParameters;
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.businessentities.VDSStatus;
import org.ovirt.engine.core.common.businessentities.VM;
import org.ovirt.engine.core.common.businessentities.VdsSpmStatus;
import org.ovirt.engine.core.common.businessentities.pm.FenceActionType;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.common.vdscommands.SpmStopVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.UpdateVdsVMsClearedVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
import org.ovirt.engine.core.dao.VdsDao;
import org.ovirt.engine.core.dao.VdsDynamicDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Send a Stop action to a power control device.
*
* 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
* @see FenceVdsBaseCommand#restartVdsVms()
*/
@NonTransactiveCommandAttribute
public class StopVdsCommand<T extends FenceVdsActionParameters> extends FenceVdsBaseCommand<T> {
private static final Logger log = LoggerFactory.getLogger(StopVdsCommand.class);
@Inject
private VdsDao vdsDao;
@Inject
private VdsDynamicDao vdsDynamicDao;
public StopVdsCommand(T parameters, CommandContext commandContext) {
super(parameters, commandContext);
}
@Override
protected LockProperties applyLockProperties(LockProperties lockProperties) {
return lockProperties.withScope(Scope.Execution);
}
@Override
protected boolean validate() {
boolean retValue = true;
if (!isExecutedAsChildCommand()) {
retValue = super.validate();
if (getVds() != null && getVds().getStatus() != VDSStatus.Maintenance) {
addValidationMessage(EngineMessage.VDS_STATUS_NOT_VALID_FOR_STOP);
retValue = false;
}
}
getReturnValue().setValid(retValue);
return retValue;
}
@Override
protected void setStatus() {
VDSStatus newStatus = VDSStatus.Down;
if (getParameters().getParentCommand() == VdcActionType.RestartVds) {
// In case the stop was issued as a result of VDS command , we
// cannot set the VDS to down -
// According to bug fix #605215 it can be that backend will crash
// during restart, and upon restart, all down VDS are not
// monitored. Instead, we will set the status to rebooting
newStatus = VDSStatus.Reboot;
}
setStatus(newStatus);
}
@Override
protected void setActionMessageParameters() {
addValidationMessage(VAR__ACTION__STOP);
}
@Override
protected void handleError() {
addValidationMessage(EngineMessage.VDS_FENCE_OPERATION_FAILED);
addValidationMessage(EngineMessage.VAR__TYPE__HOST);
addValidationMessage(EngineMessage.VAR__ACTION__STOP);
log.error("Failed to run StopVdsCommand on vds '{}'", getVdsName());
}
@Override
public AuditLogType getAuditLogTypeValue() {
return getSucceeded() ? AuditLogType.USER_VDS_STOP : AuditLogType.USER_FAILED_VDS_STOP;
}
@Override
protected void handleSpecificCommandActions() {
List<VM> vmList = getVmList();
if (vmList.size() > 0) {
RestartVdsVmsOperation restartVmsOper = new RestartVdsVmsOperation(
getContext(),
getVds()
);
restartVmsOper.restartVms(vmList);
runVdsCommand(VDSCommandType.UpdateVdsVMsCleared,
new UpdateVdsVMsClearedVDSCommandParameters(getVds().getId()));
}
}
@Override
protected void freeLock() {
if (getParameters().getParentCommand() != VdcActionType.RestartVds) {
super.freeLock();
}
}
@Override
protected FenceActionType getAction() {
return FenceActionType.STOP;
}
@Override
protected String getRequestedAuditEvent() {
return AuditLogType.USER_VDS_START.name();
}
@Override
protected void setup() {
// Set status immediately to prevent a race (BZ 636950/656224)
setStatus();
stopSpm();
}
private void stopSpm() {
// get the host spm status again from the database in order to test it's current state.
VdsSpmStatus spmStatus = vdsDao.get(getVds().getId()).getSpmStatus();
// try to stop SPM if action is Restart or Stop and the vds is SPM
if (spmStatus != VdsSpmStatus.None) {
runVdsCommand(
VDSCommandType.SpmStop,
new SpmStopVDSCommandParameters(getVds().getId(), getVds().getStoragePoolId()));
}
}
@Override
protected void teardown() {
// Successful fencing with reboot or shutdown op. Clear the power management policy flag
if (!getParameters().getKeepPolicyPMEnabled()) {
getVds().setPowerManagementControlledByPolicy(false);
vdsDynamicDao.updateVdsDynamicPowerManagementPolicyFlag(
getVdsId(),
getVds().getDynamicData().isPowerManagementControlledByPolicy());
}
}
}