package org.ovirt.engine.core.bll; import org.ovirt.engine.core.common.action.VmOperationParameterBase; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VMStatus; import org.ovirt.engine.core.common.businessentities.VmDynamic; import org.ovirt.engine.core.common.vdscommands.DestroyVmVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.UpdateVmDynamicDataVDSCommandParameters; 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.compat.StringHelper; import org.ovirt.engine.core.dal.VdcBllMessages; import org.ovirt.engine.core.dal.dbbroker.DbFacade; public abstract class StopVmCommandBase<T extends VmOperationParameterBase> extends VmOperationCommandBase<T> { private boolean privateSuspendedVm; public StopVmCommandBase(T parameters) { super(parameters); } protected boolean getSuspendedVm() { return privateSuspendedVm; } private void setSuspendedVm(boolean value) { privateSuspendedVm = value; } @Override protected boolean canDoAction() { boolean retValue = true; if (getVm() == null) { retValue = false; addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_VM_NOT_FOUND); } else if (!VM.isStatusUp(getVm().getstatus()) && getVm().getstatus() != VMStatus.Paused && getVm().getstatus() != VMStatus.NotResponding && getVm().getstatus() != VMStatus.Suspended) { if (getVm().getstatus() == VMStatus.SavingState || getVm().getstatus() == VMStatus.RestoringState) { retValue = false; addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_VM_IS_SAVING_RESTORING); } else { retValue = false; addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_VM_IS_NOT_RUNNING); } } return retValue; } protected void Destroy() { if (getVm().getstatus() == VMStatus.MigratingFrom && getVm().getmigrating_to_vds() != null) { Backend.getInstance() .getResourceManager() .RunVdsCommand( VDSCommandType.DestroyVm, new DestroyVmVDSCommandParameters(new Guid(getVm().getmigrating_to_vds().toString()), getVmId(), true, false, 0)); } setActionReturnValue(Backend .getInstance() .getResourceManager() .RunVdsCommand(VDSCommandType.DestroyVm, new DestroyVmVDSCommandParameters(getVdsId(), getVmId(), false, false, 0)).getReturnValue()); } @Override protected void ExecuteVmCommand() { getParameters().setEntityId(getVm().getvm_guid()); if (getVm().getstatus() == VMStatus.Suspended || !StringHelper.isNullOrEmpty(getVm().gethibernation_vol_handle())) { setSuspendedVm(true); setSucceeded(StopSuspendedVm()); } else { super.ExecuteVmCommand(); } } /** * Start stopping operation for suspended VM, by deleting its storage image groups (Created by hibernation process * which indicated its saved memory), and set the VM status to image locked. * * @return True - Operation succeeded <BR/> * False - Operation failed. */ private boolean StopSuspendedVm() { boolean returnVal = false; // Set the Vm to null, for getting the recent VM from the DB, instead from the cache. setVm(null); VMStatus vmStatus = getVm().getstatus(); // Check whether stop VM procedure didn't started yet (Status is not imageLocked), by another transaction. if (getVm().getstatus() != VMStatus.ImageLocked) { // Set the VM to image locked to decrease race condition. getVm().setstatus(VMStatus.ImageLocked); UpdateVmData(getVm().getDynamicData()); if (!StringHelper.isNullOrEmpty(getVm().gethibernation_vol_handle()) && HandleHibernatedVm(getActionType(), false)) { returnVal = true; } else { getVm().setstatus(vmStatus); UpdateVmData(getVm().getDynamicData()); } } return returnVal; } /** * Update Vm dynamic data in the DB.<BR/> * If VM is active in the VDSM (not suspended/stop), we will use UpdateVmDynamicData VDS command, for preventing * over write in the DB, otherwise , update directly to the DB. */ private void UpdateVmData(VmDynamic vmDynamicData) { if (getVm().getrun_on_vds() != null) { Backend.getInstance() .getResourceManager() .RunVdsCommand(VDSCommandType.UpdateVmDynamicData, new UpdateVmDynamicDataVDSCommandParameters(getVm().getrun_on_vds().getValue(), vmDynamicData)); } else { DbFacade.getInstance().getVmDynamicDAO().update(vmDynamicData); } } @Override protected void EndVmCommand() { setCommandShouldBeLogged(false); if (getVm() != null) { getVm().setstatus(VMStatus.Down); getVm().sethibernation_vol_handle(null); DbFacade.getInstance().getVmDynamicDAO().update(getVm().getDynamicData()); } else { log.warn("StopVmCommandBase::EndVmCommand: Vm is null - not performing full EndAction"); } setSucceeded(true); } private static LogCompat log = LogFactoryCompat.getLog(StopVmCommandBase.class); }