Exemple #1
0
def _build_task_from_command(cmd):
    if isinstance(cmd, wf_cmds.RunExistingTask):
        task = _create_task(
            cmd.wf_ex,
            cmd.wf_spec,
            spec_parser.get_task_spec(cmd.task_ex.spec),
            cmd.ctx,
            task_ex=cmd.task_ex,
            unique_key=cmd.task_ex.unique_key,
            waiting=cmd.task_ex.state == states.WAITING,
            triggered_by=cmd.triggered_by,
            rerun=cmd.rerun
        )

        if cmd.reset:
            task.reset()

        return task

    if isinstance(cmd, wf_cmds.RunTask):
        task = _create_task(
            cmd.wf_ex,
            cmd.wf_spec,
            cmd.task_spec,
            cmd.ctx,
            unique_key=cmd.unique_key,
            waiting=cmd.is_waiting(),
            triggered_by=cmd.triggered_by
        )

        return task

    raise exc.MistralError('Unsupported workflow command: %s' % cmd)
Exemple #2
0
    def schedule(self, input_dict, target, index=0, desc='', safe_rerun=False):
        assert not self.action_ex

        parent_wf_ex = self.task_ex.workflow_execution
        parent_wf_spec = spec_parser.get_workflow_spec_by_execution_id(
            parent_wf_ex.id)

        task_spec = spec_parser.get_task_spec(self.task_ex.spec)

        wf_spec_name = task_spec.get_workflow_name()

        wf_def = engine_utils.resolve_workflow_definition(
            parent_wf_ex.workflow_name, parent_wf_spec.get_name(),
            wf_spec_name)

        wf_spec = spec_parser.get_workflow_spec_by_definition_id(
            wf_def.id, wf_def.updated_at)

        wf_params = {'task_execution_id': self.task_ex.id, 'index': index}

        if 'env' in parent_wf_ex.params:
            wf_params['env'] = parent_wf_ex.params['env']
            wf_params['evaluate_env'] = parent_wf_ex.params.get('evaluate_env')

        for k, v in list(input_dict.items()):
            if k not in wf_spec.get_input():
                wf_params[k] = v
                del input_dict[k]

        wf_handler.start_workflow(wf_def.id, input_dict,
                                  "sub-workflow execution", wf_params)
Exemple #3
0
def _on_action_complete(action_ex):
    """Handles action completion event.

    :param action_ex: Action execution.
    """

    task_ex = action_ex.task_execution

    if not task_ex:
        return

    task_spec = spec_parser.get_task_spec(task_ex.spec)

    wf_ex = task_ex.workflow_execution

    task = _create_task(
        wf_ex, spec_parser.get_workflow_spec_by_execution_id(wf_ex.id),
        task_spec, task_ex.in_context, task_ex)

    try:
        task.on_action_complete(action_ex)
    except exc.MistralException as e:
        wf_ex = task_ex.workflow_execution

        msg = ("Failed to handle action completion [error=%s, wf=%s, task=%s,"
               " action=%s]:\n%s" %
               (e, wf_ex.name, task_ex.name, action_ex.name, tb.format_exc()))

        force_fail_task(task_ex, msg, task=task)

        return

    _check_affected_tasks(task)
Exemple #4
0
def _build_task_from_command(cmd):
    if isinstance(cmd, wf_cmds.RunExistingTask):
        task = _create_task(cmd.wf_ex,
                            cmd.wf_spec,
                            spec_parser.get_task_spec(cmd.task_ex.spec),
                            cmd.ctx,
                            task_ex=cmd.task_ex,
                            unique_key=cmd.task_ex.unique_key,
                            waiting=cmd.task_ex.state == states.WAITING,
                            triggered_by=cmd.triggered_by)

        if cmd.reset:
            task.reset()

        return task

    if isinstance(cmd, wf_cmds.RunTask):
        task = _create_task(cmd.wf_ex,
                            cmd.wf_spec,
                            cmd.task_spec,
                            cmd.ctx,
                            unique_key=cmd.unique_key,
                            waiting=cmd.is_waiting(),
                            triggered_by=cmd.triggered_by)

        return task

    raise exc.MistralError('Unsupported workflow command: %s' % cmd)
