Пример #1
0
    def handle_task(self, cntx, **kwargs):
        """Handle the execution of the workbook task.

        :param cntx: a request context dict
        :type cntx: dict
        :param kwargs: a dict of method arguments
        :type kwargs: dict
        """
        try:
            task = kwargs.get('task', None)
            if not task:
                raise Exception('No task is provided to the executor.')
            LOG.info("Received a task: %s" % task)

            db_task = db_api.task_get(task['workbook_name'],
                                      task['execution_id'],
                                      task['id'])
            db_exec = db_api.execution_get(task['workbook_name'],
                                           task['execution_id'])

            if not db_exec or not db_task:
                return

            if db_exec['state'] != states.RUNNING or \
                    db_task['state'] != states.IDLE:
                return

            self._do_task_action(db_task)
            db_api.task_update(task['workbook_name'],
                               task['execution_id'],
                               task['id'],
                               {'state': states.RUNNING})
        except Exception as exc:
            LOG.exception(exc)
            self._handle_task_error(task, exc)
Пример #2
0
    def _run_task(cls, task):
        action = a_f.create_action(task)

        LOG.info("Task is started - %s" % task['name'])

        if a_h.is_task_synchronous(task):
            try:
                state, result = states.SUCCESS, action.run()
            except exc.ActionException:
                state, result = states.ERROR, None

            cls.convey_task_result(task['workbook_name'],
                                   task['execution_id'],
                                   task['id'],
                                   state, result)
        else:
            try:
                action.run()

                db_api.task_update(task['workbook_name'],
                                   task['execution_id'],
                                   task['id'],
                                   {'state': states.RUNNING})
            except exc.ActionException:
                cls.convey_task_result(task['workbook_name'],
                                       task['execution_id'],
                                       task['id'],
                                       states.ERROR, None)
Пример #3
0
def prepare_tasks(tasks, context):
    for task in tasks:
        # TODO(rakhmerov): Inbound context should be a merge of outbound
        # contexts of task dependencies, if any.
        task['in_context'] = context
        task['parameters'] = evaluate_task_parameters(task, context)

        db_api.task_update(task['workbook_name'],
                           task['execution_id'],
                           task['id'],
                           {'in_context': task['in_context'],
                            'parameters': task['parameters']})
Пример #4
0
        def run_delayed_task():
            """
            Runs the delayed task. Performs all the steps required to setup
            a task to run which are not already done. This is mostly code
            copied over from convey_task_result.
            """
            db_api.start_tx()
            try:
                workbook_name = task['workbook_name']
                execution_id = task['execution_id']
                execution = db_api.execution_get(workbook_name, execution_id)

                # Change state from DELAYED to IDLE to unblock processing.

                WORKFLOW_TRACE.info("Task '%s' [%s -> %s]"
                                    % (task['name'],
                                       task['state'], states.IDLE))

                db_task = db_api.task_update(workbook_name,
                                             execution_id,
                                             task['id'],
                                             {"state": states.IDLE})
                task_to_start = [db_task]
                data_flow.prepare_tasks(task_to_start, outbound_context)
                db_api.commit_tx()
            finally:
                db_api.end_tx()

            if not states.is_stopped_or_finished(execution["state"]):
                cls._run_tasks(task_to_start)
Пример #5
0
    def _update_task(cls, workbook, task, state, task_output):
        """
        Update the task with the runtime information. The outbound_context
        for this task is also calculated.
        :return: task, outbound_context. task is the updated task and
        computed outbound context.
        """
        workbook_name = task['workbook_name']
        execution_id = task['execution_id']
        task_spec = workbook.tasks.get(task["name"])
        task_runtime_context = task["task_runtime_context"]

        # Compute the outbound_context, state and exec_flow_context.
        outbound_context = data_flow.get_outbound_context(task, task_output)
        state, task_runtime_context = retry.get_task_runtime(
            task_spec, state, outbound_context, task_runtime_context)

        # Update the task.
        update_values = {"state": state,
                         "output": task_output,
                         "task_runtime_context": task_runtime_context}
        task = db_api.task_update(workbook_name, execution_id, task["id"],
                                  update_values)

        return task, outbound_context
