コード例 #1
0
ファイル: executions.py プロジェクト: lyandut/st2
def abandon_execution_if_incomplete(liveaction_id, publish=True):
    """
    Marks execution as abandoned if it is still incomplete. Abandoning an
    execution implies that its end state is unknown and cannot anylonger
    be determined. This method should only be called if the owning process
    is certain it can no longer determine status of an execution.
    """
    liveaction_db = action_utils.get_liveaction_by_id(liveaction_id)

    # No need to abandon and already complete action
    if liveaction_db.status in action_constants.LIVEACTION_COMPLETED_STATES:
        raise ValueError('LiveAction %s already in a completed state %s.' %
                         (liveaction_id, liveaction_db.status))

    # Update status to reflect execution being abandoned.
    liveaction_db = action_utils.update_liveaction_status(
        status=action_constants.LIVEACTION_STATUS_ABANDONED,
        liveaction_db=liveaction_db,
        result={})

    execution_db = update_execution(liveaction_db, publish=publish)

    LOG.info('Marked execution %s as %s.', execution_db.id,
             action_constants.LIVEACTION_STATUS_ABANDONED)

    # Invoke post run on the action to execute post run operations such as callback.
    runners_utils.invoke_post_run(liveaction_db)

    return execution_db
コード例 #2
0
ファイル: executions.py プロジェクト: ssubbanna/st2_test
def abandon_execution_if_incomplete(liveaction_id, publish=True):
    """
    Marks execution as abandoned if it is still incomplete. Abandoning an
    execution implies that its end state is unknown and cannot anylonger
    be determined. This method should only be called if the owning process
    is certain it can no longer determine status of an execution.
    """
    liveaction_db = action_utils.get_liveaction_by_id(liveaction_id)

    # No need to abandon and already complete action
    if liveaction_db.status in action_constants.LIVEACTION_COMPLETED_STATES:
        raise ValueError('LiveAction %s already in a completed state %s.' %
                         (liveaction_id, liveaction_db.status))

    # Update status to reflect execution being abandoned.
    liveaction_db = action_utils.update_liveaction_status(
        status=action_constants.LIVEACTION_STATUS_ABANDONED,
        liveaction_db=liveaction_db,
        result={})

    execution_db = update_execution(liveaction_db, publish=publish)

    LOG.info('Marked execution %s as %s.', execution_db.id,
             action_constants.LIVEACTION_STATUS_ABANDONED)

    # Invoke post run on the action to execute post run operations such as callback.
    runners_utils.invoke_post_run(liveaction_db)

    return execution_db
コード例 #3
0
def purge_inquiries(logger):
    """Purge Inquiries that have exceeded their configured TTL

    At the moment, Inquiries do not have their own database model, so this function effectively
    is another, more specialized GC for executions. It will look for executions with a 'pending'
    status that use the 'inquirer' runner, which is the current definition for an Inquiry.

    Then it will mark those that have a nonzero TTL have existed longer than their TTL as
    "timed out". It will then request that the parent workflow(s) resume, where the failure
    can be handled as the user desires.
    """

    # Get all existing Inquiries
    filters = {'runner__name': 'inquirer', 'status': action_constants.LIVEACTION_STATUS_PENDING}
    inquiries = list(ActionExecution.query(**filters))

    gc_count = 0

    # Inspect each Inquiry, and determine if TTL is expired
    for inquiry in inquiries:

        ttl = int(inquiry.result.get('ttl'))
        if ttl <= 0:
            logger.debug("Inquiry %s has a TTL of %s. Skipping." % (inquiry.id, ttl))
            continue

        min_since_creation = int(
            (get_datetime_utc_now() - inquiry.start_timestamp).total_seconds() / 60
        )

        logger.debug("Inquiry %s has a TTL of %s and was started %s minute(s) ago" % (
                     inquiry.id, ttl, min_since_creation))

        if min_since_creation > ttl:
            gc_count += 1
            logger.info("TTL expired for Inquiry %s. Marking as timed out." % inquiry.id)

            liveaction_db = action_utils.update_liveaction_status(
                status=action_constants.LIVEACTION_STATUS_TIMED_OUT,
                result=inquiry.result,
                liveaction_id=inquiry.liveaction.get('id'))
            executions.update_execution(liveaction_db)

            # Call Inquiry runner's post_run to trigger callback to workflow
            action_db = get_action_by_ref(liveaction_db.action)
            invoke_post_run(liveaction_db=liveaction_db, action_db=action_db)

            if liveaction_db.context.get("parent"):
                # Request that root workflow resumes
                root_liveaction = action_service.get_root_liveaction(liveaction_db)
                action_service.request_resume(
                    root_liveaction,
                    UserDB(cfg.CONF.system_user.user)
                )

    logger.info('Marked %s ttl-expired Inquiries as "timed out".' % (gc_count))
