AnsibleModule 的多个实例可以在一个模块内 created/called 吗?

Can multiple instances of AnsibleModule be created/called inside one Module?

我们的服务器逻辑结构是基于"cluster"和"instance"的概念。集群是 Weblogic and/or Karaf and/or Apache and/or Nginx and/or Jboss 的一组实例。实例 "MAY or MAY-NOT" 分布在多个主机上。

一个 classic 集群将是: 主持人:a,b 上的实例:tst13-apache、tst13-weblogic-ecom、tst13-weblogic-fulfill b 上的实例:tst13-karaf-rest-bus、tst13-karf-rest-svcs、tst13-nginx-cache

我创建了一个超级class模块(myMod)和5个子classes(myApache、myNginx、myJboss、myKaraf、myWeblogic)。 "instance" 信息(库存变量)保存在 ldap 数据库中。这些实例不在主机上 rc.d 目录中的 "registered"。每个服务器都有 "generic scripts" 用于启动一个 apache 实例和一个 weblogic 实例以及一个 JBoss 实例和... "instance name" 所以调用 Ansible 模块如 "httpd" 是不切实际的。

我的模块将用于针对实例列表采取的 "stop, start, status, kill, etc"(操作)。

理想情况下,我想为要在目标主机上运行的每个软件实例创建一个到目标 "host" 的 ssh 连接(我相信这意味着每个实例一个模块的实例需要采取行动的服务器软件);然而,到目前为止,ansible 似乎每个目的地建立 1 个 ssh 连接 "host".

因为一个 "host" 可以是 运行 多个不同类型软件的实例(2 个 apache 实例、4 个 weblogic 实例和 3 个 karaf 实例都可以在一台主机上);按如下方式创建我的 "myMod" 似乎很实用:

#####
## <ANSIBLE_HOME>/modules/controller.py    
#####
    import socket
    from ansible.module_utils.ldapData import ldapData
    from ansible.module_utils.myMod import myMod
    from ansible.module_utils.myModules import myApache, myNginx, myWeblogic, myKaraf, myJboss

    def main():

        arg_spec = dict(
                action = dict(default='status', choices=['start', 'stop', 'kill', 'status', 'warm', 'startsession', 'stopsession']),
                instances = dict(default='@', required=False, type='str'),
            )

        host = socket.gethostname()

        serverdata = ldapData()
        cluster = serverdata.hosts[host]["cluster"]
        clusterData = serverdata.clusters[cluster]
        hostData = serverdata.hosts[host]

        classList = list(myMod.__subclasses__())

        for classType in classList:
            localMod = classType(arg_spec, hostData, clusterData)
            localMod.process()

    if __name__ == '__main__':
        main()

myMod中的process方法是这样的:

#####
## <ANSIBLE_HOME>/module_utils/myMod.py
#####
    def process(self):
        fPointers = {
                'start': self.start,
                'stop': self.stop,
                'kill': self.kill,
                'status': self.status,
                'stopsession': self.stopsession,
                'startsesson': self.startsession,
                'warm': self.warm
        }
        act = self.params['action']
        for inst in self.instances:
                if fPointers[act]:
                        fPointers[act](inst)
                else:
                        undefined(inst)
        self.exit_json(changed=self.changed, msg=self.out, warnings=self.warn, errors=self.err)

目前,我只取回第一个被调用 "process" 的模块的 "out" 和 "warn" 以及 "err"。其他模块要么不执行,要么不报告。我期望 exit_json 是 "exiting the entire Ansible run" 而不仅仅是 "the current module"。

我说的对吗?有没有我不知道的概念在起作用?确保 运行 末尾的 ansible "report" 显示 "all output of all instances" 的最佳更改是什么?

对于每个任务,Ansible 在通过 SSH 将其发送到执行之前将模块与所有必需的库和参数打包在一起。所以你的主模块(包装器)应该在一个 运行.

中完成所有工作

exit_json方法stops整个过程用sys.exit(0),所以当你第一次调用这个方法时你的模块运行就完成了。

我建议您制作一个 AnsibleModule class 和一组 return 数据到父模块的助手。然后你只需将所有助手的结果组合成一个对象并将其刷新到标准输出(使用 exit_json)。