stackstorm 30. 源码分析之----stackstorm重要场景run action


目标:
弄清楚run action原理
目录:
0 st2api调试代码前准备
1 st2api服务分析
2 关键方法publish_request分析
3 st2actionrunner调试代码前准备
4 st2actionrunner服务分析
5 总结

0 st2api调试代码前准备
将st2api容器启动命令修改

      containers:
      - command:
        - bash
        - -c
        - exec /opt/stackstorm/st2/bin/gunicorn st2api.wsgi:application -k eventlet
          -b 0.0.0.0:9101 --workers 1 --threads 1 --graceful-timeout 10 --timeout
          30
修改为:
      containers:
      - command:
        - sleep
        - 3d
等待st2api的pod启动后
修改/etc/st2/st2.conf
[auth]
host = 127.0.0.1
[api]
host = 127.0.0.1
的host的值修改为0.0.0.0

原因:
服务监听127.0.0.1只有本机才可以监听,而
0.0.0.0则表示其他节点可以发送请求,这样监听服务也可以监听到其他节点的请求。


修改为:
sudo /opt/stackstorm/st2/bin/st2api --config-file /etc/st2/st2.conf

进入st2任意的pod,执行st2 login命令后,然后执行如下命令:
st2 run core.local cmd=ls

1 st2api服务分析
代码入口
/opt/stackstorm/st2/lib/python2.7/site-packages/st2api/controllers/v1/actionexecutions.py的post()
代码如下:
class ActionExecutionsController(BaseResourceIsolationControllerMixin,
                                 ActionExecutionsControllerMixin, ResourceController):

    def post(self, liveaction_api, requester_user, context_string=None, show_secrets=False):
        return self._handle_schedule_execution(liveaction_api=liveaction_api,
                                               requester_user=requester_user,
                                               context_string=context_string,
                                               show_secrets=show_secrets)

分析:
1.1)执行run action命令进入到
上述st2api的代码
对应输入参数样例如下:
(Pdb) p liveaction_api
<st2common.router.Body object at 0x4090e50>
(Pdb) p liveaction_api.__dict__
{u'action': u'core.local', u'user': None, u'parameters': {u'cmd': u'ls'}}
(Pdb) p requester_user
<UserDB: UserDB(id=5ed81d6197474e0001587c06, is_service=False, name="admin@example.org", nicknames={})>
(Pdb) p requester_user.__dict__
{'_cls': 'UserDB'}
(Pdb) p context_string
None
(Pdb) p show_secrets
None

1.2)继续进入
class ActionExecutionsControllerMixin(BaseRestControllerMixin):

    def _handle_schedule_execution(self, liveaction_api, requester_user, context_string=None,
                                   show_secrets=False):
        """
        :param liveaction: LiveActionAPI object.
        :type liveaction: :class:`LiveActionAPI`
        """

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

        # Assert action ref is valid
        action_ref = liveaction_api.action
        action_db = action_utils.get_action_by_ref(action_ref)

        if not action_db:
            message = 'Action "%s" cannot be found.' % action_ref
            LOG.warning(message)
            abort(http_client.BAD_REQUEST, message)

        # Assert the permissions
        assert_user_has_resource_db_permission(user_db=requester_user, resource_db=action_db,
                                               permission_type=PermissionType.ACTION_EXECUTE)

        # Validate that the authenticated user is admin if user query param is provided
        user = liveaction_api.user or requester_user.name
        assert_user_is_admin_if_user_query_param_is_provided(user_db=requester_user,
                                                             user=user)

        try:
            return self._schedule_execution(liveaction=liveaction_api,
                                            requester_user=requester_user,
                                            user=user,
                                            context_string=context_string,
                                            show_secrets=show_secrets,
                                            pack=action_db.pack)
        except ValueError as e:
            LOG.exception('Unable to execute action.')
            ......
分析:
上述主要处理逻辑是:
根据action_ref查询得到action_db,调用_schedule_execution获取执行结果


1.3) 分析_schedule_execution方法
class ActionExecutionsControllerMixin(BaseRestControllerMixin):

    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)


分析:
1)_schedule_execution方法
    1 根据输入参数,形如
        (Pdb) p liveaction_api
        <st2common.router.Body object at 0x4090e50>
        (Pdb) p liveaction_api.__dict__
        {u'action': u'core.local', u'user': None, u'parameters': {u'cmd': u'ls'}}
        (Pdb) p requester_user
        <UserDB: UserDB(id=5ed81d6197474e0001587c06, is_service=False, name="admin@example.org", nicknames={})>
        (Pdb) p requester_user.__dict__
        {'_cls': 'UserDB'}
        (Pdb) p context_string
        None
        (Pdb) p show_secrets
        None
        pack : core
    2 根据action_ref查询得到action_db,根据runner_type名称(例如: 'local-shell-cmd')查询得到runnertype_db
    3 获取action实例的参数(例如: liveaction_db.parameters{u'cmd': u'ls'})
    4 调用create_request(liveaction): 创建一个action的执行,返回(liveaction, execution),具体是:
        向live_action_d_b表添加或更新liveaction
        创建execution
    5 调用publish_request(liveaction, execution)方法,具体是:
        发送liveaction消息到'st2.liveaction'这个exchange, routing_key为'create'
        发送liveaction消息到'st2.liveaction.status'这个exchange, routing_key为'requested'
        发送actionexecution消息到'st2.execution'这个exchange, routing_key为'create'
        返回: liveaction, execution
    6 将execution返回

其中最为关键的就是5 调用publish_request(liveaction, execution)方法
发送liveaction消息到'st2.liveaction.status'这个exchange, routing_key为'requested'
具体参见2的分析

2 关键方法publish_request分析
_, actionexecution_db = action_service.publish_request(liveaction_db, actionexecution_db)
进行liveaction状态的修改,导致actionrunner接收到消息并进行处理
下面是actionrunner的日志
2020-06-05T08:36:02.974507088Z 2020-06-05 16:36:02,925 AUDIT [-] The status of action execution is changed from requested to scheduled.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值