Пример #6
0
        def run_delayed_task():
            """
            Runs the delayed task. Performs all the steps required to setup
            a task to run which are not already done. This is mostly code
            copied over from convey_task_result.
            """
            db_api.start_tx()
            try:
                workbook_name = task['workbook_name']
                execution_id = task['execution_id']
                execution = db_api.execution_get(workbook_name, execution_id)

                # Change state from DELAYED to IDLE to unblock processing.

                WORKFLOW_TRACE.info("Task '%s' [%s -> %s]" %
                                    (task['name'], task['state'], states.IDLE))

                db_task = db_api.task_update(workbook_name, execution_id,
                                             task['id'],
                                             {"state": states.IDLE})
                task_to_start = [db_task]
                data_flow.prepare_tasks(task_to_start, outbound_context)
                db_api.commit_tx()
            finally:
                db_api.end_tx()

            if not states.is_stopped_or_finished(execution["state"]):
                cls._run_tasks(task_to_start)
Пример #7
0
    def _update_task(cls, workbook, task, state, task_output):
        """
        Update the task with the runtime information. The outbound_context
        for this task is also calculated.
        :return: task, outbound_context. task is the updated task and
        computed outbound context.
        """
        workbook_name = task['workbook_name']
        execution_id = task['execution_id']
        task_spec = workbook.tasks.get(task["name"])
        task_runtime_context = task["task_runtime_context"]

        # Compute the outbound_context, state and exec_flow_context.
        outbound_context = data_flow.get_outbound_context(task, task_output)
        state, task_runtime_context = retry.get_task_runtime(
            task_spec, state, outbound_context, task_runtime_context)

        # Update the task.
        update_values = {
            "state": state,
            "output": task_output,
            "task_runtime_context": task_runtime_context
        }
        task = db_api.task_update(workbook_name, execution_id, task["id"],
                                  update_values)

        return task, outbound_context
Пример #8
0
def prepare_tasks(tasks, context, workbook):
    results = []

    for task in tasks:
        # TODO(rakhmerov): Inbound context should be a merge of
        # outbound contexts of task dependencies, if any.
        action_params = evaluate_task_parameters(task, context)

        db_api.task_update(task['id'],
                           {'state': states.RUNNING,
                            'in_context': context,
                            'parameters': action_params})

        # Get action name. Unwrap ad-hoc and reevaluate params if
        # necessary.
        action_name = wb_task.TaskSpec(task['task_spec'])\
            .get_full_action_name()

        openstack_ctx = context.get('openstack')

        if not a_f.get_action_class(action_name):
            # If action is not found in registered actions try to find
            # ad-hoc action definition.
            if openstack_ctx is not None:
                action_params.update({'openstack': openstack_ctx})

            action = a_f.resolve_adhoc_action_name(workbook, action_name)

            if not action:
                msg = 'Unknown action [workbook=%s, action=%s]' % \
                      (workbook, action_name)
                raise exc.ActionException(msg)

            action_params = a_f.convert_adhoc_action_params(workbook,
                                                            action_name,
                                                            action_params)
            action_name = action

        if _has_action_context_param(a_f.get_action_class(action_name)):
            action_params[_ACTION_CTX_PARAM] = \
                _get_action_context(task, openstack_ctx)

        results.append((task['id'], action_name, action_params))

    return results
Пример #9
0
    def handle_task(self, cntx, **kwargs):
        """Handle the execution of the workbook task.

        :param cntx: a request context dict
        :type cntx: dict
        :param kwargs: a dict of method arguments
        :type kwargs: dict
        """
        try:
            task = kwargs.get('task', None)
            if not task:
                raise Exception('No task is provided to the executor.')

            LOG.info("Received a task: %s" % task)

            db_task = db_api.task_get(task['workbook_name'],
                                      task['execution_id'],
                                      task['id'])
            db_exec = db_api.execution_get(task['workbook_name'],
                                           task['execution_id'])

            if not db_exec or not db_task:
                return

            if db_exec['state'] != states.RUNNING or \
                    db_task['state'] != states.IDLE:
                return

            # Update the state to running before performing action. The
            # do_task_action assigns state to the task which is the appropriate
            # value to preserve.

            WORKFLOW_TRACE.info("Task '%s' [%s -> %s]" % (db_task['name'],
                                                          db_task['state'],
                                                          states.RUNNING))

            db_api.task_update(task['workbook_name'],
                               task['execution_id'],
                               task['id'],
                               {'state': states.RUNNING})

            self._do_task_action(db_task)
        except Exception as e:
            LOG.exception(e)
            self._handle_task_error(task, e)
