def _schedule_execution(self, action_alias_db, params, notify, context, requester_user,
                            show_secrets):
        action_ref = action_alias_db.action_ref
        action_db = action_utils.get_action_by_ref(action_ref)

        if not action_db:
            raise StackStormDBObjectNotFoundError('Action with ref "%s" not found ' % (action_ref))

        assert_user_has_resource_db_permission(user_db=requester_user, resource_db=action_db,
                                               permission_type=PermissionType.ACTION_EXECUTE)

        try:
            # prior to shipping off the params cast them to the right type.
            params = action_param_utils.cast_params(action_ref=action_alias_db.action_ref,
                                                    params=params,
                                                    cast_overrides=CAST_OVERRIDES)
            if not context:
                context = {
                    'action_alias_ref': reference.get_ref_from_model(action_alias_db),
                    'user': get_system_username()
                }
            liveaction = LiveActionDB(action=action_alias_db.action_ref, context=context,
                                      parameters=params, notify=notify)
            _, action_execution_db = action_service.request(liveaction)
            mask_secrets = self._get_mask_secrets(requester_user, show_secrets=show_secrets)
            return ActionExecutionAPI.from_model(action_execution_db, mask_secrets=mask_secrets)
        except ValueError as e:
            LOG.exception('Unable to execute action.')
            abort(http_client.BAD_REQUEST, str(e))
        except jsonschema.ValidationError as e:
            LOG.exception('Unable to execute action. Parameter validation failed.')
            abort(http_client.BAD_REQUEST, str(e))
        except Exception as e:
            LOG.exception('Unable to execute action. Unexpected error encountered.')
            abort(http_client.INTERNAL_SERVER_ERROR, str(e))
Example #2
0
    def _schedule_execution(self, liveaction):
        # Initialize execution context if it does not exist.
        if not hasattr(liveaction, 'context'):
            liveaction.context = dict()

        # Retrieve username of the authed user (note - if auth is disabled, user will not be
        # set so we fall back to the system user name)
        request_token = pecan.request.context.get('token', None)

        if request_token:
            user = request_token.user
        else:
            user = cfg.CONF.system_user.user

        liveaction.context['user'] = user
        LOG.debug('User is: %s' % user)

        # Retrieve other st2 context from request header.
        if 'st2-context' in pecan.request.headers and pecan.request.headers[
                'st2-context']:
            context = jsonify.try_loads(pecan.request.headers['st2-context'])
            if not isinstance(context, dict):
                raise ValueError(
                    'Unable to convert st2-context from the headers into JSON.'
                )
            liveaction.context.update(context)

        # Schedule the action execution.
        liveactiondb = LiveActionAPI.to_model(liveaction)
        _, actionexecutiondb = action_service.request(liveactiondb)
        from_model_kwargs = self._get_from_model_kwargs_for_request(
            request=pecan.request)
        return ActionExecutionAPI.from_model(actionexecutiondb,
                                             from_model_kwargs)
Example #3
0
    def _schedule_execution(self, execution):
        # Initialize execution context if it does not exist.
        if not hasattr(execution, 'context'):
            execution.context = dict()

        # Retrieve username of the authed user (note - if auth is disabled, user will not be
        # set so we fall back to the system user name)
        request_token = pecan.request.context.get('token', None)

        if request_token:
            user = request_token.user
        else:
            user = cfg.CONF.system_user.user

        execution.context['user'] = user

        # Retrieve other st2 context from request header.
        if ('st2-context' in pecan.request.headers and pecan.request.headers['st2-context']):
            context = jsonify.try_loads(pecan.request.headers['st2-context'])
            if not isinstance(context, dict):
                raise ValueError('Unable to convert st2-context from the headers into JSON.')
            execution.context.update(context)

        # Schedule the action execution.
        liveactiondb = LiveActionAPI.to_model(execution)
        _, actionexecutiondb = action_service.request(liveactiondb)
        return ActionExecutionAPI.from_model(actionexecutiondb)
Example #4
0
    def _schedule_execution(self, action_alias_db, params, notify, context):
        action_ref = action_alias_db.action_ref
        action_db = action_utils.get_action_by_ref(action_ref)

        if not action_db:
            raise StackStormDBObjectNotFoundError('Action with ref "%s" not found ' % (action_ref))

        assert_request_user_has_resource_db_permission(request=pecan.request, resource_db=action_db,
            permission_type=PermissionType.ACTION_EXECUTE)

        try:
            # prior to shipping off the params cast them to the right type.
            params = action_param_utils.cast_params(action_ref=action_alias_db.action_ref,
                                                    params=params,
                                                    cast_overrides=CAST_OVERRIDES)
            if not context:
                context = {
                    'action_alias_ref': reference.get_ref_from_model(action_alias_db),
                    'user': get_system_username()
                }
            liveaction = LiveActionDB(action=action_alias_db.action_ref, context=context,
                                      parameters=params, notify=notify)
            _, action_execution_db = action_service.request(liveaction)
            return ActionExecutionAPI.from_model(action_execution_db)
        except ValueError as e:
            LOG.exception('Unable to execute action.')
            pecan.abort(http_client.BAD_REQUEST, str(e))
        except jsonschema.ValidationError as e:
            LOG.exception('Unable to execute action. Parameter validation failed.')
            pecan.abort(http_client.BAD_REQUEST, str(e))
        except Exception as e:
            LOG.exception('Unable to execute action. Unexpected error encountered.')
            pecan.abort(http_client.INTERNAL_SERVER_ERROR, str(e))
Example #5
0
    def _schedule_execution(self, liveaction):
        # Initialize execution context if it does not exist.
        if not hasattr(liveaction, 'context'):
            liveaction.context = dict()

        liveaction.context['user'] = get_requester()
        LOG.debug('User is: %s' % liveaction.context['user'])

        # Retrieve other st2 context from request header.
        if 'st2-context' in pecan.request.headers and pecan.request.headers['st2-context']:
            context = jsonify.try_loads(pecan.request.headers['st2-context'])
            if not isinstance(context, dict):
                raise ValueError('Unable to convert st2-context from the headers into JSON.')
            liveaction.context.update(context)

        # Schedule the action execution.
        liveaction_db = LiveActionAPI.to_model(liveaction)
        liveaction_db, actionexecution_db = action_service.create_request(liveaction_db)

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

        try:
            liveaction_db.parameters = param_utils.render_live_params(
                runnertype_db.runner_parameters, action_db.parameters, liveaction_db.parameters,
                liveaction_db.context)
        except ParamException as e:
            raise ValueValidationException(str(e))

        liveaction_db = LiveAction.add_or_update(liveaction_db, publish=False)

        _, actionexecution_db = action_service.publish_request(liveaction_db, actionexecution_db)
        from_model_kwargs = self._get_from_model_kwargs_for_request(request=pecan.request)
        return ActionExecutionAPI.from_model(actionexecution_db, from_model_kwargs)
Example #6
0
 def process(self, execution):
     LOG.debug('Got execution from queue: %s', execution)
     if execution.status not in COMPLETION_STATUSES:
         return
     execution_api = ActionExecutionAPI.from_model(execution, mask_secrets=True)
     self.pending_executions.put_nowait(execution_api)
     LOG.debug("Added execution to queue.")
Example #7
0
    def _schedule_execution(self, liveaction):
        # Initialize execution context if it does not exist.
        if not hasattr(liveaction, "context"):
            liveaction.context = dict()

        # Retrieve username of the authed user (note - if auth is disabled, user will not be
        # set so we fall back to the system user name)
        request_token = pecan.request.context.get("token", None)

        if request_token:
            user = request_token.user
        else:
            user = cfg.CONF.system_user.user

        liveaction.context["user"] = user
        LOG.debug("User is: %s" % user)

        # Retrieve other st2 context from request header.
        if "st2-context" in pecan.request.headers and pecan.request.headers["st2-context"]:
            context = jsonify.try_loads(pecan.request.headers["st2-context"])
            if not isinstance(context, dict):
                raise ValueError("Unable to convert st2-context from the headers into JSON.")
            liveaction.context.update(context)

        # Schedule the action execution.
        liveactiondb = LiveActionAPI.to_model(liveaction)
        _, actionexecutiondb = action_service.request(liveactiondb)
        from_model_kwargs = self._get_from_model_kwargs_for_request(request=pecan.request)
        return ActionExecutionAPI.from_model(actionexecutiondb, from_model_kwargs)
