Example #1
0
    def test_format_metrics_action_db_without_pack(self):
        action = 'lakface'
        pack = 'unknown'

        action_db = MagicMock()
        action_db.pack = None
        action_db.name = action

        key = base.format_metrics_key(action_db=action_db)

        self.assertEquals(key, "st2.%s.%s" % (pack, action))
Example #2
0
    def test_format_metrics_liveaction_db_without_pack(self):
        action = 'lakface'
        pack = 'unknown'

        liveaction_db = MagicMock()
        liveaction_db.context = {}
        liveaction_db.action = "%s.%s" % (pack, action)

        key = base.format_metrics_key(liveaction_db=liveaction_db)

        self.assertEquals(key, "st2.%s.%s" % (pack, action))
Example #3
0
    def test_format_metrics_action_db_without_key(self):
        pack = 'test'
        action = 'lakface'

        action_db = MagicMock()
        action_db.pack = pack
        action_db.name = action

        key = base.format_metrics_key(action_db=action_db)

        self.assertEquals(key, "st2.%s.%s" % (pack, action))
Example #4
0
    def test_format_metrics_action_db_without_pack(self):
        action = 'lakface'
        pack = 'unknown'

        action_db = MagicMock()
        action_db.pack = None
        action_db.name = action

        key = base.format_metrics_key(action_db=action_db)

        self.assertEquals(key, "st2.%s.%s" % (pack, action))
Example #5
0
    def test_format_metrics_liveaction_db_without_key(self):
        pack = 'test'
        action = 'lakface'

        liveaction_db = MagicMock()
        liveaction_db.context = {'pack': pack}
        liveaction_db.action = action

        key = base.format_metrics_key(liveaction_db=liveaction_db)

        self.assertEquals(key, "st2.%s.%s" % (pack, action))
Example #6
0
    def test_format_metrics_action_db_without_key(self):
        pack = 'test'
        action = 'lakface'

        action_db = MagicMock()
        action_db.pack = pack
        action_db.name = action

        key = base.format_metrics_key(action_db=action_db)

        self.assertEquals(key, "st2.%s.%s" % (pack, action))
Example #7
0
    def test_format_metrics_liveaction_db_without_pack(self):
        action = 'lakface'
        pack = 'unknown'

        liveaction_db = MagicMock()
        liveaction_db.context = {}
        liveaction_db.action = "%s.%s" % (pack, action)

        key = base.format_metrics_key(liveaction_db=liveaction_db)

        self.assertEquals(key, "st2.%s.%s" % (pack, action))
Example #8
0
    def test_format_metrics_liveaction_db_without_key(self):
        pack = 'test'
        action = 'lakface'

        liveaction_db = MagicMock()
        liveaction_db.context = {'pack': pack}
        liveaction_db.action = action

        key = base.format_metrics_key(liveaction_db=liveaction_db)

        self.assertEquals(key, "st2.%s.%s" % (pack, action))
Example #9
0
    def create_rule_enforcers(self, trigger_instance, matching_rules):
        """
        Creates a RuleEnforcer matching to each rule.

        This method is trigger_instance specific therefore if creation of 1 RuleEnforcer
        fails it is likely that all wil be broken.
        """
        enforcers = []
        for matching_rule in matching_rules:

            get_driver().inc_counter(
                format_metrics_key(key='rule.%s' % matching_rule))

            enforcers.append(RuleEnforcer(trigger_instance, matching_rule))
        return enforcers
Example #10
0
    def create_rule_enforcers(self, trigger_instance, matching_rules):
        """
        Creates a RuleEnforcer matching to each rule.

        This method is trigger_instance specific therefore if creation of 1 RuleEnforcer
        fails it is likely that all wil be broken.
        """
        enforcers = []
        for matching_rule in matching_rules:

            get_driver().inc_counter(
                format_metrics_key(
                    key='rule.%s' % matching_rule
                )
            )

            enforcers.append(RuleEnforcer(trigger_instance, matching_rule))
        return enforcers
