Search in sources :

Example 1 with ProgramCounter

use of org.onosproject.workflow.api.ProgramCounter in project onos by opennetworkinglab.

the class WorkFlowEngine method execWorkflowContext.

/**
 * Executes workflow context.
 *
 * @param context workflow context
 * @return workflow context
 */
private WorkflowContext execWorkflowContext(WorkflowContext context) {
    Workflow workflow = workflowStore.get(context.workflowId());
    if (workflow == null) {
        log.error("Invalid workflow {}", context.workflowId());
        return null;
    }
    final WorkflowContext latestContext = workplaceStore.getContext(context.name());
    if (latestContext == null) {
        log.error("Invalid workflow context {}", context.name());
        return null;
    }
    initWorkletExecution(latestContext);
    try {
        final ProgramCounter pc = workflow.next(latestContext);
        final Worklet worklet = workflow.getWorkletInstance(pc);
        if (worklet == Worklet.Common.INIT) {
            log.error("workflow.next gave INIT. It cannot be executed (context: {})", context.name());
            return latestContext;
        }
        latestContext.setCurrent(pc);
        if (worklet == Worklet.Common.COMPLETED) {
            if (workflow.attributes().contains(REMOVE_AFTER_COMPLETE)) {
                workplaceStore.removeContext(latestContext.name());
                return null;
            } else {
                latestContext.setState(WorkflowState.IDLE);
                workplaceStore.commitContext(latestContext.name(), latestContext, false);
                return latestContext;
            }
        }
        log.info("{} worklet.process:{}", latestContext.name(), worklet.tag());
        log.trace("{} context: {}", latestContext.name(), latestContext);
        dataModelInjector.inject(worklet, latestContext);
        WorkletDescription workletDesc = workflow.getWorkletDesc(pc);
        if (Objects.nonNull(workletDesc)) {
            if (!(workletDesc.tag().equals("INIT") || workletDesc.tag().equals("COMPLETED"))) {
                staticDataModelInjector.inject(worklet, workletDesc);
            }
        }
        worklet.process(latestContext);
        dataModelInjector.inhale(worklet, latestContext);
        log.info("{} worklet.process(done): {}", latestContext.name(), worklet.tag());
        log.trace("{} context: {}", latestContext.name(), latestContext);
        if (latestContext.completionEventType() != null) {
            if (latestContext.completionEventGenerator() == null) {
                String msg = String.format("Invalid exepecting event(%s), generator(%s)", latestContext.completionEventType(), latestContext.completionEventGenerator());
                throw new WorkflowException(msg);
            }
            registerEventMap(latestContext.completionEventType(), latestContext.completionEventHints(), latestContext.name(), pc.toString());
            latestContext.completionEventGenerator().apply();
            if (latestContext.completionEventTimeout() != 0L) {
                final EventTimeoutTask eventTimeoutTask = EventTimeoutTask.builder().context(latestContext).programCounter(pc).eventType(latestContext.completionEventType().getName()).eventHintSet(latestContext.completionEventHints()).build();
                timerChain.schedule(latestContext.completionEventTimeout(), () -> {
                    eventtaskAccumulator.add(eventTimeoutTask);
                });
            }
        } else {
            if (latestContext.completionEventTimeout() != 0L) {
                final TimeoutTask timeoutTask = TimeoutTask.builder().context(latestContext).programCounter(pc).build();
                timerChain.schedule(latestContext.completionEventTimeout(), () -> {
                    eventtaskAccumulator.add(timeoutTask);
                });
            } else {
                // completed case
                // increase program counter
                latestContext.setCurrent(workflow.increased(pc));
            }
        }
        workplaceStore.commitContext(latestContext.name(), latestContext, latestContext.triggerNext());
    } catch (WorkflowException e) {
        log.error("Exception: ", e);
        latestContext.setCause(e.getMessage());
        latestContext.setState(WorkflowState.EXCEPTION);
        workplaceStore.commitContext(latestContext.name(), latestContext, false);
    } catch (StorageException e) {
        log.error("Exception: ", e);
    // StorageException does not commit context.
    } catch (Exception e) {
        log.error("Exception: ", e);
        latestContext.setCause(e.getMessage());
        latestContext.setState(WorkflowState.EXCEPTION);
        workplaceStore.commitContext(latestContext.name(), latestContext, false);
    }
    return latestContext;
}
Also used : WorkletDescription(org.onosproject.workflow.api.WorkletDescription) EventTimeoutTask(org.onosproject.workflow.api.EventTimeoutTask) WorkflowContext(org.onosproject.workflow.api.WorkflowContext) SystemWorkflowContext(org.onosproject.workflow.api.SystemWorkflowContext) WorkflowException(org.onosproject.workflow.api.WorkflowException) Workflow(org.onosproject.workflow.api.Workflow) Worklet(org.onosproject.workflow.api.Worklet) ProgramCounter(org.onosproject.workflow.api.ProgramCounter) StorageException(org.onosproject.store.service.StorageException) StorageException(org.onosproject.store.service.StorageException) WorkflowException(org.onosproject.workflow.api.WorkflowException) EventTimeoutTask(org.onosproject.workflow.api.EventTimeoutTask) TimeoutTask(org.onosproject.workflow.api.TimeoutTask)