Example #8
0
    def _schedule_execution(self, liveaction):
        # Initialize execution context if it does not exist.
        if not hasattr(liveaction, 'context'):
            liveaction.context = dict()

        liveaction.context['user'] = self._get_requester()
        LOG.debug('User is: %s' % liveaction.context['user'])

        # Retrieve other st2 context from request header.
        if 'st2-context' in pecan.request.headers and pecan.request.headers[
                'st2-context']:
            context = jsonify.try_loads(pecan.request.headers['st2-context'])
            if not isinstance(context, dict):
                raise ValueError(
                    'Unable to convert st2-context from the headers into JSON.'
                )
            liveaction.context.update(context)

        # Schedule the action execution.
        liveactiondb = LiveActionAPI.to_model(liveaction)
        _, actionexecutiondb = action_service.request(liveactiondb)
        from_model_kwargs = self._get_from_model_kwargs_for_request(
            request=pecan.request)
        return ActionExecutionAPI.from_model(actionexecutiondb,
                                             from_model_kwargs)
Example #9
0
    def delete(self, id, requester_user, **kwargs):
        """
        Stops a single execution.

        Handles requests:
            DELETE /executions/<id>

        """
        if not requester_user:
            requester_user = UserDB(cfg.CONF.system_user.user)

        execution_api = self._get_one_by_id(
            id=id,
            requester_user=requester_user,
            permission_type=PermissionType.EXECUTION_STOP)

        if not execution_api:
            abort(http_client.NOT_FOUND,
                  'Execution with id %s not found.' % id)

        liveaction_id = execution_api.liveaction['id']
        if not liveaction_id:
            abort(
                http_client.INTERNAL_SERVER_ERROR,
                'Execution object missing link to liveaction %s.' %
                liveaction_id)

        try:
            liveaction_db = LiveAction.get_by_id(liveaction_id)
        except:
            abort(
                http_client.INTERNAL_SERVER_ERROR,
                'Execution object missing link to liveaction %s.' %
                liveaction_id)

        if liveaction_db.status == LIVEACTION_STATUS_CANCELED:
            LOG.info('Action %s already in "canceled" state; \
                returning execution object.' % liveaction_db.id)
            return execution_api

        if liveaction_db.status not in LIVEACTION_CANCELABLE_STATES:
            abort(
                http_client.OK, 'Action cannot be canceled. State = %s.' %
                liveaction_db.status)

        try:
            (liveaction_db,
             execution_db) = action_service.request_cancellation(
                 liveaction_db, requester_user.name
                 or cfg.CONF.system_user.user)
        except:
            LOG.exception('Failed requesting cancellation for liveaction %s.',
                          liveaction_db.id)
            abort(http_client.INTERNAL_SERVER_ERROR,
                  'Failed canceling execution.')

        from_model_kwargs = self._get_from_model_kwargs_for_request(**kwargs)

        return ActionExecutionAPI.from_model(execution_db, from_model_kwargs)
Example #10
0
    def test_model_complete(self):

        # Create API object.
        obj = ActionExecutionAPI(**copy.deepcopy(self.fake_history_workflow))
        self.assertDictEqual(obj.trigger,
                             self.fake_history_workflow['trigger'])
        self.assertDictEqual(obj.trigger_type,
                             self.fake_history_workflow['trigger_type'])
        self.assertDictEqual(obj.trigger_instance,
                             self.fake_history_workflow['trigger_instance'])
        self.assertDictEqual(obj.rule, self.fake_history_workflow['rule'])
        self.assertDictEqual(obj.action, self.fake_history_workflow['action'])
        self.assertDictEqual(obj.runner, self.fake_history_workflow['runner'])
        self.assertEquals(obj.liveaction,
                          self.fake_history_workflow['liveaction'])
        self.assertIsNone(getattr(obj, 'parent', None))
        self.assertListEqual(obj.children,
                             self.fake_history_workflow['children'])

        # Convert API object to DB model.
        model = ActionExecutionAPI.to_model(obj)
        self.assertEqual(str(model.id), obj.id)
        self.assertDictEqual(model.trigger,
                             self.fake_history_workflow['trigger'])
        self.assertDictEqual(model.trigger_type,
                             self.fake_history_workflow['trigger_type'])
        self.assertDictEqual(model.trigger_instance,
                             self.fake_history_workflow['trigger_instance'])
        self.assertDictEqual(model.rule, self.fake_history_workflow['rule'])
        self.assertDictEqual(model.action,
                             self.fake_history_workflow['action'])
        self.assertDictEqual(model.runner,
                             self.fake_history_workflow['runner'])
        doc = copy.deepcopy(self.fake_history_workflow['liveaction'])
        doc['start_timestamp'] = doc['start_timestamp']
        doc['end_timestamp'] = doc['end_timestamp']
        self.assertDictEqual(model.liveaction, doc)
        self.assertIsNone(getattr(model, 'parent', None))
        self.assertListEqual(model.children,
                             self.fake_history_workflow['children'])

        # Convert DB model to API object.
        obj = ActionExecutionAPI.from_model(model)
        self.assertEqual(str(model.id), obj.id)
        self.assertDictEqual(obj.trigger,
                             self.fake_history_workflow['trigger'])
        self.assertDictEqual(obj.trigger_type,
                             self.fake_history_workflow['trigger_type'])
        self.assertDictEqual(obj.trigger_instance,
                             self.fake_history_workflow['trigger_instance'])
        self.assertDictEqual(obj.rule, self.fake_history_workflow['rule'])
        self.assertDictEqual(obj.action, self.fake_history_workflow['action'])
        self.assertDictEqual(obj.runner, self.fake_history_workflow['runner'])
        self.assertDictEqual(obj.liveaction,
                             self.fake_history_workflow['liveaction'])
        self.assertIsNone(getattr(obj, 'parent', None))
        self.assertListEqual(obj.children,
                             self.fake_history_workflow['children'])
Example #11
0
    def test_model_complete(self):

        # Create API object.
        obj = ActionExecutionAPI(**copy.deepcopy(self.fake_history_workflow))
        self.assertDictEqual(obj.trigger,
                             self.fake_history_workflow["trigger"])
        self.assertDictEqual(obj.trigger_type,
                             self.fake_history_workflow["trigger_type"])
        self.assertDictEqual(obj.trigger_instance,
                             self.fake_history_workflow["trigger_instance"])
        self.assertDictEqual(obj.rule, self.fake_history_workflow["rule"])
        self.assertDictEqual(obj.action, self.fake_history_workflow["action"])
        self.assertDictEqual(obj.runner, self.fake_history_workflow["runner"])
        self.assertEqual(obj.liveaction,
                         self.fake_history_workflow["liveaction"])
        self.assertIsNone(getattr(obj, "parent", None))
        self.assertListEqual(obj.children,
                             self.fake_history_workflow["children"])

        # Convert API object to DB model.
        model = ActionExecutionAPI.to_model(obj)
        self.assertEqual(str(model.id), obj.id)
        self.assertDictEqual(model.trigger,
                             self.fake_history_workflow["trigger"])
        self.assertDictEqual(model.trigger_type,
                             self.fake_history_workflow["trigger_type"])
        self.assertDictEqual(model.trigger_instance,
                             self.fake_history_workflow["trigger_instance"])
        self.assertDictEqual(model.rule, self.fake_history_workflow["rule"])
        self.assertDictEqual(model.action,
                             self.fake_history_workflow["action"])
        self.assertDictEqual(model.runner,
                             self.fake_history_workflow["runner"])
        doc = copy.deepcopy(self.fake_history_workflow["liveaction"])
        doc["start_timestamp"] = doc["start_timestamp"]
        doc["end_timestamp"] = doc["end_timestamp"]
        self.assertDictEqual(model.liveaction, doc)
        self.assertIsNone(getattr(model, "parent", None))
        self.assertListEqual(model.children,
                             self.fake_history_workflow["children"])

        # Convert DB model to API object.
        obj = ActionExecutionAPI.from_model(model)
        self.assertEqual(str(model.id), obj.id)
        self.assertDictEqual(obj.trigger,
                             self.fake_history_workflow["trigger"])
        self.assertDictEqual(obj.trigger_type,
                             self.fake_history_workflow["trigger_type"])
        self.assertDictEqual(obj.trigger_instance,
                             self.fake_history_workflow["trigger_instance"])
        self.assertDictEqual(obj.rule, self.fake_history_workflow["rule"])
        self.assertDictEqual(obj.action, self.fake_history_workflow["action"])
        self.assertDictEqual(obj.runner, self.fake_history_workflow["runner"])
        self.assertDictEqual(obj.liveaction,
                             self.fake_history_workflow["liveaction"])
        self.assertIsNone(getattr(obj, "parent", None))
        self.assertListEqual(obj.children,
                             self.fake_history_workflow["children"])
