use of cz.metacentrum.perun.taskslib.model.TaskResult in project perun by CESNET.
the class TaskScheduler method sendToEngine.
/**
* Send Task to Engine. Called when it waited long enough in a waiting queue (listening for other changes).
*
* @param task Task to be send to Engine
* @return Resulting state if Task was sent or denied or any error happened.
*/
protected TaskScheduled sendToEngine(Task task) {
Service service = task.getService();
Facility facility = task.getFacility();
try {
initPerunSession();
service = perun.getServicesManager().getServiceById(perunSession, service.getId());
facility = perun.getFacilitiesManager().getFacilityById(perunSession, facility.getId());
task.setService(service);
task.setFacility(facility);
} catch (ServiceNotExistsException e) {
log.error("[{}] Service for task does not exist...", task.getId());
task.setEndTime(LocalDateTime.now());
task.setStatus(TaskStatus.ERROR);
return DB_ERROR;
} catch (FacilityNotExistsException e) {
log.error("[{}] Facility for task does not exist...", task.getId());
task.setEndTime(LocalDateTime.now());
task.setStatus(TaskStatus.ERROR);
return DB_ERROR;
} catch (PrivilegeException e) {
log.error("[{}] Privilege error accessing the database: {}", task.getId(), e.getMessage());
task.setEndTime(LocalDateTime.now());
task.setStatus(TaskStatus.ERROR);
return DB_ERROR;
} catch (InternalErrorException e) {
log.error("[{}] Internal error: {}", task.getId(), e.getMessage());
task.setEndTime(LocalDateTime.now());
task.setStatus(TaskStatus.ERROR);
return DB_ERROR;
}
EngineMessageProducer engineMessageProducer = engineMessageProducerFactory.getProducer();
log.debug("[{}] Scheduling {}.", task.getId(), task);
if (engineMessageProducer != null) {
log.debug("[{}] Assigned queue {} to task.", task.getId(), engineMessageProducer.getQueueName());
} else {
log.error("[{}] There are no engines registered.", task.getId());
return QUEUE_ERROR;
}
if (service.isEnabled()) {
log.debug("[{}] Service {} is enabled globally.", task.getId(), service.getId());
} else {
log.debug("[{}] Service {} is disabled globally.", task.getId(), service.getId());
return DENIED;
}
try {
if (!((PerunBl) perun).getServicesManagerBl().isServiceBlockedOnFacility(service, facility)) {
log.debug("[{}] Service {} is allowed on Facility {}.", task.getId(), service.getId(), facility.getId());
} else {
log.debug("[{}] Service {} is blocked on Facility {}.", task.getId(), service.getId(), facility.getId());
return DENIED;
}
} catch (Exception e) {
log.error("[{}] Error getting disabled status for Service, task will not run now: {}.", task.getId(), e);
return ERROR;
}
// task|[task_id][is_forced][exec_service_id][facility]|[destination_list]|[dependency_list]
// - the task|[engine_id] part is added by dispatcherQueue
List<Destination> destinations = task.getDestinations();
if (task.isSourceUpdated() || destinations == null || destinations.isEmpty()) {
log.trace("[{}] No destinations for task, trying to query the database.", task.getId());
try {
initPerunSession();
destinations = perun.getServicesManager().getDestinations(perunSession, task.getService(), task.getFacility());
} catch (ServiceNotExistsException e) {
log.error("[{}] No destinations found for task. Service not exists...", task.getId());
task.setEndTime(LocalDateTime.now());
task.setStatus(TaskStatus.ERROR);
return DB_ERROR;
} catch (FacilityNotExistsException e) {
log.error("[{}] No destinations found for task. Facility for task does not exist...", task.getId());
task.setEndTime(LocalDateTime.now());
task.setStatus(TaskStatus.ERROR);
return DB_ERROR;
} catch (PrivilegeException e) {
log.error("[{}] No destinations found for task. Privilege error accessing the database: {}", task.getId(), e.getMessage());
task.setEndTime(LocalDateTime.now());
task.setStatus(TaskStatus.ERROR);
return DB_ERROR;
} catch (InternalErrorException e) {
log.error("[{}] No destinations found for task. Internal error: {}", task.getId(), e.getMessage());
task.setEndTime(LocalDateTime.now());
task.setStatus(TaskStatus.ERROR);
return DB_ERROR;
}
}
log.debug("[{}] Fetched destinations: {}", task.getId(), (destinations == null) ? "[]" : destinations.toString());
if (destinations != null && !destinations.isEmpty()) {
Iterator<Destination> iter = destinations.iterator();
while (iter.hasNext()) {
Destination dest = iter.next();
if (((PerunBl) perun).getServicesManagerBl().isServiceBlockedOnDestination(service, dest.getId())) {
// create fake task result to let admin know about the block
TaskResult result = new TaskResult();
result.setTaskId(task.getId());
result.setDestination(dest);
result.setDestinationId(dest.getId());
result.setService(service);
result.setStandardMessage("");
result.setErrorMessage("Destination is blocked in Perun.");
result.setReturnCode(1);
result.setId(0);
result.setTimestamp(new Date(System.currentTimeMillis()));
result.setStatus(TaskResult.TaskResultStatus.DENIED);
try {
schedulingPool.onTaskDestinationComplete(result);
} catch (Exception ex) {
log.warn("Couldn't store fake TaskResult about blocked destination.");
}
// actually remove from destinations sent to engine
iter.remove();
log.debug("[{}] Removed blocked destination: {}", task.getId(), dest.toString());
}
}
if (destinations.isEmpty()) {
// when service is blocked globally in Perun or on facility as a whole.
return DENIED;
}
}
task.setDestinations(destinations);
// construct JMS message for Engine
StringBuilder destinations_s = new StringBuilder("Destinations [");
if (destinations != null) {
for (Destination destination : destinations) {
destinations_s.append(destination.serializeToString()).append(", ");
}
}
destinations_s.append("]");
// send message async
engineMessageProducer.sendMessage("[" + task.getId() + "][" + task.isPropagationForced() + "]|[" + fixStringSeparators(task.getService().serializeToString()) + "]|[" + fixStringSeparators(task.getFacility().serializeToString()) + "]|[" + fixStringSeparators(destinations_s.toString()) + "]");
// modify task status and reset forced flag
task.setSentToEngine(LocalDateTime.now());
task.setStatus(Task.TaskStatus.PLANNED);
task.setPropagationForced(false);
return SUCCESS;
}
use of cz.metacentrum.perun.taskslib.model.TaskResult in project perun by CESNET.
the class SchedulingPoolImpl method onTaskDestinationComplete.
@Override
public void onTaskDestinationComplete(String string) {
if (string == null || string.isEmpty()) {
log.error("Could not parse TaskResult message from Engine.");
return;
}
try {
List<PerunBean> listOfBeans = AuditParser.parseLog(string);
if (!listOfBeans.isEmpty()) {
TaskResult taskResult = (TaskResult) listOfBeans.get(0);
log.debug("[{}] Received TaskResult for Task from Engine.", taskResult.getTaskId());
onTaskDestinationComplete(taskResult);
} else {
log.error("No TaskResult found in message from Engine: {}.", string);
}
} catch (Exception e) {
log.error("Could not save TaskResult from Engine {}, {}", string, e.getMessage());
}
}
use of cz.metacentrum.perun.taskslib.model.TaskResult in project perun by CESNET.
the class TasksManagerEntry method deleteTaskResultById.
@Override
public void deleteTaskResultById(PerunSession sess, int taskResultId) throws PrivilegeException {
TaskResult result = tasksManagerBl.getTaskResultById(sess, taskResultId);
Task task = tasksManagerBl.getTaskById(sess, result.getTaskId());
Facility facility = task.getFacility();
if (!AuthzResolver.authorizedInternal(sess, "deleteTaskResultById_int_policy", facility)) {
throw new PrivilegeException(sess, "deleteTaskResults");
}
tasksManagerBl.deleteTaskResultById(sess, result.getId());
}
use of cz.metacentrum.perun.taskslib.model.TaskResult in project perun by CESNET.
the class ServicesManagerBlImpl method deleteDestination.
@Override
public void deleteDestination(PerunSession sess, Destination destination) throws DestinationAlreadyRemovedException, RelationExistsException {
List<Service> services = getServicesManagerImpl().getServicesFromDestination(destination.getId());
if (!services.isEmpty()) {
throw new RelationExistsException("Destination is used by some services and facilities.");
}
// remove task results of destination
List<TaskResult> taskResults = getPerunBl().getTasksManagerBl().getTaskResultsByDestinations(sess, Collections.singletonList(destination.getDestination()));
for (TaskResult taskResult : taskResults) {
getPerunBl().getTasksManagerBl().deleteTaskResultById(sess, taskResult.getId());
}
// remove all service denials on destination
this.unblockAllServicesOnDestination(sess, destination.getId());
getServicesManagerImpl().deleteDestination(sess, destination);
}
use of cz.metacentrum.perun.taskslib.model.TaskResult in project perun by CESNET.
the class PropagationMaintainerImpl method endStuckTasks.
// ----- methods ------------------------------
public void endStuckTasks() {
// handle stuck GEN tasks
for (Map.Entry<Future<Task>, Task> generatingTask : generatingTasks.getRunningTasks().entrySet()) {
Task task = generatingTask.getValue();
Future<Task> future = generatingTask.getKey();
LocalDateTime startTime = task.getGenStartTime();
long howManyMinutesAgo = 0;
if (startTime != null) {
howManyMinutesAgo = ChronoUnit.MINUTES.between(startTime, LocalDateTime.now());
}
if (startTime == null) {
// by implementation can't happen, we set time before adding to the generatingTasksMap
log.error("[{}] Task in generatingTasks has no start time. Shouldn't happen by implementation.", task.getId());
} else if (howManyMinutesAgo >= rescheduleTime) {
if (!future.isCancelled()) {
// Cancel running GEN Task - we expect that it will be picked by GenCollector
// and removed from the Engine.
log.debug("[{}] Cancelling stuck generating Future<Task>.", task.getId());
future.cancel(true);
} else {
// We cancelled Task in previous run, but it wasn't picked by GenCollector
// GenCollector probably doesn't run -> abort task manually
log.debug("[{}] Cancelled stuck generating Future<Task> was not picked by GenCollector, forcefully removing from Engine.", task.getId());
// to release semaphore
generatingTasks.removeStuckTask(future);
abortTask(task, TaskStatus.GENERROR);
}
}
}
// handle stuck SEND tasks
for (Map.Entry<Future<SendTask>, SendTask> sendingSendTask : sendingSendTasks.getRunningTasks().entrySet()) {
SendTask sendTask = sendingSendTask.getValue();
Future<SendTask> future = sendingSendTask.getKey();
Task task = sendTask.getTask();
Date startTime = sendTask.getStartTime();
int howManyMinutesAgo = 0;
if (startTime != null) {
howManyMinutesAgo = (int) (System.currentTimeMillis() - startTime.getTime()) / 1000 / 60;
}
if (startTime == null) {
// by implementation can't happen, we set time before adding to the generatingTasksMap
log.error("[{}] SendTask in sendingSendTask has no start time for Destination {}. Shouldn't happen by implementation.", task.getId(), sendTask.getDestination());
} else if (howManyMinutesAgo >= rescheduleTime) {
sendTask.setStatus(SendTaskStatus.ERROR);
if (!future.isCancelled()) {
// Cancel running Send Task - we expect that it will be picked by SendCollector
// and removed from the Engine if all SendTasks are done
log.debug("[{}] Cancelling stuck sending Future<SendTask> for Destination: {}.", task.getId(), sendTask.getDestination());
future.cancel(true);
} else {
log.debug("[{}] Cancelled stuck sending Future<SendTask> for Destination: {} was not picked by SendCollector, forcefully removing from Engine.", task.getId(), sendTask.getDestination());
// We cancelled Task in previous run, but it wasn't picked by SendCollector
// SendCollector probably doesn't run
// to release semaphore
sendingSendTasks.removeStuckTask(future);
// make sure Task is switched to SENDERROR
task.setSendEndTime(LocalDateTime.now());
task.setStatus(TaskStatus.SENDERROR);
// report result
TaskResult taskResult = null;
try {
taskResult = schedulingPool.createTaskResult(task.getId(), sendTask.getDestination().getId(), sendTask.getStderr(), sendTask.getStdout(), sendTask.getReturnCode(), task.getService());
jmsQueueManager.reportTaskResult(taskResult);
} catch (JMSException | InterruptedException e) {
log.error("[{}] Error trying to reportTaskResult {} of {} to Dispatcher: {}", task.getId(), taskResult, task, e);
}
// lower counter for stuck SendTask if count <= 1 remove from Engine
try {
schedulingPool.decreaseSendTaskCount(task, 1);
} catch (TaskStoreException e) {
log.error("[{}] Task {} could not be removed from SchedulingPool: {}", task.getId(), task, e);
}
}
}
}
// check all known Tasks
Collection<Task> allTasks = schedulingPool.getAllTasks();
if (allTasks == null) {
return;
}
for (Task task : allTasks) {
switch(task.getStatus()) {
case WAITING:
/*
Such Tasks should never be in Engine, (only in Dispatcher) since when they are sent to Engine,
status is set to PLANNED in both components. If they are already present in SchedulingPool
(Engine), then adding of new (same) Task is skipped and previous processing is finished first.
=> just remove such nonsense from SchedulingPool and don't spam Dispatcher
*/
try {
// TODO - can such Task be in any structure like generating/sending/newTasks/generatedTasks ?
schedulingPool.removeTask(task.getId());
log.warn("[{}] Task in WAITING state shouldn't be in Engine at all, silently removing from SchedulingPool.", task.getId());
} catch (TaskStoreException ex) {
log.error("[{}] Failed during removal of WAITING Task from SchedulingPool. Such Task shouldn't be in Engine at all: {}", task.getId(), ex);
}
case PLANNED:
/*
Check tasks, that should be put to scheduling pool by EventProcessorImpl and taken by GenPlanner.
Tasks might be like that, because adding to BlockingDeque has limit on Integer#MAX_SIZE
(while EventProcessorImpl adds Task to the scheduling pool).
Also if GenPlanner implementation fails it might take Task from the BlockingDeque but doesn't change
its status or doesn't put it between generatingTasks.
*/
BlockingDeque<Task> newTasks = schedulingPool.getNewTasksQueue();
if (!newTasks.contains(task)) {
try {
log.debug("[{}] Re-adding PLANNED Task back to pool and newTasks queue. Probably GenPlanner failed.", task.getId());
schedulingPool.addTask(task);
} catch (TaskStoreException e) {
log.error("Could not save Task {} into Engine SchedulingPool because of {}, setting to ERROR", task, e);
abortTask(task, TaskStatus.ERROR);
}
}
break;
case GENERATING:
/*
This is basically the same check as for the GENERATING Tasks above,
but now for Tasks missing in "generatingTasks".
!! We can't abort GENERATING Tasks with startTime=NULL here,
because they are waiting to be started at genCompletionService#blockingSubmit() !!
*/
LocalDateTime startTime = task.getGenStartTime();
long howManyMinutesAgo = 0;
if (startTime != null) {
howManyMinutesAgo = ChronoUnit.MINUTES.between(startTime, LocalDateTime.now());
}
// somebody probably wrongly manipulated the structure
if (howManyMinutesAgo >= rescheduleTime && !generatingTasks.getRunningTasks().values().contains(task)) {
// probably GenCollector failed to pick task -> abort
abortTask(task, TaskStatus.GENERROR);
}
break;
case GENERROR:
case GENERATED:
/*
Check Tasks, which should be processed by GenCollector and taken by SendPlanner or reported as GENERROR to Dispatcher.
Task must have endTime set by GenWorker, otherwise it failed completely and should be reported as error.
If either of GenCollector and SendPlanner fails to process generated tasks, it's missing in generatedTasksQueue.
*/
LocalDateTime genEndTime = task.getGenEndTime();
howManyMinutesAgo = 0;
if (genEndTime != null) {
howManyMinutesAgo = ChronoUnit.MINUTES.between(genEndTime, LocalDateTime.now());
}
// If too much time has passed for Task and its not present in generatedTasksQueue, something is broken
if ((genEndTime == null || howManyMinutesAgo >= rescheduleTime) && !schedulingPool.getGeneratedTasksQueue().contains(task)) {
abortTask(task, TaskStatus.GENERROR);
}
break;
case SENDING:
// TODO since Task is switched to SENDING before blockingSubmit() of any SendWorker.
break;
case WARNING:
case SENDERROR:
LocalDateTime endTime = task.getSendEndTime();
howManyMinutesAgo = 0;
if (endTime != null) {
howManyMinutesAgo = ChronoUnit.MINUTES.between(endTime, LocalDateTime.now());
}
// If too much time has passed something is broken
if (endTime == null || howManyMinutesAgo >= rescheduleTime) {
abortTask(task, TaskStatus.SENDERROR);
}
break;
case ERROR:
break;
case DONE:
default:
// unknown state
log.debug("[{}] Failing to default, status was: {}", task.getId(), task.getStatus());
abortTask(task, TaskStatus.ERROR);
}
}
}
Aggregations