Example #11
0
File: worker.py Project: versus/st2
    def process(self, pre_ack_response):

        trigger_instance, message = self._decompose_pre_ack_process_response(
            pre_ack_response)
        if not trigger_instance:
            raise ValueError('No trigger_instance provided for processing.')

        get_driver().inc_counter(
            format_metrics_key(key='trigger.%s' % (trigger_instance.trigger)))

        try:
            # Use trace_context from the message and if not found create a new context
            # and use the trigger_instance.id as trace_tag.
            trace_context = message.get(TRACE_CONTEXT, None)
            if not trace_context:
                trace_context = {
                    TRACE_ID: 'trigger_instance-%s' % str(trigger_instance.id)
                }
            # add a trace or update an existing trace with trigger_instance
            trace_service.add_or_update_given_trace_context(
                trace_context=trace_context,
                trigger_instances=[
                    trace_service.get_trace_component_for_trigger_instance(
                        trigger_instance)
                ])

            container_utils.update_trigger_instance_status(
                trigger_instance,
                trigger_constants.TRIGGER_INSTANCE_PROCESSING)
            self.rules_engine.handle_trigger_instance(trigger_instance)
            container_utils.update_trigger_instance_status(
                trigger_instance, trigger_constants.TRIGGER_INSTANCE_PROCESSED)
        except:
            # TODO : Capture the reason for failure.
            container_utils.update_trigger_instance_status(
                trigger_instance,
                trigger_constants.TRIGGER_INSTANCE_PROCESSING_FAILED)
            # This could be a large message but at least in case of an exception
            # we get to see more context.
            # Beyond this point code cannot really handle the exception anyway so
            # eating up the exception.
            LOG.exception('Failed to handle trigger_instance %s.',
                          trigger_instance)
            return
Example #12
0
    def _do_run(self, runner, runnertype_db, action_db, liveaction_db):
        # Create a temporary auth token which will be available
        # for the duration of the action execution.
        runner.auth_token = self._create_auth_token(
            context=runner.context,
            action_db=action_db,
            liveaction_db=liveaction_db)

        try:
            # Finalized parameters are resolved and then rendered. This process could
            # fail. Handle the exception and report the error correctly.
            try:
                runner_params, action_params = param_utils.render_final_params(
                    runnertype_db.runner_parameters, action_db.parameters,
                    liveaction_db.parameters, liveaction_db.context)
                runner.runner_parameters = runner_params
            except ParamException as e:
                raise actionrunner.ActionRunnerException(str(e))

            LOG.debug('Performing pre-run for runner: %s', runner.runner_id)
            runner.pre_run()

            # Mask secret parameters in the log context
            resolved_action_params = ResolvedActionParameters(
                action_db=action_db,
                runner_type_db=runnertype_db,
                runner_parameters=runner_params,
                action_parameters=action_params)
            extra = {'runner': runner, 'parameters': resolved_action_params}
            LOG.debug('Performing run for runner: %s' % (runner.runner_id),
                      extra=extra)
            with CounterWithTimer(
                    key=format_metrics_key(action_db=action_db, key='action')):
                (status, result, context) = runner.run(action_params)

            try:
                result = json.loads(result)
            except:
                pass

            action_completed = status in action_constants.LIVEACTION_COMPLETED_STATES
            if (isinstance(runner, PollingAsyncActionRunner)
                    and runner.is_polling_enabled() and not action_completed):
                queries.setup_query(liveaction_db.id, runnertype_db, context)
        except:
            LOG.exception('Failed to run action.')
            _, ex, tb = sys.exc_info()
            # mark execution as failed.
            status = action_constants.LIVEACTION_STATUS_FAILED
            # include the error message and traceback to try and provide some hints.
            result = {
                'error': str(ex),
                'traceback': ''.join(traceback.format_tb(tb, 20))
            }
            context = None
        finally:
            # Log action completion
            extra = {'result': result, 'status': status}
            LOG.debug('Action "%s" completed.' % (action_db.name), extra=extra)

            # Update the final status of liveaction and corresponding action execution.
            liveaction_db = self._update_status(liveaction_db.id, status,
                                                result, context)

            # Always clean-up the auth_token
            # This method should be called in the finally block to ensure post_run is not impacted.
            self._clean_up_auth_token(runner=runner, status=status)

        LOG.debug('Performing post_run for runner: %s', runner.runner_id)
        runner.post_run(status=status, result=result)

        LOG.debug('Runner do_run result',
                  extra={'result': liveaction_db.result})
        LOG.audit('Liveaction completed',
                  extra={'liveaction_db': liveaction_db})

        return liveaction_db
