package org.ovirt.engine.core.bll.tasks; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Future; import java.util.stream.Collectors; import org.ovirt.engine.core.bll.CommandBase; import org.ovirt.engine.core.bll.context.CommandContext; import org.ovirt.engine.core.bll.tasks.interfaces.CommandCoordinator; 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.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.businessentities.StoragePool; import org.ovirt.engine.core.common.businessentities.SubjectEntity; 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.compat.backendcompat.CommandExecutionStatus; public class CommandCoordinatorUtil { public static final CommandCoordinator coco = new CommandCoordinatorImpl(); /** * Start polling the task identified by the vdsm task id * @param taskID The vdsm task id */ public static void startPollingTask(Guid taskID) { getAsyncTaskManager().startPollingTask(taskID); } /** * Retrieves from the specified storage pool the tasks that exist on it and * adds them to the async task manager. * * @param sp the storage pool to retrieve running tasks from */ public static void addStoragePoolExistingTasks(StoragePool sp) { getAsyncTaskManager().addStoragePoolExistingTasks(sp); } /** * Checks if there are tasks of the specified type existing on the entity * @param id The entity id * @param type The action type */ public static boolean hasTasksForEntityIdAndAction(Guid id, VdcActionType type) { return getAsyncTaskManager().hasTasksForEntityIdAndAction(id, type); } /** * Checks if there are tasks existing on the storage pool * @param storagePoolID Id of the storage pool */ public static boolean hasTasksByStoragePoolId(Guid storagePoolID) { return getAsyncTaskManager().hasTasksByStoragePoolId(storagePoolID); } /** * Initialize Async Task Manager. */ public static void initAsyncTaskManager() { getAsyncTaskManager().initAsyncTaskManager(); } /** * Checks if there are tasks on the entity * @param id The entity id */ public static boolean entityHasTasks(Guid id) { return getAsyncTaskManager().entityHasTasks(id); } /** * Poll vdsm for the task status and update the task * @param taskIdList The list of task ids * @return List of async task status */ public static ArrayList<AsyncTaskStatus> pollTasks(java.util.ArrayList<Guid> taskIdList) { return getAsyncTaskManager().pollTasks(taskIdList); } /** * Create an Async Task. * @param taskId the id of the async task place holder in the database * @param command the command object creating the task * @param asyncTaskCreationInfo Info on how to create the task * @param parentCommand The type of command issuing the task * @param description A message which describes the task * @param entitiesMap map of entities */ public static Guid createTask( Guid taskId, CommandBase<?> command, AsyncTaskCreationInfo asyncTaskCreationInfo, VdcActionType parentCommand, String description, Map<Guid, VdcObjectType> entitiesMap) { return coco.createTask(taskId, command, asyncTaskCreationInfo, parentCommand, description, entitiesMap); } /** * Create the {@link SPMAsyncTask} object to be run * @param taskId the id of the async task place holder in the database * @param command the command object creating the task * @param asyncTaskCreationInfo Info on how to create the task * @param parentCommand The type of command issuing the task */ public static SPMAsyncTask concreteCreateTask( Guid taskId, CommandBase<?> command, AsyncTaskCreationInfo asyncTaskCreationInfo, VdcActionType parentCommand) { return coco.concreteCreateTask(taskId, command, asyncTaskCreationInfo, parentCommand); } /** * Stops all tasks, and set them to polling state, for clearing them up later. * @param command The command whose vdsm tasks need to be cancelled */ public static void cancelTasks(final CommandBase<?> command) { coco.cancelTasks(command); } /** * Revert the vdsm tasks associated with the command * @param command The command whose vdsm tasks need to be reverted */ public static void revertTasks(final CommandBase<?> command) { coco.revertTasks(command); } /** * Retrieve the async task by task id, create one if it does not exist. * @param taskId the id of the async task place holder in the database * @param command the command object retrieving or creating the task * @param asyncTaskCreationInfo Info on how to create the task if one does not exist * @param parentCommand The type of command issuing the task */ public static AsyncTask getAsyncTask( Guid taskId, CommandBase<?> command, AsyncTaskCreationInfo asyncTaskCreationInfo, VdcActionType parentCommand) { return coco.getAsyncTask(taskId, command, asyncTaskCreationInfo, parentCommand); } /** * Create Async Task to be run * @param command the command object creating the task * @param asyncTaskCreationInfo Info on how to create the task * @param parentCommand The type of command issuing the task */ public static AsyncTask createAsyncTask( CommandBase<?> command, AsyncTaskCreationInfo asyncTaskCreationInfo, VdcActionType parentCommand) { return coco.createAsyncTask(command, asyncTaskCreationInfo, parentCommand); } /** * Fail the command associated with the task identified by the task id that has empty vdsm id and log the failure * with the specified message. * @param taskId the id of the async task in the database * @param message the message to be logged for the failure */ public static void logAndFailTaskOfCommandWithEmptyVdsmId(Guid taskId, String message) { getAsyncTaskManager().logAndFailTaskOfCommandWithEmptyVdsmId(taskId, message); } /** * Get the ids of the users executing the vdsm tasks. * @param tasksIDs The vdsm task ids being executed * @return The collection of user ids */ public static Collection<Guid> getUserIdsForVdsmTaskIds(ArrayList<Guid> tasksIDs) { return getAsyncTaskManager().getUserIdsForVdsmTaskIds(tasksIDs); } /** * Remove the async task identified the task id from the database. * @param taskId The task id of the async task in the database */ public static void removeTaskFromDbByTaskId(Guid taskId) { AsyncTaskManager.removeTaskFromDbByTaskId(taskId); } /** * Get the async task from the database identified by the asyncTaskId * @return The async task to be saved */ public static AsyncTask getAsyncTaskFromDb(Guid asyncTaskId) { return coco.getAsyncTaskFromDb(asyncTaskId); } /** * Save the async task in the database * @param asyncTask the async task to be saved in to the database */ public static void saveAsyncTaskToDb(AsyncTask asyncTask) { coco.saveAsyncTaskToDb(asyncTask); } /** * Remove the async task identified the task id from the database. * @param taskId The task id of the async task in the database * @return The number of rows updated in the database */ public static int callRemoveTaskFromDbByTaskId(Guid taskId) { return coco.removeTaskFromDbByTaskId(taskId); } /** * Save or update the async task in the database. * @param asyncTask The async task to be saved or updated */ public static void addOrUpdateTaskInDB(AsyncTask asyncTask) { coco.addOrUpdateTaskInDB(asyncTask); } /** * Persist the command entity in the database * @param cmdEntity The command entity to be persisted * @param cmdContext The CommandContext object associated with the command being persisted */ public static void persistCommand(CommandEntity cmdEntity, CommandContext cmdContext) { coco.persistCommand(cmdEntity, cmdContext); } /** * Persist the command related entities in the database */ public static void persistCommandAssociatedEntities(Guid cmdId, Collection<SubjectEntity> subjectEntities) { coco.persistCommandAssociatedEntities(buildCommandAssociatedEntities(cmdId, subjectEntities)); } private static Collection<CommandAssociatedEntity> buildCommandAssociatedEntities(Guid cmdId, Collection<SubjectEntity> subjectEntities) { if (subjectEntities.isEmpty()) { return Collections.emptySet(); } return subjectEntities.stream().map(subjectEntity -> new CommandAssociatedEntity(cmdId, subjectEntity.getEntityType(), subjectEntity.getEntityId())) .collect(Collectors.toSet()); } /** * Return the child command ids for the parent command identified by commandId * @param commandId The id of the parent command * @return The list of child command ids */ public static List<Guid> getChildCommandIds(Guid commandId) { return coco.getChildCommandIds(commandId); } /** * Return the child command ids for the parent command identified by commandId with the given action type and * status. * @param commandId The id of the parent command * @param childActionType The action type of the child command * @param status The status of the child command, can be null */ public static List<Guid> getChildCommandIds(Guid commandId, VdcActionType childActionType, CommandStatus status) { return coco.getChildCommandIds(commandId, childActionType, status); } /** * Return the command ids being executed by the user identified by engine session seq id. * @param engineSessionSeqId The id of the user's engine session */ public static List<Guid> getCommandIdsBySessionSeqId(long engineSessionSeqId) { return coco.getCommandIdsBySessionSeqId(engineSessionSeqId); } /** * Get the command entity for the command identified by the commandId * @param commandId The id of the command * @return The command entity for the command id */ public static CommandEntity getCommandEntity(Guid commandId) { return coco.getCommandEntity(commandId); } /** * Get the command object for the command identified by command id. * @param commandId The id of the command * @return The command */ @SuppressWarnings("unchecked") public static <C extends CommandBase<?>> C retrieveCommand(Guid commandId) { return (C) coco.retrieveCommand(commandId); } /** * Remove the command entity for the command identified by command id * @param commandId The id of the command */ public static void removeCommand(Guid commandId) { coco.removeCommand(commandId); } /** * Remove the command entities for the command and the command's child commands from the database * @param commandId The id of the command */ public static void removeAllCommandsInHierarchy(Guid commandId) { coco.removeAllCommandsInHierarchy(commandId); } /** * Remove all command entities whose creation date is before the cutoff * @param cutoff The cutoff date */ public static void removeAllCommandsBeforeDate(DateTime cutoff) { coco.removeAllCommandsBeforeDate(cutoff); } /** * Get the status of command identified by command id * @param commandId The id of the command * @return The status of the command */ public static CommandStatus getCommandStatus(Guid commandId) { return coco.getCommandStatus(commandId); } /** * Update the status of command identified by command id * @param commandId The id of the command * @param status The new status of the command */ public static void updateCommandStatus(Guid commandId, CommandStatus status) { coco.updateCommandStatus(commandId, status); } /** * Get the async task command execution status * @param commandId The id of the command * @return The async task command execution status */ public static CommandExecutionStatus getCommandExecutionStatus(Guid commandId) { CommandEntity cmdEntity = coco.getCommandEntity(commandId); return cmdEntity == null ? CommandExecutionStatus.UNKNOWN : cmdEntity.isExecuted() ? CommandExecutionStatus.EXECUTED : CommandExecutionStatus.NOT_EXECUTED; } /** * Returns the command entity's data for the command identified by the command id. * @param commandId The id of the command */ public static Map<String, Serializable> getCommandData(Guid commandId) { CommandEntity cmdEntity = coco.getCommandEntity(commandId); return cmdEntity == null ? new HashMap<>() : cmdEntity.getData(); } /** * Set the command entity's data for the command identified by the command id. * @param commandId The id of the command */ public static void updateCommandData(Guid commandId, Map<String, Serializable> data) { coco.updateCommandData(commandId, data); } /** * Set the command entity's executed status for the command identified by the command id. * @param commandId The id of the command */ public static void updateCommandExecuted(Guid commandId) { coco.updateCommandExecuted(commandId); } /** * Submit the command for asynchronous execution to the Command Executor thread pool. * @param actionType The action type of the command * @param parameters The parameters for the command * @param cmdContext The command context for the command * @return The future object for the command submitted to the thread pool */ public static Future<VdcReturnValueBase> executeAsyncCommand(VdcActionType actionType, VdcActionParametersBase parameters, CommandContext cmdContext) { return coco.executeAsyncCommand(actionType, parameters, cmdContext); } /** * Get the ids of the commands which are associated with the entity. * @param entityId The id of the entity * @return The list of command ids */ public static List<Guid> getCommandIdsByEntityId(Guid entityId) { return coco.getCommandIdsByEntityId(entityId); } /** * Get the associated entities for the command * @param cmdId The id of the entity * @return The list of associated entities */ public static List<CommandAssociatedEntity> getCommandAssociatedEntities(Guid cmdId) { return coco.getCommandAssociatedEntities(cmdId); } /** * Get the return value for the command identified by the command id. * @param cmdId The id of the command * @return The return value for the command */ public static VdcReturnValueBase getCommandReturnValue(Guid cmdId) { CommandEntity cmdEnity = coco.getCommandEntity(cmdId); return cmdEnity == null ? null : cmdEnity.getReturnValue(); } private static AsyncTaskManager getAsyncTaskManager() { return AsyncTaskManager.getInstance(coco); } /** * Subscribes the given command for an event by its given event key * * @param eventKey * the event key to subscribe * @param commandEntity * the subscribed command, which its callback will be invoked upon event */ public static void subscribe(String eventKey, CommandEntity commandEntity) { coco.subscribe(eventKey, commandEntity); } }