Exemple #5
0
    def put(self, id, task):
        """Update the specified task execution.

        :param id: Task execution ID.
        :param task: Task execution object.
        """
        acl.enforce('tasks:update', context.ctx())

        LOG.info("Update task execution [id=%s, task=%s]" % (id, task))

        with db_api.transaction():
            task_ex = db_api.get_task_execution(id)
            task_spec = spec_parser.get_task_spec(task_ex.spec)
            task_name = task.name or None
            reset = task.reset
            env = task.env or None

            if task_name and task_name != task_ex.name:
                raise exc.WorkflowException('Task name does not match.')

            wf_ex = db_api.get_workflow_execution(
                task_ex.workflow_execution_id
            )

        wf_name = task.workflow_name or None

        if wf_name and wf_name != wf_ex.name:
            raise exc.WorkflowException('Workflow name does not match.')

        if task.state != states.RUNNING:
            raise exc.WorkflowException(
                'Invalid task state. '
                'Only updating task to rerun is supported.'
            )

        if task_ex.state != states.ERROR:
            raise exc.WorkflowException(
                'The current task execution must be in ERROR for rerun.'
                ' Only updating task to rerun is supported.'
            )

        if not task_spec.get_with_items() and not reset:
            raise exc.WorkflowException(
                'Only with-items task has the option to not reset.'
            )

        rpc.get_engine_client().rerun_workflow(
            task_ex.id,
            reset=reset,
            env=env
        )

        with db_api.transaction():
            task_ex = db_api.get_task_execution(id)

            return _get_task_resource_with_result(task_ex)
Exemple #6
0
def _on_action_update(action_ex):
    """Handles action update event.

    :param action_ex: Action execution.
    """

    task_ex = action_ex.task_execution

    if not task_ex:
        return

    task_spec = spec_parser.get_task_spec(task_ex.spec)

    wf_ex = task_ex.workflow_execution

    task = _create_task(
        wf_ex,
        spec_parser.get_workflow_spec_by_execution_id(wf_ex.id),
        task_spec,
        task_ex.in_context,
        task_ex
    )

    try:
        task.on_action_update(action_ex)

        if states.is_paused(action_ex.state):
            wf_handler.pause_workflow(wf_ex)

        if states.is_running(action_ex.state):
            # If any subworkflow of the parent workflow is paused,
            # then keep the parent workflow execution paused.
            for task_ex in wf_ex.task_executions:
                if states.is_paused(task_ex.state):
                    return

            # Otherwise if no other subworkflow is paused,
            # then resume the parent workflow execution.
            wf_handler.resume_workflow(wf_ex)

    except exc.MistralException as e:
        wf_ex = task_ex.workflow_execution

        msg = ("Failed to handle action update [error=%s, wf=%s, task=%s,"
               " action=%s]:\n%s" %
               (e, wf_ex.name, task_ex.name, action_ex.name, tb.format_exc()))

        LOG.error(msg)

        task.set_state(states.ERROR, msg)

        wf_handler.force_fail_workflow(wf_ex, msg)

        return
    def __init__(self, wf_ex, wf_spec, task_ex, reset=True, triggered_by=None):
        super(RunExistingTask,
              self).__init__(wf_ex,
                             wf_spec,
                             spec_parser.get_task_spec(task_ex.spec),
                             task_ex.in_context,
                             triggered_by=triggered_by)

        self.task_ex = task_ex
        self.reset = reset
        self.unique_key = task_ex.unique_key
Exemple #8
0
def _on_action_update(action_ex):
    """Handles action update event.

    :param action_ex: Action execution.
    """

    task_ex = action_ex.task_execution

    if not task_ex:
        return

    task_spec = spec_parser.get_task_spec(task_ex.spec)

    wf_ex = task_ex.workflow_execution

    task = _create_task(
        wf_ex,
        spec_parser.get_workflow_spec_by_execution_id(wf_ex.id),
        task_spec,
        task_ex.in_context,
        task_ex
    )

    try:
        task.on_action_update(action_ex)

        if states.is_paused(action_ex.state):
            wf_handler.pause_workflow(wf_ex)

        if states.is_running(action_ex.state):
            # If any subworkflow of the parent workflow is paused,
            # then keep the parent workflow execution paused.
            for task_ex in wf_ex.task_executions:
                if states.is_paused(task_ex.state):
                    return

            # Otherwise if no other subworkflow is paused,
            # then resume the parent workflow execution.
            wf_handler.resume_workflow(wf_ex)

    except exc.MistralException as e:
        wf_ex = task_ex.workflow_execution

        msg = ("Failed to handle action update [error=%s, wf=%s, task=%s,"
               " action=%s]:\n%s" %
               (e, wf_ex.name, task_ex.name, action_ex.name, tb.format_exc()))

        force_fail_task(task_ex, msg, task=task)

        return

    _check_affected_tasks(task)
Exemple #9
0
        def _read_task_params(id, task):
            with db_api.transaction():
                task_ex = db_api.get_task_execution(id)
                task_spec = spec_parser.get_task_spec(task_ex.spec)
                task_name = task.name or None
                reset = task.reset
                env = task.env or None

                if task_name and task_name != task_ex.name:
                    raise exc.WorkflowException('Task name does not match.')

                wf_ex = db_api.get_workflow_execution(
                    task_ex.workflow_execution_id)

                return env, reset, task_ex, task_spec, wf_ex