コード例 #4
0
    def _query_and_save_results(self, query_context, last_query_time=None):
        this_query_time = time.time()
        execution_id = query_context.execution_id
        actual_query_context = query_context.query_context

        LOG.debug('Querying external service for results. Context: %s' %
                  actual_query_context)
        try:
            (status, results) = self.query(execution_id,
                                           actual_query_context,
                                           last_query_time=last_query_time)
        except:
            LOG.exception('Failed querying results for liveaction_id %s.',
                          execution_id)
            if self.delete_state_object_on_error:
                self._delete_state_object(query_context)
                LOG.debug('Removed state object %s.', query_context)
            return

        liveaction_db = None
        try:
            liveaction_db = self._update_action_results(
                execution_id, status, results)
        except Exception:
            LOG.exception(
                'Failed updating action results for liveaction_id %s',
                execution_id)
            if self.delete_state_object_on_error:
                self._delete_state_object(query_context)
                LOG.debug('Removed state object %s.', query_context)
            return

        if (status in action_constants.LIVEACTION_COMPLETED_STATES
                or status == action_constants.LIVEACTION_STATUS_PAUSED):
            runners_utils.invoke_post_run(liveaction_db)
            self._delete_state_object(query_context)
            LOG.debug("Detailed workflow liveaction results - ",
                      extra={'liveaction_db': liveaction_db})
            return

        if not self._is_state_object_exist(query_context):
            LOG.warning(
                'Query for liveaction_id %s is not rescheduled '
                'because state object %s has been deleted.', execution_id,
                query_context.id)

            return

        self._query_contexts.put((this_query_time, query_context))
コード例 #5
0
ファイル: action.py プロジェクト: rush-skills/st2
def update_status(
    liveaction,
    new_status,
    result=None,
    publish=True,
    set_result_size=False,
    context=None,
):
    if liveaction.status == new_status:
        return liveaction

    old_status = liveaction.status

    updates = {
        "liveaction_id": liveaction.id,
        "status": new_status,
        "result": result,
        "publish": False,
        "context": context,
    }

    if new_status in action_constants.LIVEACTION_COMPLETED_STATES:
        updates["end_timestamp"] = date_utils.get_datetime_utc_now()

    liveaction = action_utils.update_liveaction_status(**updates)
    action_execution = executions.update_execution(
        liveaction, set_result_size=set_result_size)

    msg = ("The status of action execution is changed from %s to %s. "
           "<LiveAction.id=%s, ActionExecution.id=%s>" %
           (old_status, new_status, liveaction.id, action_execution.id))

    extra = {
        "action_execution_db": action_execution,
        "liveaction_db": liveaction
    }

    LOG.audit(msg, extra=extra)
    LOG.info(msg)

    # Invoke post run if liveaction status is completed or paused.
    if (new_status in action_constants.LIVEACTION_COMPLETED_STATES
            or new_status == action_constants.LIVEACTION_STATUS_PAUSED):
        runners_utils.invoke_post_run(liveaction)

    if publish:
        LiveAction.publish_status(liveaction)

    return liveaction