Example 2 with ProgramCounter

use of org.onosproject.workflow.api.ProgramCounter in project onos by opennetworkinglab.

the class WorkflowManager method checkWorkflowDataModelSchema.

/**
 * Checks the schema of workflow data.
 *
 * @param workflow workflow
 * @param worklowDescJson jsonNode
 * @throws WorkflowException workflow exception
 */
private void checkWorkflowDataModelSchema(Workflow workflow, JsonNode worklowDescJson) throws WorkflowException {
    List<String> errors = new ArrayList<>();
    JsonNode dataNode = worklowDescJson.get("data");
    if (Objects.isNull(dataNode) || dataNode instanceof MissingNode) {
        errors.add("workflow description json does not have 'data'");
        throw new WorkflowDataModelException(workflow.id(), worklowDescJson, errors);
    }
    for (ProgramCounter pc : workflow.getProgram()) {
        Worklet worklet = workflow.getWorkletInstance(pc);
        if (Worklet.Common.COMPLETED.equals(worklet) || Worklet.Common.INIT.equals(worklet)) {
            continue;
        }
        Class cls = worklet.getClass();
        for (Field field : cls.getDeclaredFields()) {
            if (field.isSynthetic()) {
                continue;
            }
            for (Annotation annotation : field.getAnnotations()) {
                if (!(annotation instanceof JsonDataModel)) {
                    continue;
                }
                JsonDataModel jsonDataModel = (JsonDataModel) annotation;
                Matcher matcher = Pattern.compile("(\\w+)").matcher(jsonDataModel.path());
                if (!matcher.find()) {
                    throw new WorkflowException("Invalid Json Data Model Path(" + jsonDataModel.path() + ") in " + worklet.tag());
                }
                String path = matcher.group(1);
                Optional<String> optError = getJsonNodeDataError(dataNode, worklet, field, path, jsonDataModel.optional());
                if (optError.isPresent()) {
                    errors.add(optError.get());
                }
            }
        }
    }
    if (!errors.isEmpty()) {
        throw new WorkflowDataModelException(workflow.id(), worklowDescJson, errors);
    }
}
Also used : Matcher(java.util.regex.Matcher) WorkflowException(org.onosproject.workflow.api.WorkflowException) ArrayList(java.util.ArrayList) JsonNode(com.fasterxml.jackson.databind.JsonNode) MissingNode(com.fasterxml.jackson.databind.node.MissingNode) Worklet(org.onosproject.workflow.api.Worklet) WorkflowDataModelException(org.onosproject.workflow.api.WorkflowDataModelException) Annotation(java.lang.annotation.Annotation) Field(java.lang.reflect.Field) JsonDataModel(org.onosproject.workflow.api.JsonDataModel) ProgramCounter(org.onosproject.workflow.api.ProgramCounter)

Example 3 with ProgramCounter

use of org.onosproject.workflow.api.ProgramCounter in project onos by opennetworkinglab.

the class WorkFlowEngine method eventMapTrigger.