Example #12
0
    def _schedule_execution(self,
                            liveaction,
                            user=None,
                            context_string=None,
                            show_secrets=False):
        # Initialize execution context if it does not exist.
        if not hasattr(liveaction, 'context'):
            liveaction.context = dict()

        liveaction.context['user'] = user
        LOG.debug('User is: %s' % liveaction.context['user'])

        # Retrieve other st2 context from request header.
        if context_string:
            context = try_loads(context_string)
            if not isinstance(context, dict):
                raise ValueError(
                    'Unable to convert st2-context from the headers into JSON.'
                )
            liveaction.context.update(context)

        # Schedule the action execution.
        liveaction_db = LiveActionAPI.to_model(liveaction)
        liveaction_db, actionexecution_db = action_service.create_request(
            liveaction_db)

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

        try:
            liveaction_db.parameters = param_utils.render_live_params(
                runnertype_db.runner_parameters, action_db.parameters,
                liveaction_db.parameters, liveaction_db.context)
        except ParamException:
            # By this point the execution is already in the DB therefore need to mark it failed.
            _, e, tb = sys.exc_info()
            action_service.update_status(liveaction=liveaction_db,
                                         new_status=LIVEACTION_STATUS_FAILED,
                                         result={
                                             'error':
                                             str(e),
                                             'traceback':
                                             ''.join(
                                                 traceback.format_tb(tb, 20))
                                         })
            # Might be a good idea to return the actual ActionExecution rather than bubble up
            # the execption.
            raise ValueValidationException(str(e))

        liveaction_db = LiveAction.add_or_update(liveaction_db, publish=False)

        _, actionexecution_db = action_service.publish_request(
            liveaction_db, actionexecution_db)
        execution_api = ActionExecutionAPI.from_model(
            actionexecution_db, mask_secrets=(not show_secrets))

        return Response(json=execution_api, status=http_client.CREATED)
Example #13
0
    def delete(self, exec_id):
        """
        Stops a single execution.

        Handles requests:
            DELETE /actionexecutions/<id>

        """
        execution_api = self._get_one(id=exec_id)

        if not execution_api:
            abort(http_client.NOT_FOUND,
                  'Execution with id %s not found.' % exec_id)
            return

        liveaction_id = execution_api.liveaction['id']
        if not liveaction_id:
            abort(
                http_client.INTERNAL_SERVER_ERROR,
                'Execution object missing link to liveaction %s.' %
                liveaction_id)

        try:
            liveaction_db = LiveAction.get_by_id(liveaction_id)
        except:
            abort(
                http_client.INTERNAL_SERVER_ERROR,
                'Execution object missing link to liveaction %s.' %
                liveaction_id)
            return

        if liveaction_db.status == LIVEACTION_STATUS_CANCELED:
            abort(http_client.OK, 'Action is already in "canceled" state.')

        if liveaction_db.status not in CANCELABLE_STATES:
            abort(
                http_client.OK, 'Action cannot be canceled. State = %s.' %
                liveaction_db.status)
            return

        liveaction_db.status = 'canceled'
        liveaction_db.end_timestamp = date_utils.get_datetime_utc_now()
        liveaction_db.result = {'message': 'Action canceled by user.'}
        try:
            LiveAction.add_or_update(liveaction_db)
        except:
            LOG.exception(
                'Failed updating status to canceled for liveaction %s.',
                liveaction_db.id)
            abort(http_client.INTERNAL_SERVER_ERROR,
                  'Failed canceling execution.')
            return

        execution_db = execution_service.update_execution(liveaction_db)
        from_model_kwargs = self._get_from_model_kwargs_for_request(
            request=pecan.request)
        return ActionExecutionAPI.from_model(execution_db, from_model_kwargs)
Example #14
0
 def test_get_one(self):
     obj_id = random.choice(self.refs.keys())
     response = self.app.get('/v1/executions/%s' % obj_id)
     self.assertEqual(response.status_int, 200)
     self.assertIsInstance(response.json, dict)
     record = response.json
     fake_record = ActionExecutionAPI.from_model(self.refs[obj_id])
     self.assertEqual(record['id'], obj_id)
     self.assertDictEqual(record['action'], fake_record.action)
     self.assertDictEqual(record['runner'], fake_record.runner)
     self.assertDictEqual(record['liveaction'], fake_record.liveaction)
Example #15
0
 def test_get_one(self):
     obj_id = random.choice(list(self.refs.keys()))
     response = self.app.get('/v1/executions/%s' % obj_id)
     self.assertEqual(response.status_int, 200)
     self.assertIsInstance(response.json, dict)
     record = response.json
     fake_record = ActionExecutionAPI.from_model(self.refs[obj_id])
     self.assertEqual(record['id'], obj_id)
     self.assertDictEqual(record['action'], fake_record.action)
     self.assertDictEqual(record['runner'], fake_record.runner)
     self.assertDictEqual(record['liveaction'], fake_record.liveaction)
Example #16
0
    def test_model_partial(self):
        # Create API object.
        obj = ActionExecutionAPI(
            **copy.deepcopy(self.fake_history_subtasks[0]))
        self.assertIsNone(getattr(obj, 'trigger', None))
        self.assertIsNone(getattr(obj, 'trigger_type', None))
        self.assertIsNone(getattr(obj, 'trigger_instance', None))
        self.assertIsNone(getattr(obj, 'rule', None))
        self.assertDictEqual(obj.action,
                             self.fake_history_subtasks[0]['action'])
        self.assertDictEqual(obj.runner,
                             self.fake_history_subtasks[0]['runner'])
        self.assertDictEqual(obj.liveaction,
                             self.fake_history_subtasks[0]['liveaction'])
        self.assertEqual(obj.parent, self.fake_history_subtasks[0]['parent'])
        self.assertIsNone(getattr(obj, 'children', None))

        # Convert API object to DB model.
        model = ActionExecutionAPI.to_model(obj)
        self.assertEqual(str(model.id), obj.id)
        self.assertDictEqual(model.trigger, {})
        self.assertDictEqual(model.trigger_type, {})
        self.assertDictEqual(model.trigger_instance, {})
        self.assertDictEqual(model.rule, {})
        self.assertDictEqual(model.action,
                             self.fake_history_subtasks[0]['action'])
        self.assertDictEqual(model.runner,
                             self.fake_history_subtasks[0]['runner'])
        doc = copy.deepcopy(self.fake_history_subtasks[0]['liveaction'])
        doc['start_timestamp'] = doc['start_timestamp']
        doc['end_timestamp'] = doc['end_timestamp']

        self.assertDictEqual(model.liveaction, doc)
        self.assertEqual(model.parent, self.fake_history_subtasks[0]['parent'])
        self.assertListEqual(model.children, [])

        # Convert DB model to API object.
        obj = ActionExecutionAPI.from_model(model)
        self.assertEqual(str(model.id), obj.id)
        self.assertIsNone(getattr(obj, 'trigger', None))
        self.assertIsNone(getattr(obj, 'trigger_type', None))
        self.assertIsNone(getattr(obj, 'trigger_instance', None))
        self.assertIsNone(getattr(obj, 'rule', None))
        self.assertDictEqual(obj.action,
                             self.fake_history_subtasks[0]['action'])
        self.assertDictEqual(obj.runner,
                             self.fake_history_subtasks[0]['runner'])
        self.assertDictEqual(obj.liveaction,
                             self.fake_history_subtasks[0]['liveaction'])
        self.assertEqual(obj.parent, self.fake_history_subtasks[0]['parent'])
        self.assertIsNone(getattr(obj, 'children', None))