コード例 #6
0
ファイル: base.py プロジェクト: treetory/st2
    def _query_and_save_results(self, query_context, last_query_time=None):
        this_query_time = time.time()
        execution_id = query_context.execution_id
        actual_query_context = query_context.query_context

        LOG.debug('Querying external service for results. Context: %s' %
                  actual_query_context)
        try:
            (status, results) = self.query(execution_id,
                                           actual_query_context,
                                           last_query_time=last_query_time)
        except:
            LOG.exception('Failed querying results for liveaction_id %s.',
                          execution_id)
            if self.delete_state_object_on_error:
                self._delete_state_object(query_context)
                LOG.debug('Removed state object %s.', query_context)
            return

        liveaction_db = None
        try:
            liveaction_db = self._update_action_results(
                execution_id, status, results)
        except Exception:
            LOG.exception(
                'Failed updating action results for liveaction_id %s',
                execution_id)
            if self.delete_state_object_on_error:
                self._delete_state_object(query_context)
                LOG.debug('Removed state object %s.', query_context)
            return

        if status in action_constants.LIVEACTION_COMPLETED_STATES:
            if status != action_constants.LIVEACTION_STATUS_CANCELED:
                runners_utils.invoke_post_run(liveaction_db)

            self._delete_state_object(query_context)

            return

        self._query_contexts.put((this_query_time, query_context))
コード例 #7
0
def update_status(liveaction, new_status, result=None, publish=True):
    if liveaction.status == new_status:
        return liveaction

    old_status = liveaction.status

    updates = {
        'liveaction_id': liveaction.id,
        'status': new_status,
        'result': result,
        'publish': False
    }

    if new_status in action_constants.LIVEACTION_COMPLETED_STATES:
        updates['end_timestamp'] = date_utils.get_datetime_utc_now()

    liveaction = action_utils.update_liveaction_status(**updates)
    action_execution = executions.update_execution(liveaction)

    msg = ('The status of action execution is changed from %s to %s. '
           '<LiveAction.id=%s, ActionExecution.id=%s>' %
           (old_status, new_status, liveaction.id, action_execution.id))

    extra = {
        'action_execution_db': action_execution,
        'liveaction_db': liveaction
    }

    LOG.audit(msg, extra=extra)
    LOG.info(msg)

    # Invoke post run if liveaction status is completed or paused.
    if (new_status in action_constants.LIVEACTION_COMPLETED_STATES
            or new_status == action_constants.LIVEACTION_STATUS_PAUSED):
        runners_utils.invoke_post_run(liveaction)

    if publish:
        LiveAction.publish_status(liveaction)

    return liveaction
コード例 #8
0
ファイル: action.py プロジェクト: StackStorm/st2
def update_status(liveaction, new_status, result=None, publish=True):
    if liveaction.status == new_status:
        return liveaction

    old_status = liveaction.status

    updates = {
        'liveaction_id': liveaction.id,
        'status': new_status,
        'result': result,
        'publish': False
    }

    if new_status in action_constants.LIVEACTION_COMPLETED_STATES:
        updates['end_timestamp'] = date_utils.get_datetime_utc_now()

    liveaction = action_utils.update_liveaction_status(**updates)
    action_execution = executions.update_execution(liveaction)

    msg = ('The status of action execution is changed from %s to %s. '
           '<LiveAction.id=%s, ActionExecution.id=%s>' % (old_status,
           new_status, liveaction.id, action_execution.id))

    extra = {
        'action_execution_db': action_execution,
        'liveaction_db': liveaction
    }

    LOG.audit(msg, extra=extra)
    LOG.info(msg)

    # Invoke post run if liveaction status is completed or paused.
    if (new_status in action_constants.LIVEACTION_COMPLETED_STATES or
            new_status == action_constants.LIVEACTION_STATUS_PAUSED):
        runners_utils.invoke_post_run(liveaction)

    if publish:
        LiveAction.publish_status(liveaction)

    return liveaction