@Override
public void eventMapTrigger(Event event, EventHintSupplier supplier) {
    if (event.subject() instanceof SystemWorkflowContext) {
        return;
    }
    Map<String, String> eventMap;
    String eventHint;
    try {
        eventHint = supplier.apply(event);
    } catch (Throwable e) {
        log.error("Exception: ", e);
        return;
    }
    if (eventHint == null) {
        // do nothing
        log.error("Invalid eventHint, event: {}", event);
        return;
    }
    try {
        eventMap = eventMapStore.getEventMapByHint(event.getClass().getName(), eventHint);
    } catch (WorkflowException e) {
        log.error("Exception: ", e);
        return;
    }
    if (Objects.isNull(eventMap) || eventMap.isEmpty()) {
        // do nothing;
        log.debug("Invalid eventMap, event: {}", event);
        return;
    }
    for (Map.Entry<String, String> entry : eventMap.entrySet()) {
        String contextName = entry.getKey();
        String strProgramCounter = entry.getValue();
        ProgramCounter pc;
        try {
            pc = ProgramCounter.valueOf(strProgramCounter);
        } catch (IllegalArgumentException e) {
            log.error("Exception: ", e);
            return;
        }
        WorkflowContext context = workplaceStore.getContext(contextName);
        if (Objects.isNull(context)) {
            log.info("Invalid context: {}, event: {}", contextName, event);
            continue;
        }
        EventTask eventtask = null;
        try {
            eventtask = EventTask.builder().event(event).eventHint(eventHint).context(context).programCounter(pc).build();
        } catch (WorkflowException e) {
            log.error("Exception: ", e);
        }
        log.debug("eventtaskAccumulator.add: task: {}", eventtask);
        if (!Objects.isNull(eventtask)) {
            eventtaskAccumulator.add(eventtask);
        }
    }
}
Also used : SystemWorkflowContext(org.onosproject.workflow.api.SystemWorkflowContext) WorkflowException(org.onosproject.workflow.api.WorkflowException) WorkflowContext(org.onosproject.workflow.api.WorkflowContext) SystemWorkflowContext(org.onosproject.workflow.api.SystemWorkflowContext) ProgramCounter(org.onosproject.workflow.api.ProgramCounter) Map(java.util.Map) EventTask(org.onosproject.workflow.api.EventTask)

Example 4 with ProgramCounter

use of org.onosproject.workflow.api.ProgramCounter in project onos by opennetworkinglab.

the class WorkFlowEngine method execEventTask.

/**
 * Executes event task.
 *
 * @param task event task
 * @return event task
 */
private EventTask execEventTask(EventTask task) {
    if (!eventMapStore.isEventMapPresent(task.context().name())) {
        log.trace("EventMap doesnt exist for taskcontext:{}", task.context().name());
        return task;
    }
    log.debug("execEventTask- task: {}, hash: {}", task, stringHash(task.context().distributor()));
    WorkflowContext context = (WorkflowContext) (task.context());
    Workflow workflow = workflowStore.get(context.workflowId());
    if (workflow == null) {
        log.error("Invalid workflow {}", context.workflowId());
        return task;
    }
    WorkflowContext latestContext = workplaceStore.getContext(context.name());
    if (latestContext == null) {
        log.error("Invalid workflow context {}", context.name());
        return task;
    }
    try {
        if (!Objects.equals(latestContext.current(), task.programCounter())) {
            log.error("Current worklet({}) is not mismatched with task work({}). Ignored.", latestContext.current(), task.programCounter());
            return task;
        }
        Worklet worklet = workflow.getWorkletInstance(task.programCounter());
        if (Worklet.Common.COMPLETED.equals(worklet) || Worklet.Common.INIT.equals(worklet)) {
            log.error("Current worklet is {}, Ignored", worklet);
            return task;
        }
        initWorkletExecution(latestContext);
        log.info("{} worklet.isCompleted:{}", latestContext.name(), worklet.tag());
        log.trace("{} task:{}, context: {}", latestContext.name(), task, latestContext);
        dataModelInjector.inject(worklet, latestContext);
        boolean completed = worklet.isCompleted(latestContext, task.event());
        dataModelInjector.inhale(worklet, latestContext);
        if (completed) {
            log.info("{} worklet.isCompleted(true):{}", latestContext.name(), worklet.tag());
            log.trace("{} task:{}, context: {}", latestContext.name(), task, latestContext);
            eventMapStore.unregisterEventMap(task.eventType(), latestContext.name());
            // completed case
            // increase program counter
            ProgramCounter pc = latestContext.current();
            latestContext.setCurrent(workflow.increased(pc));
            workplaceStore.commitContext(latestContext.name(), latestContext, true);
            return null;
        } else {
            log.info("{} worklet.isCompleted(false):{}", latestContext.name(), worklet.tag());
            log.trace("{} task:{}, context: {}", latestContext.name(), task, latestContext);
            workplaceStore.commitContext(latestContext.name(), latestContext, false);
        }
    } catch (WorkflowException e) {
        log.error("Exception: ", e);
        latestContext.setCause(e.getMessage());
        latestContext.setState(WorkflowState.EXCEPTION);
        workplaceStore.commitContext(latestContext.name(), latestContext, false);
    } catch (StorageException e) {
        log.error("Exception: ", e);
    // StorageException does not commit context.
    } catch (Exception e) {
        log.error("Exception: ", e);
        latestContext.setCause(e.getMessage());
        latestContext.setState(WorkflowState.EXCEPTION);
        workplaceStore.commitContext(latestContext.name(), latestContext, false);
    }
    return task;
}
Also used : WorkflowContext(org.onosproject.workflow.api.WorkflowContext) SystemWorkflowContext(org.onosproject.workflow.api.SystemWorkflowContext) WorkflowException(org.onosproject.workflow.api.WorkflowException) Workflow(org.onosproject.workflow.api.Workflow) Worklet(org.onosproject.workflow.api.Worklet) ProgramCounter(org.onosproject.workflow.api.ProgramCounter) StorageException(org.onosproject.store.service.StorageException) StorageException(org.onosproject.store.service.StorageException) WorkflowException(org.onosproject.workflow.api.WorkflowException)