Example #17
0
    def delete(self, exec_id):
        """
        Stops a single execution.

        Handles requests:
            DELETE /executions/<id>

        """
        execution_api = self._get_one(id=exec_id)

        if not execution_api:
            abort(http_client.NOT_FOUND,
                  'Execution with id %s not found.' % exec_id)

        liveaction_id = execution_api.liveaction['id']
        if not liveaction_id:
            abort(
                http_client.INTERNAL_SERVER_ERROR,
                'Execution object missing link to liveaction %s.' %
                liveaction_id)

        try:
            liveaction_db = LiveAction.get_by_id(liveaction_id)
        except:
            abort(
                http_client.INTERNAL_SERVER_ERROR,
                'Execution object missing link to liveaction %s.' %
                liveaction_id)

        if liveaction_db.status == LIVEACTION_STATUS_CANCELED:
            abort(http_client.OK, 'Action is already in "canceled" state.')

        if liveaction_db.status not in CANCELABLE_STATES:
            abort(
                http_client.OK, 'Action cannot be canceled. State = %s.' %
                liveaction_db.status)

        try:
            (liveaction_db,
             execution_db) = action_service.request_cancellation(
                 liveaction_db, self._get_requester())
        except:
            LOG.exception('Failed requesting cancellation for liveaction %s.',
                          liveaction_db.id)
            abort(http_client.INTERNAL_SERVER_ERROR,
                  'Failed canceling execution.')

        from_model_kwargs = self._get_from_model_kwargs_for_request(
            request=pecan.request)

        return ActionExecutionAPI.from_model(execution_db, from_model_kwargs)
Example #18
0
    def delete(self, id, requester_user, show_secrets=False):
        """
        Stops a single execution.

        Handles requests:
            DELETE /executions/<id>

        """
        if not requester_user:
            requester_user = UserDB(cfg.CONF.system_user.user)

        from_model_kwargs = {
            'mask_secrets': self._get_mask_secrets(requester_user, show_secrets=show_secrets)
        }
        execution_api = self._get_one_by_id(id=id, requester_user=requester_user,
                                            from_model_kwargs=from_model_kwargs,
                                            permission_type=PermissionType.EXECUTION_STOP)

        if not execution_api:
            abort(http_client.NOT_FOUND, 'Execution with id %s not found.' % id)

        liveaction_id = execution_api.liveaction['id']
        if not liveaction_id:
            abort(http_client.INTERNAL_SERVER_ERROR,
                  'Execution object missing link to liveaction %s.' % liveaction_id)

        try:
            liveaction_db = LiveAction.get_by_id(liveaction_id)
        except:
            abort(http_client.INTERNAL_SERVER_ERROR,
                  'Execution object missing link to liveaction %s.' % liveaction_id)

        if liveaction_db.status == action_constants.LIVEACTION_STATUS_CANCELED:
            LOG.info(
                'Action %s already in "canceled" state; \
                returning execution object.' % liveaction_db.id
            )
            return execution_api

        if liveaction_db.status not in action_constants.LIVEACTION_CANCELABLE_STATES:
            abort(http_client.OK, 'Action cannot be canceled. State = %s.' % liveaction_db.status)

        try:
            (liveaction_db, execution_db) = action_service.request_cancellation(
                liveaction_db, requester_user.name or cfg.CONF.system_user.user)
        except:
            LOG.exception('Failed requesting cancellation for liveaction %s.', liveaction_db.id)
            abort(http_client.INTERNAL_SERVER_ERROR, 'Failed canceling execution.')

        return ActionExecutionAPI.from_model(execution_db,
                                             mask_secrets=from_model_kwargs['mask_secrets'])
Example #19
0
    def delete(self, exec_id):
        """
        Stops a single execution.

        Handles requests:
            DELETE /actionexecutions/<id>

        """
        execution_api = self._get_one(id=exec_id)

        if not execution_api:
            abort(http_client.NOT_FOUND, 'Execution with id %s not found.' % exec_id)
            return

        liveaction_id = execution_api.liveaction['id']
        if not liveaction_id:
            abort(http_client.INTERNAL_SERVER_ERROR,
                  'Execution object missing link to liveaction %s.' % liveaction_id)

        try:
            liveaction_db = LiveAction.get_by_id(liveaction_id)
        except:
            abort(http_client.INTERNAL_SERVER_ERROR,
                  'Execution object missing link to liveaction %s.' % liveaction_id)
            return

        if liveaction_db.status == LIVEACTION_STATUS_CANCELED:
            abort(http_client.OK,
                  'Action is already in "canceled" state.')

        if liveaction_db.status not in CANCELABLE_STATES:
            abort(http_client.OK,
                  'Action cannot be canceled. State = %s.' % liveaction_db.status)
            return

        liveaction_db.status = 'canceled'
        liveaction_db.end_timestamp = date_utils.get_datetime_utc_now()
        liveaction_db.result = {'message': 'Action canceled by user.'}
        try:
            LiveAction.add_or_update(liveaction_db)
        except:
            LOG.exception('Failed updating status to canceled for liveaction %s.',
                          liveaction_db.id)
            abort(http_client.INTERNAL_SERVER_ERROR, 'Failed canceling execution.')
            return

        execution_db = execution_service.update_execution(liveaction_db)
        from_model_kwargs = self._get_from_model_kwargs_for_request(request=pecan.request)
        return ActionExecutionAPI.from_model(execution_db, from_model_kwargs)
Example #20
0
    def _bootstrap(self):
        marker = self._get_export_marker_from_db()
        LOG.info('Using marker %s...' % marker)
        missed_executions = self._get_missed_executions_from_db(export_marker=marker)
        LOG.info('Found %d executions not exported yet...', len(missed_executions))

        for missed_execution in missed_executions:
            if missed_execution.status not in COMPLETION_STATUSES:
                continue
            execution_api = ActionExecutionAPI.from_model(missed_execution, mask_secrets=True)
            try:
                LOG.debug('Missed execution %s', execution_api)
                self.pending_executions.put_nowait(execution_api)
            except:
                LOG.exception('Failed adding execution to in-memory queue.')
                continue
        LOG.info('Bootstrapped executions...')
Example #21
0
    def delete(self, exec_id):
        """
        Stops a single execution.

        Handles requests:
            DELETE /executions/<id>

        """
        execution_api = self._get_one(id=exec_id)

        if not execution_api:
            abort(http_client.NOT_FOUND, 'Execution with id %s not found.' % exec_id)

        liveaction_id = execution_api.liveaction['id']
        if not liveaction_id:
            abort(http_client.INTERNAL_SERVER_ERROR,
                  'Execution object missing link to liveaction %s.' % liveaction_id)

        try:
            liveaction_db = LiveAction.get_by_id(liveaction_id)
        except:
            abort(http_client.INTERNAL_SERVER_ERROR,
                  'Execution object missing link to liveaction %s.' % liveaction_id)

        if liveaction_db.status == LIVEACTION_STATUS_CANCELED:
            LOG.info(
                'Action %s already in "canceled" state; \
                returning execution object.' % liveaction_db.id
            )
            return execution_api

        if liveaction_db.status not in LIVEACTION_CANCELABLE_STATES:
            abort(http_client.OK, 'Action cannot be canceled. State = %s.' % liveaction_db.status)

        try:
            (liveaction_db, execution_db) = action_service.request_cancellation(
                liveaction_db, get_requester())
        except:
            LOG.exception('Failed requesting cancellation for liveaction %s.', liveaction_db.id)
            abort(http_client.INTERNAL_SERVER_ERROR, 'Failed canceling execution.')

        from_model_kwargs = self._get_from_model_kwargs_for_request(request=pecan.request)

        return ActionExecutionAPI.from_model(execution_db, from_model_kwargs)