Пример #10
0
    def handle_task(self, cntx, **kwargs):
        """Handle the execution of the workbook task.

        :param cntx: a request context dict
        :type cntx: dict
        :param kwargs: a dict of method arguments
        :type kwargs: dict
        """
        try:
            task = kwargs.get('task', None)
            if not task:
                raise Exception('No task is provided to the executor.')

            LOG.info("Received a task: %s" % task)

            db_task = db_api.task_get(task['workbook_name'],
                                      task['execution_id'], task['id'])
            db_exec = db_api.execution_get(task['workbook_name'],
                                           task['execution_id'])

            if not db_exec or not db_task:
                return

            if db_exec['state'] != states.RUNNING or \
                    db_task['state'] != states.IDLE:
                return

            # Update the state to running before performing action. The
            # do_task_action assigns state to the task which is the appropriate
            # value to preserve.

            WORKFLOW_TRACE.info(
                "Task '%s' [%s -> %s]" %
                (db_task['name'], db_task['state'], states.RUNNING))

            db_api.task_update(task['workbook_name'], task['execution_id'],
                               task['id'], {'state': states.RUNNING})

            self._do_task_action(db_task)
        except Exception as e:
            LOG.exception(e)
            self._handle_task_error(task, e)
Пример #11
0
    def _handle_task_error(self, task, exception):
        """Handle exception from the task execution.

        :param task: the task corresponding to the exception
        :type task: dict
        :param exception: an exception thrown during the execution of the task
        :type exception: Exception
        """
        try:
            db_api.start_tx()
            try:
                db_api.execution_update(task['execution_id'],
                                        {'state': states.ERROR})
                db_api.task_update(task['id'],
                                   {'state': states.ERROR})
                db_api.commit_tx()
            finally:
                db_api.end_tx()
        except Exception as e:
            LOG.exception(e)
Пример #12
0
    def convey_task_result(cls, workbook_name, execution_id,
                           task_id, state, result):
        db_api.start_tx()

        workbook = cls._get_workbook(workbook_name)
        try:
            #TODO(rakhmerov): validate state transition
            task = db_api.task_get(workbook_name, execution_id, task_id)

            task_output = data_flow.get_task_output(task, result)

            # Update task state.
            task = db_api.task_update(workbook_name, execution_id, task_id,
                                      {"state": state, "output": task_output})

            execution = db_api.execution_get(workbook_name, execution_id)

            # Calculate task outbound context.
            outbound_context = data_flow.get_outbound_context(task)

            cls._create_next_tasks(task, workbook)

            # Determine what tasks need to be started.
            tasks = db_api.tasks_get(workbook_name, execution_id)

            new_exec_state = cls._determine_execution_state(execution, tasks)

            if execution['state'] != new_exec_state:
                execution = \
                    db_api.execution_update(workbook_name, execution_id, {
                        "state": new_exec_state
                    })

                LOG.info("Changed execution state: %s" % execution)

            tasks_to_start = workflow.find_resolved_tasks(tasks)

            data_flow.prepare_tasks(tasks_to_start, outbound_context)

            db_api.commit_tx()
        except Exception as e:
            raise exc.EngineException("Failed to create necessary DB objects:"
                                      " %s" % e)
        finally:
            db_api.end_tx()

        if states.is_stopped_or_finished(execution["state"]):
            return task

        if tasks_to_start:
            cls._run_tasks(tasks_to_start)

        return task
Пример #13
0
    def _handle_task_error(self, task, exception):
        """Handle exception from the task execution.

        :param task: the task corresponding to the exception
        :type task: dict
        :param exception: an exception thrown during the execution of the task
        :type exception: Exception
        """
        try:
            db_api.start_tx()
            try:
                db_api.execution_update(task['workbook_name'],
                                        task['execution_id'],
                                        {'state': states.ERROR})
                db_api.task_update(task['workbook_name'], task['execution_id'],
                                   task['id'], {'state': states.ERROR})
                db_api.commit_tx()
            finally:
                db_api.end_tx()
        except Exception as e:
            LOG.exception(e)
Пример #14
0
    def _do_task_action(self, task):
        """Executes the action defined by the task and return result.

        :param task: a task definition
        :type task: dict
        """
        LOG.info("Starting task action [task_id=%s, "
                 "action='%s', service='%s'" %
                 (task['id'], task['task_spec']['action'],
                  task['service_spec']))

        action = a_f.create_action(task)

        if a_h.is_task_synchronous(task):
            try:
                state, result = states.SUCCESS, action.run()
            except exc.ActionException:
                state, result = states.ERROR, None

            engine.convey_task_result(task['workbook_name'],
                                      task['execution_id'],
                                      task['id'],
                                      state, result)
        else:
            try:
                action.run()

                db_api.task_update(task['workbook_name'],
                                   task['execution_id'],
                                   task['id'],
                                   {'state': states.RUNNING})
            except exc.ActionException:
                engine.convey_task_result(task['workbook_name'],
                                          task['execution_id'],
                                          task['id'],
                                          states.ERROR, None)