Example #13
0
def update_liveaction_status(status=None, result=None, context=None, end_timestamp=None,
                             liveaction_id=None, runner_info=None, liveaction_db=None,
                             publish=True):
    """
        Update the status of the specified LiveAction to the value provided in
        new_status.

        The LiveAction may be specified using either liveaction_id, or as an
        liveaction_db instance.
    """

    if (liveaction_id is None) and (liveaction_db is None):
        raise ValueError('Must specify an liveaction_id or an liveaction_db when '
                         'calling update_LiveAction_status')

    if liveaction_db is None:
        liveaction_db = get_liveaction_by_id(liveaction_id)

    if status not in LIVEACTION_STATUSES:
        raise ValueError('Attempting to set status for LiveAction "%s" '
                         'to unknown status string. Unknown status is "%s"',
                         liveaction_db, status)

    # If liveaction_db status is set then we need to decrement the counter
    # because it is transitioning to a new state
    if liveaction_db.status:
        get_driver().dec_counter(
            format_metrics_key(
                liveaction_db=liveaction_db,
                key='action.%s' % liveaction_db.status
            )
        )

    # If status is provided then we need to increment the timer because the action
    # is transitioning into this new state
    if status:
        get_driver().inc_counter(
            format_metrics_key(
                liveaction_db=liveaction_db,
                key='action.%s' % status
            )
        )

    extra = {'liveaction_db': liveaction_db}
    LOG.debug('Updating ActionExection: "%s" with status="%s"', liveaction_db.id, status,
              extra=extra)

    # If liveaction is already canceled, then do not allow status to be updated.
    if liveaction_db.status == LIVEACTION_STATUS_CANCELED and status != LIVEACTION_STATUS_CANCELED:
        LOG.info('Unable to update ActionExecution "%s" with status="%s". '
                 'ActionExecution is already canceled.', liveaction_db.id, status, extra=extra)
        return liveaction_db

    old_status = liveaction_db.status
    liveaction_db.status = status

    if result:
        liveaction_db.result = result

    if context:
        liveaction_db.context.update(context)

    if end_timestamp:
        liveaction_db.end_timestamp = end_timestamp

    if runner_info:
        liveaction_db.runner_info = runner_info

    liveaction_db = LiveAction.add_or_update(liveaction_db)

    LOG.debug('Updated status for LiveAction object.', extra=extra)

    if publish and status != old_status:
        LiveAction.publish_status(liveaction_db)
        LOG.debug('Published status for LiveAction object.', extra=extra)

    return liveaction_db