Example #22
0
    def post(self, execution):
        try:
            # Initialize execution context if it does not exist.
            if not hasattr(execution, 'context'):
                execution.context = dict()

            # Retrieve username of the authed user (note - if auth is disabled, user will not be
            # set so we fall back to the system user name)
            request_token = pecan.request.context.get('token', None)

            if request_token:
                user = request_token.user
            else:
                user = cfg.CONF.system_user.user

            execution.context['user'] = user

            # Retrieve other st2 context from request header.
            if ('st2-context' in pecan.request.headers
                    and pecan.request.headers['st2-context']):
                context = jsonify.try_loads(
                    pecan.request.headers['st2-context'])
                if not isinstance(context, dict):
                    raise ValueError(
                        'Unable to convert st2-context from the headers into JSON.'
                    )
                execution.context.update(context)

            # Schedule the action execution.
            liveactiondb = LiveActionAPI.to_model(execution)
            _, actionexecutiondb = action_service.schedule(liveactiondb)
            return ActionExecutionAPI.from_model(actionexecutiondb)
        except ValueError as e:
            LOG.exception('Unable to execute action.')
            abort(http_client.BAD_REQUEST, str(e))
        except jsonschema.ValidationError as e:
            LOG.exception(
                'Unable to execute action. Parameter validation failed.')
            abort(http_client.BAD_REQUEST, str(e))
        except Exception as e:
            LOG.exception(
                'Unable to execute action. Unexpected error encountered.')
            abort(http_client.INTERNAL_SERVER_ERROR, str(e))
Example #23
0
    def _schedule_execution(self, liveaction):
        # Initialize execution context if it does not exist.
        if not hasattr(liveaction, 'context'):
            liveaction.context = dict()

        liveaction.context['user'] = get_requester()
        LOG.debug('User is: %s' % liveaction.context['user'])

        # Retrieve other st2 context from request header.
        if 'st2-context' in pecan.request.headers and pecan.request.headers[
                'st2-context']:
            context = jsonify.try_loads(pecan.request.headers['st2-context'])
            if not isinstance(context, dict):
                raise ValueError(
                    'Unable to convert st2-context from the headers into JSON.'
                )
            liveaction.context.update(context)

        # Schedule the action execution.
        liveaction_db = LiveActionAPI.to_model(liveaction)
        liveaction_db, actionexecution_db = action_service.create_request(
            liveaction_db)

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

        try:
            liveaction_db.parameters = param_utils.render_live_params(
                runnertype_db.runner_parameters, action_db.parameters,
                liveaction_db.parameters, liveaction_db.context)
        except ParamException as e:
            raise ValueValidationException(str(e))

        liveaction_db = LiveAction.add_or_update(liveaction_db, publish=False)

        _, actionexecution_db = action_service.publish_request(
            liveaction_db, actionexecution_db)
        from_model_kwargs = self._get_from_model_kwargs_for_request(
            request=pecan.request)
        return ActionExecutionAPI.from_model(actionexecution_db,
                                             from_model_kwargs)
Example #24
0
    def test_model_complete(self):

        # Create API object.
        obj = ActionExecutionAPI(**copy.deepcopy(self.fake_history_workflow))
        self.assertDictEqual(obj.trigger, self.fake_history_workflow['trigger'])
        self.assertDictEqual(obj.trigger_type, self.fake_history_workflow['trigger_type'])
        self.assertDictEqual(obj.trigger_instance, self.fake_history_workflow['trigger_instance'])
        self.assertDictEqual(obj.rule, self.fake_history_workflow['rule'])
        self.assertDictEqual(obj.action, self.fake_history_workflow['action'])
        self.assertDictEqual(obj.runner, self.fake_history_workflow['runner'])
        self.assertEquals(obj.liveaction, self.fake_history_workflow['liveaction'])
        self.assertIsNone(getattr(obj, 'parent', None))
        self.assertListEqual(obj.children, self.fake_history_workflow['children'])

        # Convert API object to DB model.
        model = ActionExecutionAPI.to_model(obj)
        self.assertEqual(str(model.id), obj.id)
        self.assertDictEqual(model.trigger, self.fake_history_workflow['trigger'])
        self.assertDictEqual(model.trigger_type, self.fake_history_workflow['trigger_type'])
        self.assertDictEqual(model.trigger_instance, self.fake_history_workflow['trigger_instance'])
        self.assertDictEqual(model.rule, self.fake_history_workflow['rule'])
        self.assertDictEqual(model.action, self.fake_history_workflow['action'])
        self.assertDictEqual(model.runner, self.fake_history_workflow['runner'])
        doc = copy.deepcopy(self.fake_history_workflow['liveaction'])
        doc['start_timestamp'] = doc['start_timestamp']
        doc['end_timestamp'] = doc['end_timestamp']
        self.assertDictEqual(model.liveaction, doc)
        self.assertIsNone(getattr(model, 'parent', None))
        self.assertListEqual(model.children, self.fake_history_workflow['children'])

        # Convert DB model to API object.
        obj = ActionExecutionAPI.from_model(model)
        self.assertEqual(str(model.id), obj.id)
        self.assertDictEqual(obj.trigger, self.fake_history_workflow['trigger'])
        self.assertDictEqual(obj.trigger_type, self.fake_history_workflow['trigger_type'])
        self.assertDictEqual(obj.trigger_instance, self.fake_history_workflow['trigger_instance'])
        self.assertDictEqual(obj.rule, self.fake_history_workflow['rule'])
        self.assertDictEqual(obj.action, self.fake_history_workflow['action'])
        self.assertDictEqual(obj.runner, self.fake_history_workflow['runner'])
        self.assertDictEqual(obj.liveaction, self.fake_history_workflow['liveaction'])
        self.assertIsNone(getattr(obj, 'parent', None))
        self.assertListEqual(obj.children, self.fake_history_workflow['children'])
Example #25
0
    def test_model_partial(self):
        # Create API object.
        obj = ActionExecutionAPI(**copy.deepcopy(self.fake_history_subtasks[0]))
        self.assertIsNone(getattr(obj, 'trigger', None))
        self.assertIsNone(getattr(obj, 'trigger_type', None))
        self.assertIsNone(getattr(obj, 'trigger_instance', None))
        self.assertIsNone(getattr(obj, 'rule', None))
        self.assertDictEqual(obj.action, self.fake_history_subtasks[0]['action'])
        self.assertDictEqual(obj.runner, self.fake_history_subtasks[0]['runner'])
        self.assertDictEqual(obj.liveaction, self.fake_history_subtasks[0]['liveaction'])
        self.assertEqual(obj.parent, self.fake_history_subtasks[0]['parent'])
        self.assertIsNone(getattr(obj, 'children', None))

        # Convert API object to DB model.
        model = ActionExecutionAPI.to_model(obj)
        self.assertEqual(str(model.id), obj.id)
        self.assertDictEqual(model.trigger, {})
        self.assertDictEqual(model.trigger_type, {})
        self.assertDictEqual(model.trigger_instance, {})
        self.assertDictEqual(model.rule, {})
        self.assertDictEqual(model.action, self.fake_history_subtasks[0]['action'])
        self.assertDictEqual(model.runner, self.fake_history_subtasks[0]['runner'])
        doc = copy.deepcopy(self.fake_history_subtasks[0]['liveaction'])
        doc['start_timestamp'] = doc['start_timestamp']
        doc['end_timestamp'] = doc['end_timestamp']

        self.assertDictEqual(model.liveaction, doc)
        self.assertEqual(model.parent, self.fake_history_subtasks[0]['parent'])
        self.assertListEqual(model.children, [])

        # Convert DB model to API object.
        obj = ActionExecutionAPI.from_model(model)
        self.assertEqual(str(model.id), obj.id)
        self.assertIsNone(getattr(obj, 'trigger', None))
        self.assertIsNone(getattr(obj, 'trigger_type', None))
        self.assertIsNone(getattr(obj, 'trigger_instance', None))
        self.assertIsNone(getattr(obj, 'rule', None))
        self.assertDictEqual(obj.action, self.fake_history_subtasks[0]['action'])
        self.assertDictEqual(obj.runner, self.fake_history_subtasks[0]['runner'])
        self.assertDictEqual(obj.liveaction, self.fake_history_subtasks[0]['liveaction'])
        self.assertEqual(obj.parent, self.fake_history_subtasks[0]['parent'])
        self.assertIsNone(getattr(obj, 'children', None))