コード例 #9
0
ファイル: workflows.py プロジェクト: jayd2446/st2
def update_execution_records(wf_ex_db,
                             conductor,
                             update_lv_ac_on_statuses=None,
                             pub_wf_ex=False,
                             pub_lv_ac=True,
                             pub_ac_ex=True):

    wf_ac_ex_id = wf_ex_db.action_execution

    # Determine if workflow status has changed.
    wf_old_status = wf_ex_db.status
    wf_ex_db.status = conductor.get_workflow_status()
    status_changed = (wf_old_status != wf_ex_db.status)

    if status_changed:
        msg = '[%s] Updating workflow execution from status "%s" to "%s".'
        LOG.info(msg, wf_ac_ex_id, wf_old_status, wf_ex_db.status)

    # Update timestamp and output if workflow is completed.
    if wf_ex_db.status in statuses.COMPLETED_STATUSES:
        wf_ex_db.end_timestamp = date_utils.get_datetime_utc_now()
        wf_ex_db.output = conductor.get_workflow_output()

    # Update task flow and other attributes.
    wf_ex_db.errors = copy.deepcopy(conductor.errors)
    wf_ex_db.state = conductor.workflow_state.serialize()

    # Write changes to the database.
    wf_ex_db = wf_db_access.WorkflowExecution.update(wf_ex_db,
                                                     publish=pub_wf_ex)

    # Return if workflow execution status is not specified in update_lv_ac_on_statuses.
    if (isinstance(update_lv_ac_on_statuses, list)
            and wf_ex_db.status not in update_lv_ac_on_statuses):
        return

    # Update the corresponding liveaction and action execution for the workflow.
    wf_ac_ex_db = ex_db_access.ActionExecution.get_by_id(
        wf_ex_db.action_execution)
    wf_lv_ac_db = action_utils.get_liveaction_by_id(
        wf_ac_ex_db.liveaction['id'])

    # Gather result for liveaction and action execution.
    result = {'output': wf_ex_db.output or None}

    if wf_ex_db.status in statuses.ABENDED_STATUSES:
        result['errors'] = wf_ex_db.errors

        for wf_ex_error in wf_ex_db.errors:
            msg = '[%s] Workflow execution completed with errors.'
            LOG.error(msg, wf_ac_ex_id, extra=wf_ex_error)

    # Sync update with corresponding liveaction and action execution.
    if pub_lv_ac or pub_ac_ex:
        pub_lv_ac = (wf_lv_ac_db.status != wf_ex_db.status)
        pub_ac_ex = pub_lv_ac

    if wf_lv_ac_db.status != wf_ex_db.status:
        msg = '[%s] Updating workflow liveaction from status "%s" to "%s".'
        LOG.debug(msg, wf_ac_ex_id, wf_lv_ac_db.status, wf_ex_db.status)
        msg = '[%s] Workflow liveaction status change %s be published.'
        LOG.debug(msg, wf_ac_ex_id, 'will' if pub_lv_ac else 'will not')
        msg = '[%s] Workflow action execution status change %s be published.'
        LOG.debug(msg, wf_ac_ex_id, 'will' if pub_ac_ex else 'will not')

    wf_lv_ac_db = action_utils.update_liveaction_status(
        status=wf_ex_db.status,
        result=result,
        end_timestamp=wf_ex_db.end_timestamp,
        liveaction_db=wf_lv_ac_db,
        publish=pub_lv_ac)

    ex_svc.update_execution(wf_lv_ac_db, publish=pub_ac_ex)

    # Invoke post run on the liveaction for the workflow execution.
    if status_changed and wf_lv_ac_db.status in ac_const.LIVEACTION_COMPLETED_STATES:
        LOG.info(
            '[%s] Workflow action execution is completed and invoking post run.',
            wf_ac_ex_id)
        runners_utils.invoke_post_run(wf_lv_ac_db)
コード例 #10
0
 def test_invoke_post_run_action_does_not_exist(self):
     utils.invoke_post_run(self.liveaction_db)
     action_db_utils.get_action_by_ref.assert_called_once()
     action_db_utils.get_runnertype_by_name.assert_not_called()
コード例 #11
0
 def test_invoke_post_run_action_exists(self):
     utils.invoke_post_run(self.liveaction_db)
コード例 #12
0
 def test_invoke_post_run_action_provided(self):
     utils.invoke_post_run(self.liveaction_db, action_db=self.action_db)
     action_db_utils.get_action_by_ref.assert_not_called()
コード例 #13
0
ファイル: test_runners_utils.py プロジェクト: lyandut/st2
 def test_invoke_post_run_action_does_not_exist(self):
     utils.invoke_post_run(self.liveaction_db)
     action_db_utils.get_action_by_ref.assert_called_once()
     action_db_utils.get_runnertype_by_name.assert_not_called()