Example 5 with ProgramCounter

use of org.onosproject.workflow.api.ProgramCounter in project onos by opennetworkinglab.

the class WorkflowManager method checkWorkflow.

/**
 * Checks the validity of workflow definition.
 * @param workflow workflow to be checked
 * @throws WorkflowException workflow exception
 */
private void checkWorkflow(Workflow workflow) throws WorkflowException {
    Map<String, WorkletDataModelFieldDesc> descMap = new HashMap<>();
    List<String> errors = new ArrayList<>();
    for (ProgramCounter pc : workflow.getProgram()) {
        Worklet worklet = workflow.getWorkletInstance(pc);
        if (Worklet.Common.COMPLETED.equals(worklet) || Worklet.Common.INIT.equals(worklet)) {
            continue;
        }
        Class cls = worklet.getClass();
        for (Field field : cls.getDeclaredFields()) {
            if (field.isSynthetic()) {
                continue;
            }
            for (Annotation annotation : field.getAnnotations()) {
                if (!(annotation instanceof JsonDataModel)) {
                    continue;
                }
                JsonDataModel jsonDataModel = (JsonDataModel) annotation;
                Matcher matcher = Pattern.compile("(\\w+)").matcher(jsonDataModel.path());
                if (!matcher.find()) {
                    throw new WorkflowException("Invalid Json Data Model Path(" + jsonDataModel.path() + ") in " + worklet.tag());
                }
                String path = matcher.group(1);
                WorkletDataModelFieldDesc desc = new WorkletDataModelFieldDesc(pc.workletType(), path, field.getType(), jsonDataModel.optional());
                WorkletDataModelFieldDesc existing = descMap.get(path);
                if (Objects.isNull(existing)) {
                    descMap.put(path, desc);
                } else {
                    if (!desc.hasSameAttributes(existing)) {
                        errors.add("" + desc + " is conflicted with " + existing + " in workflow " + workflow.id());
                    }
                }
            }
        }
    }
    if (!errors.isEmpty()) {
        throw new WorkflowDefinitionException(workflow.id(), errors);
    }
}
Also used : HashMap(java.util.HashMap) Matcher(java.util.regex.Matcher) WorkflowException(org.onosproject.workflow.api.WorkflowException) ArrayList(java.util.ArrayList) Worklet(org.onosproject.workflow.api.Worklet) Annotation(java.lang.annotation.Annotation) WorkflowDefinitionException(org.onosproject.workflow.api.WorkflowDefinitionException) Field(java.lang.reflect.Field) JsonDataModel(org.onosproject.workflow.api.JsonDataModel) ProgramCounter(org.onosproject.workflow.api.ProgramCounter)

Aggregations

ProgramCounter (org.onosproject.workflow.api.ProgramCounter)5 WorkflowException (org.onosproject.workflow.api.WorkflowException)5 Worklet (org.onosproject.workflow.api.Worklet)4 SystemWorkflowContext (org.onosproject.workflow.api.SystemWorkflowContext)3 WorkflowContext (org.onosproject.workflow.api.WorkflowContext)3 Annotation (java.lang.annotation.Annotation)2 Field (java.lang.reflect.Field)2 ArrayList (java.util.ArrayList)2 Matcher (java.util.regex.Matcher)2 StorageException (org.onosproject.store.service.StorageException)2 JsonDataModel (org.onosproject.workflow.api.JsonDataModel)2 Workflow (org.onosproject.workflow.api.Workflow)2 JsonNode (com.fasterxml.jackson.databind.JsonNode)1 MissingNode (com.fasterxml.jackson.databind.node.MissingNode)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 EventTask (org.onosproject.workflow.api.EventTask)1 EventTimeoutTask (org.onosproject.workflow.api.EventTimeoutTask)1 TimeoutTask (org.onosproject.workflow.api.TimeoutTask)1 WorkflowDataModelException (org.onosproject.workflow.api.WorkflowDataModelException)1