Example #26
0
    def _schedule_execution(self, liveaction, user=None):
        # Initialize execution context if it does not exist.
        if not hasattr(liveaction, 'context'):
            liveaction.context = dict()

        liveaction.context['user'] = user
        LOG.debug('User is: %s' % liveaction.context['user'])

        # Retrieve other st2 context from request header.
        if 'st2-context' in pecan.request.headers and pecan.request.headers['st2-context']:
            context = jsonify.try_loads(pecan.request.headers['st2-context'])
            if not isinstance(context, dict):
                raise ValueError('Unable to convert st2-context from the headers into JSON.')
            liveaction.context.update(context)

        # Schedule the action execution.
        liveaction_db = LiveActionAPI.to_model(liveaction)
        liveaction_db, actionexecution_db = action_service.create_request(liveaction_db)

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

        try:
            liveaction_db.parameters = param_utils.render_live_params(
                runnertype_db.runner_parameters, action_db.parameters, liveaction_db.parameters,
                liveaction_db.context)
        except ParamException:
            # By this point the execution is already in the DB therefore need to mark it failed.
            _, e, tb = sys.exc_info()
            action_service.update_status(
                liveaction=liveaction_db,
                new_status=LIVEACTION_STATUS_FAILED,
                result={'error': str(e), 'traceback': ''.join(traceback.format_tb(tb, 20))})
            # Might be a good idea to return the actual ActionExecution rather than bubble up
            # the execption.
            raise ValueValidationException(str(e))

        liveaction_db = LiveAction.add_or_update(liveaction_db, publish=False)

        _, actionexecution_db = action_service.publish_request(liveaction_db, actionexecution_db)
        from_model_kwargs = self._get_from_model_kwargs_for_request(request=pecan.request)
        return ActionExecutionAPI.from_model(actionexecution_db, from_model_kwargs)
Example #27
0
    def _schedule_execution(self, liveaction):
        # Initialize execution context if it does not exist.
        if not hasattr(liveaction, 'context'):
            liveaction.context = dict()

        liveaction.context['user'] = self._get_requester()
        LOG.debug('User is: %s' % liveaction.context['user'])

        # Retrieve other st2 context from request header.
        if 'st2-context' in pecan.request.headers and pecan.request.headers['st2-context']:
            context = jsonify.try_loads(pecan.request.headers['st2-context'])
            if not isinstance(context, dict):
                raise ValueError('Unable to convert st2-context from the headers into JSON.')
            liveaction.context.update(context)

        # Schedule the action execution.
        liveactiondb = LiveActionAPI.to_model(liveaction)
        _, actionexecutiondb = action_service.request(liveactiondb)
        from_model_kwargs = self._get_from_model_kwargs_for_request(request=pecan.request)
        return ActionExecutionAPI.from_model(actionexecutiondb, from_model_kwargs)
Example #28
0
    def post(self, execution):
        try:
            # Initialize execution context if it does not exist.
            if not hasattr(execution, 'context'):
                execution.context = dict()

            # Retrieve username of the authed user (note - if auth is disabled, user will not be
            # set so we fall back to the system user name)
            request_token = pecan.request.context.get('token', None)

            if request_token:
                user = request_token.user
            else:
                user = cfg.CONF.system_user.user

            execution.context['user'] = user

            # Retrieve other st2 context from request header.
            if ('st2-context' in pecan.request.headers and pecan.request.headers['st2-context']):
                context = jsonify.try_loads(pecan.request.headers['st2-context'])
                if not isinstance(context, dict):
                    raise ValueError('Unable to convert st2-context from the headers into JSON.')
                execution.context.update(context)

            # Schedule the action execution.
            liveactiondb = LiveActionAPI.to_model(execution)
            _, actionexecutiondb = action_service.schedule(liveactiondb)
            return ActionExecutionAPI.from_model(actionexecutiondb)
        except ValueError as e:
            LOG.exception('Unable to execute action.')
            abort(http_client.BAD_REQUEST, str(e))
        except jsonschema.ValidationError as e:
            LOG.exception('Unable to execute action. Parameter validation failed.')
            abort(http_client.BAD_REQUEST, str(e))
        except Exception as e:
            LOG.exception('Unable to execute action. Unexpected error encountered.')
            abort(http_client.INTERNAL_SERVER_ERROR, str(e))
Example #29
0
    def _append_view_properties(self, rule_enforcement_apis):
        """
        Method which appends corresponding execution (if available) and trigger instance object
        properties.
        """
        trigger_instance_ids = set([])
        execution_ids = []

        for rule_enforcement_api in rule_enforcement_apis:
            if rule_enforcement_api.get('trigger_instance_id', None):
                trigger_instance_ids.add(str(rule_enforcement_api['trigger_instance_id']))

            if rule_enforcement_api.get('execution_id', None):
                execution_ids.append(rule_enforcement_api['execution_id'])

        # 1. Retrieve corresponding execution objects
        # NOTE: Executions contain a lot of field and could contain a lot of data so we only
        # retrieve fields we need
        only_fields = [
            'id',

            'action.ref',
            'action.parameters',

            'runner.name',
            'runner.runner_parameters',

            'parameters',
            'status'
        ]
        execution_dbs = ActionExecution.query(id__in=execution_ids,
                                              only_fields=only_fields)

        execution_dbs_by_id = {}
        for execution_db in execution_dbs:
            execution_dbs_by_id[str(execution_db.id)] = execution_db

        # 2. Retrieve corresponding trigger instance objects
        trigger_instance_dbs = TriggerInstance.query(id__in=list(trigger_instance_ids))

        trigger_instance_dbs_by_id = {}

        for trigger_instance_db in trigger_instance_dbs:
            trigger_instance_dbs_by_id[str(trigger_instance_db.id)] = trigger_instance_db

        # Ammend rule enforcement objects with additional data
        for rule_enforcement_api in rule_enforcement_apis:
            rule_enforcement_api['trigger_instance'] = {}
            rule_enforcement_api['execution'] = {}

            trigger_instance_id = rule_enforcement_api.get('trigger_instance_id', None)
            execution_id = rule_enforcement_api.get('execution_id', None)

            trigger_instance_db = trigger_instance_dbs_by_id.get(trigger_instance_id, None)
            execution_db = execution_dbs_by_id.get(execution_id, None)

            if trigger_instance_db:
                trigger_instance_api = TriggerInstanceAPI.from_model(trigger_instance_db)
                rule_enforcement_api['trigger_instance'] = trigger_instance_api

            if execution_db:
                execution_api = ActionExecutionAPI.from_model(execution_db)
                rule_enforcement_api['execution'] = execution_api

        return rule_enforcement_apis