コード例 #14
0
ファイル: test_runners_utils.py プロジェクト: lyandut/st2
 def test_invoke_post_run_action_exists(self):
     utils.invoke_post_run(self.liveaction_db)
コード例 #15
0
ファイル: test_runners_utils.py プロジェクト: lyandut/st2
 def test_invoke_post_run_action_provided(self):
     utils.invoke_post_run(self.liveaction_db, action_db=self.action_db)
     action_db_utils.get_action_by_ref.assert_not_called()
コード例 #16
0
ファイル: workflows.py プロジェクト: nzlosh/st2
def update_execution_records(wf_ex_db, conductor, update_lv_ac_on_statuses=None,
                             pub_wf_ex=False, pub_lv_ac=True, pub_ac_ex=True):

    wf_ac_ex_id = wf_ex_db.action_execution

    # Determine if workflow status has changed.
    wf_old_status = wf_ex_db.status
    wf_ex_db.status = conductor.get_workflow_status()
    status_changed = (wf_old_status != wf_ex_db.status)

    if status_changed:
        msg = '[%s] Updating workflow execution from status "%s" to "%s".'
        LOG.info(msg, wf_ac_ex_id, wf_old_status, wf_ex_db.status)

    # Update timestamp and output if workflow is completed.
    if wf_ex_db.status in statuses.COMPLETED_STATUSES:
        wf_ex_db.end_timestamp = date_utils.get_datetime_utc_now()
        wf_ex_db.output = conductor.get_workflow_output()

    # Update task flow and other attributes.
    wf_ex_db.errors = copy.deepcopy(conductor.errors)
    wf_ex_db.state = conductor.workflow_state.serialize()

    # Write changes to the database.
    wf_ex_db = wf_db_access.WorkflowExecution.update(wf_ex_db, publish=pub_wf_ex)

    # Return if workflow execution status is not specified in update_lv_ac_on_statuses.
    if (isinstance(update_lv_ac_on_statuses, list) and
            wf_ex_db.status not in update_lv_ac_on_statuses):
        return

    # Update the corresponding liveaction and action execution for the workflow.
    wf_ac_ex_db = ex_db_access.ActionExecution.get_by_id(wf_ex_db.action_execution)
    wf_lv_ac_db = action_utils.get_liveaction_by_id(wf_ac_ex_db.liveaction['id'])

    # Gather result for liveaction and action execution.
    result = {'output': wf_ex_db.output or None}

    if wf_ex_db.status in statuses.ABENDED_STATUSES:
        result['errors'] = wf_ex_db.errors

        for wf_ex_error in wf_ex_db.errors:
            msg = '[%s] Workflow execution completed with errors.'
            LOG.error(msg, wf_ac_ex_id, extra=wf_ex_error)

    # Sync update with corresponding liveaction and action execution.
    if pub_lv_ac or pub_ac_ex:
        pub_lv_ac = (wf_lv_ac_db.status != wf_ex_db.status)
        pub_ac_ex = pub_lv_ac

    if wf_lv_ac_db.status != wf_ex_db.status:
        msg = '[%s] Updating workflow liveaction from status "%s" to "%s".'
        LOG.debug(msg, wf_ac_ex_id, wf_lv_ac_db.status, wf_ex_db.status)
        msg = '[%s] Workflow liveaction status change %s be published.'
        LOG.debug(msg, wf_ac_ex_id, 'will' if pub_lv_ac else 'will not')
        msg = '[%s] Workflow action execution status change %s be published.'
        LOG.debug(msg, wf_ac_ex_id, 'will' if pub_ac_ex else 'will not')

    wf_lv_ac_db = action_utils.update_liveaction_status(
        status=wf_ex_db.status,
        result=result,
        end_timestamp=wf_ex_db.end_timestamp,
        liveaction_db=wf_lv_ac_db,
        publish=pub_lv_ac)

    ex_svc.update_execution(wf_lv_ac_db, publish=pub_ac_ex)

    # Invoke post run on the liveaction for the workflow execution.
    if status_changed and wf_lv_ac_db.status in ac_const.LIVEACTION_COMPLETED_STATES:
        LOG.info('[%s] Workflow action execution is completed and invoking post run.', wf_ac_ex_id)
        runners_utils.invoke_post_run(wf_lv_ac_db)