package org.ovirt.engine.core.bll.tasks; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.concurrent.Future; import org.ovirt.engine.core.bll.Backend; import org.ovirt.engine.core.bll.CommandBase; import org.ovirt.engine.core.bll.CommandsFactory; import org.ovirt.engine.core.bll.context.CommandContext; import org.ovirt.engine.core.bll.interfaces.BackendInternal; import org.ovirt.engine.core.bll.tasks.interfaces.CommandCallback; import org.ovirt.engine.core.bll.tasks.interfaces.CommandCoordinator; import org.ovirt.engine.core.bll.tasks.interfaces.SPMTask; import org.ovirt.engine.core.common.VdcObjectType; import org.ovirt.engine.core.common.action.VdcActionParametersBase; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.action.VdcReturnValueBase; import org.ovirt.engine.core.common.asynctasks.AsyncTaskCreationInfo; import org.ovirt.engine.core.common.asynctasks.AsyncTaskParameters; import org.ovirt.engine.core.common.asynctasks.AsyncTaskType; import org.ovirt.engine.core.common.businessentities.AsyncTask; import org.ovirt.engine.core.common.businessentities.AsyncTaskStatus; import org.ovirt.engine.core.common.businessentities.CommandAssociatedEntity; import org.ovirt.engine.core.common.businessentities.CommandEntity; import org.ovirt.engine.core.common.config.Config; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.common.vdscommands.IrsBaseVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.SPMTaskGuidBaseVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.common.vdscommands.VDSParametersBase; import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; import org.ovirt.engine.core.compat.CommandStatus; import org.ovirt.engine.core.compat.DateTime; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.di.Injector; import org.ovirt.engine.core.vdsbroker.ResourceManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class CommandCoordinatorImpl implements CommandCoordinator { private static final Logger log = LoggerFactory.getLogger(CommandCoordinatorImpl.class); private final CoCoAsyncTaskHelper coCoAsyncTaskHelper; private final CommandExecutor cmdExecutor; private final CommandsRepository commandsRepository; CommandCoordinatorImpl() { coCoAsyncTaskHelper = new CoCoAsyncTaskHelper(this); commandsRepository = Injector.get(CommandsRepository.class); cmdExecutor = Injector.get(CommandExecutor.class); } public <P extends VdcActionParametersBase> CommandBase<P> createCommand(VdcActionType action, P parameters) { return CommandsFactory.createCommand(action, parameters); } @Override public void persistCommand(CommandEntity cmdEntity, CommandContext cmdContext) { commandsRepository.persistCommand(cmdEntity, cmdContext); } @Override public void persistCommand(CommandEntity cmdEntity) { commandsRepository.persistCommand(cmdEntity); } @Override public void persistCommandAssociatedEntities(Collection<CommandAssociatedEntity> cmdAssociatedEntities) { commandsRepository.persistCommandAssociatedEntities(cmdAssociatedEntities); } @Override public List<Guid> getCommandIdsByEntityId(Guid entityId) { return commandsRepository.getCommandIdsByEntityId(entityId); } @Override public List<CommandAssociatedEntity> getCommandAssociatedEntities(Guid cmdId) { return commandsRepository.getCommandAssociatedEntities(cmdId); } /** * Executes the action using a Thread Pool. Used when the calling function * would like the execute the command with no delay */ @Override public Future<VdcReturnValueBase> executeAsyncCommand(VdcActionType actionType, VdcActionParametersBase parameters, CommandContext cmdContext) { final CommandBase<?> command = CommandsFactory.createCommand(actionType, parameters, cmdContext); CommandCallback callBack = command.getCallback(); command.persistCommand(command.getParameters().getParentCommand(), cmdContext, callBack != null, false); if (callBack != null) { commandsRepository.addToCallbackMap(command.getCommandId(), new CallbackTiming(callBack, Config.<Integer> getValue(ConfigValues.AsyncCommandPollingLoopInSeconds))); } return cmdExecutor.executeAsyncCommand(command, cmdContext); } @Override public CommandEntity getCommandEntity(Guid commandId) { return commandsRepository.getCommandEntity(commandId); } @Override public CommandEntity createCommandEntity(Guid cmdId, VdcActionType actionType, VdcActionParametersBase params) { CommandEntity cmdEntity = new CommandEntity(); cmdEntity.setId(cmdId); cmdEntity.setCommandType(actionType); cmdEntity.setCommandParameters(params); return cmdEntity; } @Override public CommandBase<?> retrieveCommand(Guid commandId) { return commandsRepository.retrieveCommand(commandId); } @Override public CommandStatus getCommandStatus(final Guid commandId) { return commandsRepository.getCommandStatus(commandId); } @Override public void removeAllCommandsInHierarchy(final Guid commandId) { for (Guid childCmdId : new ArrayList<>(getChildCommandIds(commandId))) { removeAllCommandsInHierarchy(childCmdId); } removeCommand(commandId); } @Override public void removeCommand(final Guid commandId) { commandsRepository.removeCommand(commandId); } @Override public void removeAllCommandsBeforeDate(final DateTime cutoff) { commandsRepository.removeAllCommandsBeforeDate(cutoff); } @Override public void updateCommandData(final Guid commandId, final Map<String, Serializable> data) { commandsRepository.updateCommandData(commandId, data); } @Override public void updateCommandStatus(final Guid commandId, final CommandStatus status) { commandsRepository.updateCommandStatus(commandId, status); } @Override public void updateCommandExecuted(Guid commandId) { commandsRepository.updateCommandExecuted(commandId); } @Override public boolean hasCommandEntitiesWithRootCommandId(Guid rootCommandId) { return commandsRepository.hasCommandEntitiesWithRootCommandId(rootCommandId); } @Override public List<Guid> getChildCommandIds(Guid cmdId) { return commandsRepository.getChildCommandIds(cmdId); } @Override public List<Guid> getChildCommandIds(Guid cmdId, VdcActionType childActionType, CommandStatus status) { List<Guid> childCmdIds = new ArrayList<>(); for (Guid childCmdId : getChildCommandIds(cmdId)) { CommandEntity childCmdEntity = getCommandEntity(childCmdId); if (childCmdEntity != null && childCmdEntity.getCommandType().equals(childActionType) && (status == null || status.equals(childCmdEntity.getCommandStatus()))) { childCmdIds.add(childCmdId); } } return childCmdIds; } @Override public List<Guid> getCommandIdsBySessionSeqId(long engineSessionSeqId) { return commandsRepository.getCommandIdsBySessionSeqId(engineSessionSeqId); } @Override public List<CommandEntity> getChildCmdsByRootCmdId(Guid cmdId) { return commandsRepository.getChildCmdsByParentCmdId(cmdId); } @Override public List<AsyncTask> getAllAsyncTasksFromDb() { return coCoAsyncTaskHelper.getAllAsyncTasksFromDb(this); } @Override public void saveAsyncTaskToDb(final AsyncTask asyncTask) { coCoAsyncTaskHelper.saveAsyncTaskToDb(asyncTask); } @Override public AsyncTask getAsyncTaskFromDb(Guid asyncTaskId) { return coCoAsyncTaskHelper.getAsyncTaskFromDb(asyncTaskId); } @Override public int removeTaskFromDbByTaskId(final Guid taskId) throws RuntimeException { return coCoAsyncTaskHelper.removeTaskFromDbByTaskId(taskId); } @Override public AsyncTask getByVdsmTaskId(Guid vdsmTaskId) { return coCoAsyncTaskHelper.getByVdsmTaskId(vdsmTaskId); } @Override public int removeByVdsmTaskId(final Guid vdsmTaskId) { return coCoAsyncTaskHelper.removeByVdsmTaskId(vdsmTaskId); } @Override public void addOrUpdateTaskInDB(final AsyncTask asyncTask) { coCoAsyncTaskHelper.addOrUpdateTaskInDB(asyncTask); } public SPMAsyncTask createTask(AsyncTaskType taskType, AsyncTaskParameters taskParameters) { return coCoAsyncTaskHelper.createTask(taskType, taskParameters); } @Override public AsyncTask getAsyncTask( Guid taskId, CommandBase<?> command, AsyncTaskCreationInfo asyncTaskCreationInfo, VdcActionType parentCommand) { return coCoAsyncTaskHelper.getAsyncTask(taskId, command, asyncTaskCreationInfo, parentCommand); } @Override public AsyncTask createAsyncTask( CommandBase<?> command, AsyncTaskCreationInfo asyncTaskCreationInfo, VdcActionType parentCommand) { return coCoAsyncTaskHelper.createAsyncTask(command, asyncTaskCreationInfo, parentCommand); } @Override public Guid createTask(Guid taskId, CommandBase<?> command, AsyncTaskCreationInfo asyncTaskCreationInfo, VdcActionType parentCommand, String description, Map<Guid, VdcObjectType> entitiesMap) { return coCoAsyncTaskHelper.createTask(taskId, command, asyncTaskCreationInfo, parentCommand, description, entitiesMap); } @Override public SPMAsyncTask concreteCreateTask( Guid taskId, CommandBase<?> command, AsyncTaskCreationInfo asyncTaskCreationInfo, VdcActionType parentCommand) { return coCoAsyncTaskHelper.concreteCreateTask(taskId, command, asyncTaskCreationInfo, parentCommand); } @Override public void cancelTasks(final CommandBase<?> command) { coCoAsyncTaskHelper.cancelTasks(command, log); } @Override public void revertTasks(CommandBase<?> command) { coCoAsyncTaskHelper.revertTasks(command); } @Override public ArrayList<AsyncTaskCreationInfo> getAllTasksInfo(Guid storagePoolID) { return (ArrayList<AsyncTaskCreationInfo>) runVdsCommand(VDSCommandType.SPMGetAllTasksInfo, new IrsBaseVDSCommandParameters(storagePoolID)).getReturnValue(); } @Override public Map<Guid, AsyncTaskStatus> getAllTasksStatuses(Guid storagePoolID) { return (Map<Guid, AsyncTaskStatus> ) runVdsCommand(VDSCommandType.SPMGetAllTasksStatuses, new IrsBaseVDSCommandParameters(storagePoolID)).getReturnValue(); } @Override public void stopTask(Guid storagePoolID, Guid vdsmTaskID) { runVdsCommand(VDSCommandType.SPMStopTask, new SPMTaskGuidBaseVDSCommandParameters(storagePoolID, vdsmTaskID)); } @Override public VDSReturnValue clearTask(Guid storagePoolID, Guid vdsmTaskID) { return runVdsCommand(VDSCommandType.SPMClearTask, new SPMTaskGuidBaseVDSCommandParameters(storagePoolID, vdsmTaskID)); } @Override public boolean doesCommandContainAsyncTask(Guid cmdId) { return AsyncTaskManager.getInstance().doesCommandContainAsyncTask(cmdId); } private VDSReturnValue runVdsCommand(VDSCommandType commandType, VDSParametersBase parameters) { return Backend.getInstance().getResourceManager().runVdsCommand(commandType, parameters); } @Override public SPMTask construct(AsyncTaskCreationInfo creationInfo) { return AsyncTaskFactory.construct(this, creationInfo); } @Override public SPMTask construct(AsyncTaskCreationInfo creationInfo, AsyncTask asyncTask) { return AsyncTaskFactory.construct(this, creationInfo.getTaskType(), new AsyncTaskParameters(creationInfo, asyncTask), true); } @Override public SPMTask construct(AsyncTaskType taskType, AsyncTaskParameters asyncTaskParams, boolean duringInit) { return AsyncTaskFactory.construct(this, taskType, asyncTaskParams, duringInit); } @Override public VdcReturnValueBase endAction(SPMTask task) { return coCoAsyncTaskHelper.endAction(task); } @Override public CommandContext retrieveCommandContext(Guid cmdId) { return commandsRepository.retrieveCommandContext(cmdId); } protected BackendInternal getBackend() { return Backend.getInstance(); } @Override public void subscribe(String eventKey, CommandEntity commandEntity) { commandsRepository.persistCommand(commandEntity); CoCoEventSubscriber subscriber = new CoCoEventSubscriber(eventKey, commandEntity, commandsRepository); getResourceManager().subscribe(subscriber); commandsRepository.addEventSubscription(commandEntity, subscriber); } private ResourceManager getResourceManager() { return Injector.get(ResourceManager.class); } }