Example #30
0
    def _schedule_execution(self, liveaction, requester_user, action_db, user=None,
                            context_string=None, show_secrets=False):
        # Initialize execution context if it does not exist.
        if not hasattr(liveaction, 'context'):
            liveaction.context = dict()

        liveaction.context['user'] = user
        liveaction.context['pack'] = action_db.pack

        LOG.debug('User is: %s' % liveaction.context['user'])

        # Retrieve other st2 context from request header.
        if context_string:
            context = try_loads(context_string)
            if not isinstance(context, dict):
                raise ValueError('Unable to convert st2-context from the headers into JSON.')
            liveaction.context.update(context)

        # Include RBAC context (if RBAC is available and enabled)
        if cfg.CONF.rbac.enable:
            user_db = UserDB(name=user)
            role_dbs = rbac_service.get_roles_for_user(user_db=user_db, include_remote=True)
            roles = [role_db.name for role_db in role_dbs]
            liveaction.context['rbac'] = {
                'user': user,
                'roles': roles
            }

        # Schedule the action execution.
        liveaction_db = LiveActionAPI.to_model(liveaction)
        runnertype_db = action_utils.get_runnertype_by_name(action_db.runner_type['name'])

        try:
            liveaction_db.parameters = param_utils.render_live_params(
                runnertype_db.runner_parameters, action_db.parameters, liveaction_db.parameters,
                liveaction_db.context)
        except param_exc.ParamException:
            # We still need to create a request, so liveaction_db is assigned an ID
            liveaction_db, actionexecution_db = action_service.create_request(
                liveaction=liveaction_db,
                action_db=action_db,
                runnertype_db=runnertype_db)

            # By this point the execution is already in the DB therefore need to mark it failed.
            _, e, tb = sys.exc_info()
            action_service.update_status(
                liveaction=liveaction_db,
                new_status=action_constants.LIVEACTION_STATUS_FAILED,
                result={'error': six.text_type(e),
                        'traceback': ''.join(traceback.format_tb(tb, 20))})
            # Might be a good idea to return the actual ActionExecution rather than bubble up
            # the exception.
            raise validation_exc.ValueValidationException(six.text_type(e))

        # The request should be created after the above call to render_live_params
        # so any templates in live parameters have a chance to render.
        liveaction_db, actionexecution_db = action_service.create_request(liveaction=liveaction_db,
            action_db=action_db,
            runnertype_db=runnertype_db)

        _, actionexecution_db = action_service.publish_request(liveaction_db, actionexecution_db)
        mask_secrets = self._get_mask_secrets(requester_user, show_secrets=show_secrets)
        execution_api = ActionExecutionAPI.from_model(actionexecution_db, mask_secrets=mask_secrets)

        return Response(json=execution_api, status=http_client.CREATED)
Example #31
0
    def put(self, id, liveaction_api, requester_user, show_secrets=False):
        """
        Updates a single execution.

        Handles requests:
            PUT /executions/<id>

        """
        if not requester_user:
            requester_user = UserDB(cfg.CONF.system_user.user)

        from_model_kwargs = {
            'mask_secrets':
            self._get_mask_secrets(requester_user, show_secrets=show_secrets)
        }

        execution_api = self._get_one_by_id(
            id=id,
            requester_user=requester_user,
            from_model_kwargs=from_model_kwargs,
            permission_type=PermissionType.EXECUTION_STOP)

        if not execution_api:
            abort(http_client.NOT_FOUND,
                  'Execution with id %s not found.' % id)

        liveaction_id = execution_api.liveaction['id']
        if not liveaction_id:
            abort(
                http_client.INTERNAL_SERVER_ERROR,
                'Execution object missing link to liveaction %s.' %
                liveaction_id)

        try:
            liveaction_db = LiveAction.get_by_id(liveaction_id)
        except:
            abort(
                http_client.INTERNAL_SERVER_ERROR,
                'Execution object missing link to liveaction %s.' %
                liveaction_id)

        if liveaction_db.status in action_constants.LIVEACTION_COMPLETED_STATES:
            abort(http_client.BAD_REQUEST,
                  'Execution is already in completed state.')

        def update_status(liveaction_api, liveaction_db):
            status = liveaction_api.status
            result = getattr(liveaction_api, 'result', None)
            liveaction_db = action_service.update_status(
                liveaction_db, status, result)
            actionexecution_db = ActionExecution.get(
                liveaction__id=str(liveaction_db.id))
            return (liveaction_db, actionexecution_db)

        try:
            if (liveaction_db.status
                    == action_constants.LIVEACTION_STATUS_CANCELING
                    and liveaction_api.status
                    == action_constants.LIVEACTION_STATUS_CANCELED):
                if action_service.is_children_active(liveaction_id):
                    liveaction_api.status = action_constants.LIVEACTION_STATUS_CANCELING
                liveaction_db, actionexecution_db = update_status(
                    liveaction_api, liveaction_db)
            elif (liveaction_api.status
                  == action_constants.LIVEACTION_STATUS_CANCELING
                  or liveaction_api.status
                  == action_constants.LIVEACTION_STATUS_CANCELED):
                liveaction_db, actionexecution_db = action_service.request_cancellation(
                    liveaction_db, requester_user.name
                    or cfg.CONF.system_user.user)
            elif (liveaction_db.status
                  == action_constants.LIVEACTION_STATUS_PAUSING
                  and liveaction_api.status
                  == action_constants.LIVEACTION_STATUS_PAUSED):
                if action_service.is_children_active(liveaction_id):
                    liveaction_api.status = action_constants.LIVEACTION_STATUS_PAUSING
                liveaction_db, actionexecution_db = update_status(
                    liveaction_api, liveaction_db)
            elif (liveaction_api.status
                  == action_constants.LIVEACTION_STATUS_PAUSING
                  or liveaction_api.status
                  == action_constants.LIVEACTION_STATUS_PAUSED):
                liveaction_db, actionexecution_db = action_service.request_pause(
                    liveaction_db, requester_user.name
                    or cfg.CONF.system_user.user)
            elif liveaction_api.status == action_constants.LIVEACTION_STATUS_RESUMING:
                liveaction_db, actionexecution_db = action_service.request_resume(
                    liveaction_db, requester_user.name
                    or cfg.CONF.system_user.user)
            else:
                liveaction_db, actionexecution_db = update_status(
                    liveaction_api, liveaction_db)
        except runner_exc.InvalidActionRunnerOperationError as e:
            LOG.exception('Failed updating liveaction %s. %s',
                          liveaction_db.id, str(e))
            abort(http_client.BAD_REQUEST,
                  'Failed updating execution. %s' % str(e))
        except runner_exc.UnexpectedActionExecutionStatusError as e:
            LOG.exception('Failed updating liveaction %s. %s',
                          liveaction_db.id, str(e))
            abort(http_client.BAD_REQUEST,
                  'Failed updating execution. %s' % str(e))
        except Exception as e:
            LOG.exception('Failed updating liveaction %s. %s',
                          liveaction_db.id, str(e))
            abort(http_client.INTERNAL_SERVER_ERROR,
                  'Failed updating execution due to unexpected error.')

        mask_secrets = self._get_mask_secrets(requester_user,
                                              show_secrets=show_secrets)
        execution_api = ActionExecutionAPI.from_model(
            actionexecution_db, mask_secrets=mask_secrets)

        return execution_api
