package org.ovirt.engine.core.vdsbroker; import javax.inject.Inject; import org.apache.commons.lang.StringUtils; import org.ovirt.engine.core.common.vdscommands.VDSParametersBase; import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; import org.ovirt.engine.core.dal.VdcCommandBase; import org.ovirt.engine.core.utils.transaction.TransactionCompletionListener; import org.ovirt.engine.core.utils.transaction.TransactionSupport; import org.ovirt.engine.core.vdsbroker.vdsbroker.VDSExceptionBase; public abstract class VDSCommandBase<P extends VDSParametersBase> extends VdcCommandBase { private P _parameters; private boolean async; @Inject protected ResourceManager resourceManager; protected void registerRollbackHandler(TransactionCompletionListener transactionCompletionListener) { if (TransactionSupport.current() != null) { TransactionSupport.registerRollbackHandler(transactionCompletionListener); } } public P getParameters() { return _parameters; } protected VDSReturnValue _returnValue = null; public VDSReturnValue getVDSReturnValue() { return _returnValue; } public void setVDSReturnValue(VDSReturnValue value) { _returnValue = value; } @Override public Object getReturnValue() { return getVDSReturnValue().getReturnValue(); } @Override public void setReturnValue(Object value) { getVDSReturnValue().setReturnValue(value); } public VDSCommandBase(P parameters) { _parameters = parameters; } @Override public String toString() { String addInfo = getAdditionalInformation(); return String.format("%s(%s %s)", super.toString(), !addInfo.isEmpty() ? addInfo + "," : StringUtils.EMPTY, getParameters() != null ? getParameters().toString() : "null"); } @Override protected void executeCommand() { try { if (isAsync()) { executeCommandAsynchronously(); return; } // creating ReturnValue object since execute can be called more than once (failover) // and we want returnValue clean from last run. _returnValue = new VDSReturnValue(); getVDSReturnValue().setSucceeded(true); executeVDSCommand(); } catch (RuntimeException ex) { setVdsRuntimeErrorAndReport(ex); } } protected void setVdsRuntimeErrorAndReport(RuntimeException ex) { setVdsRuntimeError(ex); logException(ex); } protected void setVdsRuntimeError(RuntimeException ex) { getVDSReturnValue().setSucceeded(false); getVDSReturnValue().setExceptionString(ex.toString()); getVDSReturnValue().setExceptionObject(ex); VDSExceptionBase vdsExp = (VDSExceptionBase) ((ex instanceof VDSExceptionBase) ? ex : null); // todo: consider adding unknown vds error in case of non // VDSExceptionBase exception if (vdsExp != null) { if (vdsExp.getVdsError() != null) { getVDSReturnValue().setVdsError(((VDSExceptionBase) ex).getVdsError()); } else if (vdsExp.getCause() instanceof VDSExceptionBase) { getVDSReturnValue().setVdsError(((VDSExceptionBase) vdsExp.getCause()).getVdsError()); } } } private void logException(RuntimeException ex) { if (ex.getMessage() == null || !ex.getMessage().contains("Policy reset")) { log.error("Command '{}' execution failed: {}", this, ex.getMessage()); log.debug("Exception", ex); } } protected String getAdditionalInformation() { return StringUtils.EMPTY; } protected abstract void executeVDSCommand(); public void setAsync(boolean async) { this.async = async; } public boolean isAsync() { return this.async; } /** * When providing asynchronous execution of vds command this method need to * be overridden. */ protected void executeCommandAsynchronously() { throw new UnsupportedOperationException(this.getClass().getName() + " does not provide setAsyncResult implementation"); } }