Example #14
0
def create_request(liveaction):
    """
    Create an action execution.

    :return: (liveaction, execution)
    :rtype: tuple
    """
    # We import this here to avoid conflicts w/ runners that might import this
    # file since the runners don't have the config context by default.
    from st2common.metrics.base import get_driver, format_metrics_key
    # Use the user context from the parent action execution. Subtasks in a workflow
    # action can be invoked by a system user and so we want to use the user context
    # from the original workflow action.
    parent_context = executions.get_parent_context(liveaction)
    if parent_context:
        parent_user = parent_context.get('user', None)
        if parent_user:
            liveaction.context['user'] = parent_user

    # Validate action.
    action_db = action_utils.get_action_by_ref(liveaction.action)
    if not action_db:
        raise ValueError('Action "%s" cannot be found.' % liveaction.action)
    if not action_db.enabled:
        raise ValueError('Unable to execute. Action "%s" is disabled.' % liveaction.action)

    runnertype_db = action_utils.get_runnertype_by_name(action_db.runner_type['name'])

    if not hasattr(liveaction, 'parameters'):
        liveaction.parameters = dict()

    # Validate action parameters.
    schema = util_schema.get_schema_for_action_parameters(action_db)
    validator = util_schema.get_validator()
    util_schema.validate(liveaction.parameters, schema, validator, use_default=True,
                         allow_default_none=True)

    # validate that no immutable params are being overriden. Although possible to
    # ignore the override it is safer to inform the user to avoid surprises.
    immutables = _get_immutable_params(action_db.parameters)
    immutables.extend(_get_immutable_params(runnertype_db.runner_parameters))
    overridden_immutables = [p for p in six.iterkeys(liveaction.parameters) if p in immutables]
    if len(overridden_immutables) > 0:
        raise ValueError('Override of immutable parameter(s) %s is unsupported.'
                         % str(overridden_immutables))

    # Set notification settings for action.
    # XXX: There are cases when we don't want notifications to be sent for a particular
    # execution. So we should look at liveaction.parameters['notify']
    # and not set liveaction.notify.
    if not _is_notify_empty(action_db.notify):
        liveaction.notify = action_db.notify

    # Write to database and send to message queue.
    liveaction.status = action_constants.LIVEACTION_STATUS_REQUESTED
    liveaction.start_timestamp = date_utils.get_datetime_utc_now()

    # Set the "action_is_workflow" attribute
    liveaction.action_is_workflow = action_db.is_workflow()

    # Publish creation after both liveaction and actionexecution are created.
    liveaction = LiveAction.add_or_update(liveaction, publish=False)

    # Get trace_db if it exists. This could throw. If it throws, we have to cleanup
    # liveaction object so we don't see things in requested mode.
    trace_db = None
    try:
        _, trace_db = trace_service.get_trace_db_by_live_action(liveaction)
    except db_exc.StackStormDBObjectNotFoundError as e:
        _cleanup_liveaction(liveaction)
        raise trace_exc.TraceNotFoundException(str(e))

    execution = executions.create_execution_object(liveaction, publish=False)

    if trace_db:
        trace_service.add_or_update_given_trace_db(
            trace_db=trace_db,
            action_executions=[
                trace_service.get_trace_component_for_action_execution(execution, liveaction)
            ])

    get_driver().inc_counter(
        format_metrics_key(
            action_db=action_db,
            key='action.%s' % (liveaction.status)
        )
    )
    return liveaction, execution