Exemple #10
0
    def __init__(self, wf_ex, wf_spec, task_ex, reset=True, triggered_by=None,
                 handles_error=False, rerun=False):
        super(RunExistingTask, self).__init__(
            wf_ex,
            wf_spec,
            spec_parser.get_task_spec(task_ex.spec),
            task_ex.in_context,
            triggered_by=triggered_by,
            handles_error=handles_error
        )

        self.task_ex = task_ex
        self.reset = reset
        self.unique_key = task_ex.unique_key
        self.rerun = rerun
Exemple #11
0
def get_task_execution_result(task_ex):
    execs = task_ex.executions

    execs.sort(key=lambda x: x.runtime_context.get('index'))

    results = [
        _extract_execution_result(ex) for ex in execs
        if hasattr(ex, 'output') and ex.accepted
    ]

    # If it's a 'with-items' task we should always return an array.
    if spec_parser.get_task_spec(task_ex.spec).get_with_items():
        return results

    return results[0] if len(results) == 1 else results
Exemple #12
0
        def _read_task_params(id, task):
            with db_api.transaction():
                task_ex = db_api.get_task_execution(id)
                task_spec = spec_parser.get_task_spec(task_ex.spec)
                task_name = task.name or None
                reset = task.reset
                env = task.env or None

                if task_name and task_name != task_ex.name:
                    raise exc.WorkflowException('Task name does not match.')

                wf_ex = db_api.get_workflow_execution(
                    task_ex.workflow_execution_id
                )

                return env, reset, task_ex, task_spec, wf_ex
Exemple #13
0
def get_published_global(task_ex, wf_ex=None):
    if task_ex.state not in [states.SUCCESS, states.ERROR]:
        return

    if wf_ex is None:
        wf_ex = task_ex.workflow_execution

    expr_ctx = ContextView(get_current_task_dict(task_ex), task_ex.in_context,
                           get_workflow_environment_dict(wf_ex), wf_ex.context,
                           wf_ex.input)

    task_spec = spec_parser.get_task_spec(task_ex.spec)
    publish_spec = task_spec.get_publish(task_ex.state)

    if not publish_spec:
        return
    global_vars = publish_spec.get_global()
    return expr.evaluate_recursively(global_vars, expr_ctx)
Exemple #14
0
    def __init__(self,
                 wf_ex,
                 wf_spec,
                 task_ex,
                 reset=True,
                 triggered_by=None,
                 handles_error=False,
                 rerun=False):
        super(RunExistingTask,
              self).__init__(wf_ex,
                             wf_spec,
                             spec_parser.get_task_spec(task_ex.spec),
                             task_ex.in_context,
                             triggered_by=triggered_by,
                             handles_error=handles_error)

        self.task_ex = task_ex
        self.reset = reset
        self.unique_key = task_ex.unique_key
        self.rerun = rerun
Exemple #15
0
def get_task_execution_result(task_ex):
    execs = task_ex.executions
    execs.sort(key=lambda x: x.runtime_context.get('index'))

    results = [
        _extract_execution_result(ex) for ex in execs
        if hasattr(ex, 'output') and ex.accepted
    ]

    task_spec = spec_parser.get_task_spec(task_ex.spec)

    if task_spec.get_with_items():
        # TODO(rakhmerov): Smell: violation of 'with-items' encapsulation.
        with_items_ctx = task_ex.runtime_context.get('with_items')

        if with_items_ctx and with_items_ctx.get('count') > 0:
            return results
        else:
            return []

    return results[0] if len(results) == 1 else results
Exemple #16
0
def _on_action_complete(action_ex):
    """Handles action completion event.

    :param action_ex: Action execution.
    """

    task_ex = action_ex.task_execution

    if not task_ex:
        return

    task_spec = spec_parser.get_task_spec(task_ex.spec)

    wf_ex = task_ex.workflow_execution

    task = _create_task(
        wf_ex,
        spec_parser.get_workflow_spec_by_execution_id(wf_ex.id),
        task_spec,
        task_ex.in_context,
        task_ex
    )

    try:
        task.on_action_complete(action_ex)
    except exc.MistralException as e:
        wf_ex = task_ex.workflow_execution

        msg = ("Failed to handle action completion [error=%s, wf=%s, task=%s,"
               " action=%s]:\n%s" %
               (e, wf_ex.name, task_ex.name, action_ex.name, tb.format_exc()))

        force_fail_task(task_ex, msg, task=task)

        return

    _check_affected_tasks(task)
Exemple #17
0
def get_task_execution_result(task_ex):
    execs = task_ex.executions
    execs.sort(
        key=lambda x: x.runtime_context.get('index')
    )

    results = [
        _extract_execution_result(ex)
        for ex in execs
        if hasattr(ex, 'output') and ex.accepted
    ]

    task_spec = spec_parser.get_task_spec(task_ex.spec)

    if task_spec.get_with_items():
        # TODO(rakhmerov): Smell: violation of 'with-items' encapsulation.
        with_items_ctx = task_ex.runtime_context.get('with_items')

        if with_items_ctx and with_items_ctx.get('count') > 0:
            return results
        else:
            return []

    return results[0] if len(results) == 1 else results