Example #32
0
    def _schedule_execution(self,
                            liveaction,
                            requester_user,
                            user=None,
                            context_string=None,
                            show_secrets=False,
                            pack=None):
        # Initialize execution context if it does not exist.
        if not hasattr(liveaction, 'context'):
            liveaction.context = dict()

        liveaction.context['user'] = user
        liveaction.context['pack'] = pack
        LOG.debug('User is: %s' % liveaction.context['user'])

        # Retrieve other st2 context from request header.
        if context_string:
            context = try_loads(context_string)
            if not isinstance(context, dict):
                raise ValueError(
                    'Unable to convert st2-context from the headers into JSON.'
                )
            liveaction.context.update(context)

        # Include RBAC context (if RBAC is available and enabled)
        if cfg.CONF.rbac.enable:
            user_db = UserDB(name=user)
            role_dbs = rbac_service.get_roles_for_user(user_db=user_db,
                                                       include_remote=True)
            roles = [role_db.name for role_db in role_dbs]
            liveaction.context['rbac'] = {'user': user, 'roles': roles}

        # Schedule the action execution.
        liveaction_db = LiveActionAPI.to_model(liveaction)
        action_db = action_utils.get_action_by_ref(liveaction_db.action)
        runnertype_db = action_utils.get_runnertype_by_name(
            action_db.runner_type['name'])

        try:
            liveaction_db.parameters = param_utils.render_live_params(
                runnertype_db.runner_parameters, action_db.parameters,
                liveaction_db.parameters, liveaction_db.context)
        except param_exc.ParamException:

            # We still need to create a request, so liveaction_db is assigned an ID
            liveaction_db, actionexecution_db = action_service.create_request(
                liveaction_db)

            # By this point the execution is already in the DB therefore need to mark it failed.
            _, e, tb = sys.exc_info()
            action_service.update_status(
                liveaction=liveaction_db,
                new_status=action_constants.LIVEACTION_STATUS_FAILED,
                result={
                    'error': str(e),
                    'traceback': ''.join(traceback.format_tb(tb, 20))
                })
            # Might be a good idea to return the actual ActionExecution rather than bubble up
            # the exception.
            raise validation_exc.ValueValidationException(str(e))

        # The request should be created after the above call to render_live_params
        # so any templates in live parameters have a chance to render.
        liveaction_db, actionexecution_db = action_service.create_request(
            liveaction_db)
        liveaction_db = LiveAction.add_or_update(liveaction_db, publish=False)

        _, actionexecution_db = action_service.publish_request(
            liveaction_db, actionexecution_db)
        mask_secrets = self._get_mask_secrets(requester_user,
                                              show_secrets=show_secrets)
        execution_api = ActionExecutionAPI.from_model(
            actionexecution_db, mask_secrets=mask_secrets)

        return Response(json=execution_api, status=http_client.CREATED)
Example #33
0
    def delete(self, id, requester_user, show_secrets=False):
        """
        Stops a single execution.

        Handles requests:
            DELETE /executions/<id>

        """
        if not requester_user:
            requester_user = UserDB(name=cfg.CONF.system_user.user)

        from_model_kwargs = {
            "mask_secrets":
            self._get_mask_secrets(requester_user, show_secrets=show_secrets)
        }
        execution_api = self._get_one_by_id(
            id=id,
            requester_user=requester_user,
            from_model_kwargs=from_model_kwargs,
            permission_type=PermissionType.EXECUTION_STOP,
        )

        if not execution_api:
            abort(http_client.NOT_FOUND,
                  "Execution with id %s not found." % id)

        liveaction_id = execution_api.liveaction["id"]
        if not liveaction_id:
            abort(
                http_client.INTERNAL_SERVER_ERROR,
                "Execution object missing link to liveaction %s." %
                liveaction_id,
            )

        try:
            liveaction_db = LiveAction.get_by_id(liveaction_id)
        except:
            abort(
                http_client.INTERNAL_SERVER_ERROR,
                "Execution object missing link to liveaction %s." %
                liveaction_id,
            )

        if liveaction_db.status == action_constants.LIVEACTION_STATUS_CANCELED:
            LOG.info('Action %s already in "canceled" state; \
                returning execution object.' % liveaction_db.id)
            return execution_api

        if liveaction_db.status not in action_constants.LIVEACTION_CANCELABLE_STATES:
            abort(
                http_client.OK,
                "Action cannot be canceled. State = %s." %
                liveaction_db.status,
            )

        try:
            (liveaction_db,
             execution_db) = action_service.request_cancellation(
                 liveaction_db, requester_user.name
                 or cfg.CONF.system_user.user)
        except:
            LOG.exception("Failed requesting cancellation for liveaction %s.",
                          liveaction_db.id)
            abort(http_client.INTERNAL_SERVER_ERROR,
                  "Failed canceling execution.")

        return ActionExecutionAPI.from_model(
            execution_db, mask_secrets=from_model_kwargs["mask_secrets"])
Example #34
0
    def put(self, id, liveaction_api, requester_user, show_secrets=False):
        """
        Updates a single execution.

        Handles requests:
            PUT /executions/<id>

        """
        if not requester_user:
            requester_user = UserDB(cfg.CONF.system_user.user)

        from_model_kwargs = {
            'mask_secrets': self._get_mask_secrets(requester_user, show_secrets=show_secrets)
        }

        execution_api = self._get_one_by_id(id=id, requester_user=requester_user,
                                            from_model_kwargs=from_model_kwargs,
                                            permission_type=PermissionType.EXECUTION_STOP)

        if not execution_api:
            abort(http_client.NOT_FOUND, 'Execution with id %s not found.' % id)

        liveaction_id = execution_api.liveaction['id']
        if not liveaction_id:
            abort(http_client.INTERNAL_SERVER_ERROR,
                  'Execution object missing link to liveaction %s.' % liveaction_id)

        try:
            liveaction_db = LiveAction.get_by_id(liveaction_id)
        except:
            abort(http_client.INTERNAL_SERVER_ERROR,
                  'Execution object missing link to liveaction %s.' % liveaction_id)

        if liveaction_db.status in action_constants.LIVEACTION_COMPLETED_STATES:
            abort(http_client.BAD_REQUEST, 'Execution is already in completed state.')

        def update_status(liveaction_api, liveaction_db):
            status = liveaction_api.status
            result = getattr(liveaction_api, 'result', None)
            liveaction_db = action_service.update_status(liveaction_db, status, result)
            actionexecution_db = ActionExecution.get(liveaction__id=str(liveaction_db.id))
            return (liveaction_db, actionexecution_db)

        try:
            if (liveaction_db.status == action_constants.LIVEACTION_STATUS_CANCELING and
                    liveaction_api.status == action_constants.LIVEACTION_STATUS_CANCELED):
                if action_service.is_children_active(liveaction_id):
                    liveaction_api.status = action_constants.LIVEACTION_STATUS_CANCELING
                liveaction_db, actionexecution_db = update_status(liveaction_api, liveaction_db)
            elif (liveaction_api.status == action_constants.LIVEACTION_STATUS_CANCELING or
                    liveaction_api.status == action_constants.LIVEACTION_STATUS_CANCELED):
                liveaction_db, actionexecution_db = action_service.request_cancellation(
                    liveaction_db, requester_user.name or cfg.CONF.system_user.user)
            elif (liveaction_db.status == action_constants.LIVEACTION_STATUS_PAUSING and
                    liveaction_api.status == action_constants.LIVEACTION_STATUS_PAUSED):
                if action_service.is_children_active(liveaction_id):
                    liveaction_api.status = action_constants.LIVEACTION_STATUS_PAUSING
                liveaction_db, actionexecution_db = update_status(liveaction_api, liveaction_db)
            elif (liveaction_api.status == action_constants.LIVEACTION_STATUS_PAUSING or
                    liveaction_api.status == action_constants.LIVEACTION_STATUS_PAUSED):
                liveaction_db, actionexecution_db = action_service.request_pause(
                    liveaction_db, requester_user.name or cfg.CONF.system_user.user)
            elif liveaction_api.status == action_constants.LIVEACTION_STATUS_RESUMING:
                liveaction_db, actionexecution_db = action_service.request_resume(
                    liveaction_db, requester_user.name or cfg.CONF.system_user.user)
            else:
                liveaction_db, actionexecution_db = update_status(liveaction_api, liveaction_db)
        except runner_exc.InvalidActionRunnerOperationError as e:
            LOG.exception('Failed updating liveaction %s. %s', liveaction_db.id, six.text_type(e))
            abort(http_client.BAD_REQUEST, 'Failed updating execution. %s' % six.text_type(e))
        except runner_exc.UnexpectedActionExecutionStatusError as e:
            LOG.exception('Failed updating liveaction %s. %s', liveaction_db.id, six.text_type(e))
            abort(http_client.BAD_REQUEST, 'Failed updating execution. %s' % six.text_type(e))
        except Exception as e:
            LOG.exception('Failed updating liveaction %s. %s', liveaction_db.id, six.text_type(e))
            abort(
                http_client.INTERNAL_SERVER_ERROR,
                'Failed updating execution due to unexpected error.'
            )

        mask_secrets = self._get_mask_secrets(requester_user, show_secrets=show_secrets)
        execution_api = ActionExecutionAPI.from_model(actionexecution_db, mask_secrets=mask_secrets)

        return execution_api