Example #15
0
File: base.py Project: lyandut/st2
    def _do_run(self, runner):
        # Create a temporary auth token which will be available
        # for the duration of the action execution.
        runner.auth_token = self._create_auth_token(
            context=runner.context,
            action_db=runner.action,
            liveaction_db=runner.liveaction)

        try:
            # Finalized parameters are resolved and then rendered. This process could
            # fail. Handle the exception and report the error correctly.
            try:
                runner_params, action_params = param_utils.render_final_params(
                    runner.runner_type.runner_parameters,
                    runner.action.parameters,
                    runner.liveaction.parameters,
                    runner.liveaction.context)

                runner.runner_parameters = runner_params
            except ParamException as e:
                raise actionrunner.ActionRunnerException(str(e))

            LOG.debug('Performing pre-run for runner: %s', runner.runner_id)
            runner.pre_run()

            # Mask secret parameters in the log context
            resolved_action_params = ResolvedActionParameters(
                action_db=runner.action,
                runner_type_db=runner.runner_type,
                runner_parameters=runner_params,
                action_parameters=action_params)

            extra = {'runner': runner, 'parameters': resolved_action_params}
            LOG.debug('Performing run for runner: %s' % (runner.runner_id), extra=extra)

            with CounterWithTimer(key=format_metrics_key(action_db=runner.action, key='action')):
                (status, result, context) = runner.run(action_params)
                result = jsonify.try_loads(result)

            action_completed = status in action_constants.LIVEACTION_COMPLETED_STATES

            if (isinstance(runner, PollingAsyncActionRunner) and
                    runner.is_polling_enabled() and not action_completed):
                queries.setup_query(runner.liveaction.id, runner.runner_type, context)
        except:
            LOG.exception('Failed to run action.')
            _, ex, tb = sys.exc_info()
            # mark execution as failed.
            status = action_constants.LIVEACTION_STATUS_FAILED
            # include the error message and traceback to try and provide some hints.
            result = {'error': str(ex), 'traceback': ''.join(traceback.format_tb(tb, 20))}
            context = None
        finally:
            # Log action completion
            extra = {'result': result, 'status': status}
            LOG.debug('Action "%s" completed.' % (runner.action.name), extra=extra)

            # Update the final status of liveaction and corresponding action execution.
            runner.liveaction = self._update_status(runner.liveaction.id, status, result, context)

            # Always clean-up the auth_token
            # This method should be called in the finally block to ensure post_run is not impacted.
            self._clean_up_auth_token(runner=runner, status=status)

        LOG.debug('Performing post_run for runner: %s', runner.runner_id)
        runner.post_run(status=status, result=result)

        LOG.debug('Runner do_run result', extra={'result': runner.liveaction.result})
        LOG.audit('Liveaction completed', extra={'liveaction_db': runner.liveaction})

        return runner.liveaction
Example #16
0
def update_liveaction_status(status=None,
                             result=None,
                             context=None,
                             end_timestamp=None,
                             liveaction_id=None,
                             runner_info=None,
                             liveaction_db=None,
                             publish=True):
    """
        Update the status of the specified LiveAction to the value provided in
        new_status.

        The LiveAction may be specified using either liveaction_id, or as an
        liveaction_db instance.
    """

    if (liveaction_id is None) and (liveaction_db is None):
        raise ValueError(
            'Must specify an liveaction_id or an liveaction_db when '
            'calling update_LiveAction_status')

    if liveaction_db is None:
        liveaction_db = get_liveaction_by_id(liveaction_id)

    if status not in LIVEACTION_STATUSES:
        raise ValueError(
            'Attempting to set status for LiveAction "%s" '
            'to unknown status string. Unknown status is "%s"', liveaction_db,
            status)

    # If liveaction_db status is set then we need to decrement the counter
    # because it is transitioning to a new state
    if liveaction_db.status:
        get_driver().dec_counter(
            format_metrics_key(liveaction_db=liveaction_db,
                               key='action.%s' % liveaction_db.status))

    # If status is provided then we need to increment the timer because the action
    # is transitioning into this new state
    if status:
        get_driver().inc_counter(
            format_metrics_key(liveaction_db=liveaction_db,
                               key='action.%s' % status))

    extra = {'liveaction_db': liveaction_db}
    LOG.debug('Updating ActionExection: "%s" with status="%s"',
              liveaction_db.id,
              status,
              extra=extra)

    # If liveaction is already canceled, then do not allow status to be updated.
    if liveaction_db.status == LIVEACTION_STATUS_CANCELED and status != LIVEACTION_STATUS_CANCELED:
        LOG.info(
            'Unable to update ActionExecution "%s" with status="%s". '
            'ActionExecution is already canceled.',
            liveaction_db.id,
            status,
            extra=extra)
        return liveaction_db

    old_status = liveaction_db.status
    liveaction_db.status = status

    if result:
        liveaction_db.result = result

    if context:
        liveaction_db.context.update(context)

    if end_timestamp:
        liveaction_db.end_timestamp = end_timestamp

    if runner_info:
        liveaction_db.runner_info = runner_info

    liveaction_db = LiveAction.add_or_update(liveaction_db)

    LOG.debug('Updated status for LiveAction object.', extra=extra)

    if publish and status != old_status:
        LiveAction.publish_status(liveaction_db)
        LOG.debug('Published status for LiveAction object.', extra=extra)

    return liveaction_db