前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ansible python api 2

ansible python api 2

作者头像
py3study
发布2020-01-06 16:23:34
1.9K1
发布2020-01-06 16:23:34
举报
文章被收录于专栏:python3

 最近想利用python来调用anbile来实现一些功能,发现ansible的api已经升级到了2.0,使用上比以前复杂了许多。

 这里我参考了官方文档的例子,做了一些整改,写了一个python调用ansible的函数,执行过程中输出执行结果。函数返回执行结果,便于筛选和存储所需的数据:

代码语言:javascript
复制
# vim exec_ansible.py
from ansible.inventory.manager import InventoryManager
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.plugins.callback import CallbackBase

class ResultCallback(CallbackBase):
    """A sample callback plugin used for performing an action as results come in

    If you want to collect all results into a single object for processing at
    the end of the execution, look into utilizing the ``json`` callback plugin
    or writing your own custom callback plugin
    """
    def v2_runner_on_ok(self, result, **kwargs):
        """Print a json representation of the result
        This method could store the result in an instance attribute for retrieval later
        """
        global exec_result
        host = result._host
        self.data = json.dumps({host.name: result._result}, indent=4)
        exec_result = dict(exec_result,**json.loads(self.data))


def exec_ansible(module,args,host):               
    Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check', 'diff'])
    # initialize needed objects
    loader = DataLoader()
    options = Options(connection='ssh', module_path='/usr/local/lib/python3.6/site-packages/ansible-2.4.1.0-py3.6.egg/ansible/modules/', forks=100, become=None, become_method=None, become_user=None, check=False,diff=False)
    passwords = dict(vault_pass='secret')

    # Instantiate our ResultCallback for handling results as they come in
    results_callback = ResultCallback()

    # create inventory and pass to var manager
    inventory = InventoryManager(loader=loader, sources=['/etc/ansible/hosts'])
    variable_manager = VariableManager(loader=loader, inventory=inventory)

    # create play with tasks
    play_source =  dict(
            name = "Ansible Play",
            hosts = host,
            gather_facts = 'no',
            tasks = [
                dict(action=dict(module=module, args=args), register='shell_out'),
             ]
        )
    play = Play().load(play_source, variable_manager=variable_manager, loader=loader)

    # actually run it
    tqm = None
    global exec_result
    try:
        tqm = TaskQueueManager(
                  inventory=inventory,
                  variable_manager=variable_manager,
                  loader=loader,
                  options=options,
                  passwords=passwords,
                  stdout_callback=results_callback,  # Use our custom callback instead of the ``default`` callback plugin
              )
        result = tqm.run(play)
    finally:
        if tqm is not None:
            tqm.cleanup()
        return exec_result

调用例子:

  我本地ansible的hosts文件如下:

代码语言:javascript
复制
# more /etc/ansible/hosts
[testserver]
192.168.52.128
192.168.52.135

  调用如下:

  先调用testserver一组主机批量执行date命令:

代码语言:javascript
复制
>>> from exec_ansible import exec_ansible                             
>>> test1 = exec_ansible(module='shell',args='date',host='testserver')
{
    "192.168.52.135": {
        "warnings": [],
        "stderr": "",
        "delta": "0:00:00.003688",
        "_ansible_no_log": false,
        "stdout": "Sat Nov  5 18:54:17 CST 2016",
        "cmd": "date",
        "_ansible_parsed": true,
        "rc": 0,
        "invocation": {
            "module_args": {
                "removes": null,
                "executable": null,
                "creates": null,
                "chdir": null,
                "warn": true,
                "_raw_params": "date",
                "_uses_shell": true
            },
            "module_name": "command"
        },
        "start": "2016-11-05 18:54:17.563525",
        "changed": true,
        "end": "2016-11-05 18:54:17.567213",
        "stdout_lines": [
            "Sat Nov  5 18:54:17 CST 2016"
        ]
    }
}
{
    "192.168.52.128": {
        "warnings": [],
        "stderr": "",
        "delta": "0:00:00.003244",
        "_ansible_no_log": false,
        "stdout": "Sat Nov  5 21:48:38 CST 2016",
        "cmd": "date",
        "_ansible_parsed": true,
        "rc": 0,
        "invocation": {
            "module_args": {
                "removes": null,
                "executable": null,
                "creates": null,
                "chdir": null,
                "warn": true,
                "_raw_params": "date",
                "_uses_shell": true
            },
            "module_name": "command"
        },
        "start": "2016-11-05 21:48:38.252785",
        "changed": true,
        "end": "2016-11-05 21:48:38.256029",
        "stdout_lines": [
            "Sat Nov  5 21:48:38 CST 2016"
        ]
    }
}

 指定单台执行命令:

代码语言:javascript
复制
>>> test2 = exec_ansible(module='shell',args='free -m',host='192.168.52.128')
{
    "192.168.52.128": {
        "warnings": [],
        "changed": true,
        "invocation": {
            "module_args": {
                "_raw_params": "free -m",
                "executable": null,
                "chdir": null,
                "creates": null,
                "removes": null,
                "_uses_shell": true,
                "warn": true
            },
            "module_name": "command"
        },
        "rc": 0,
        "start": "2016-11-05 21:53:10.738545",
        "_ansible_parsed": true,
        "delta": "0:00:00.002871",
        "stdout_lines": [
            "             total       used       free     shared    buffers     cached",
            "Mem:          1869       1786         83          3        312        512",
            "-/+ buffers/cache:        961        908 ",
            "Swap:         4047          3       4044 "
        ],
        "stderr": "",
        "end": "2016-11-05 21:53:10.741416",
        "cmd": "free -m",
        "_ansible_no_log": false,
        "stdout": "             total       used       free     shared    buffers     cached\nMem:          1869       1786         83          3        312        512\n-/+ buffers/cache:        961        908 \nSwap:         4047          3       4044 "
    }
}

 这里可以从输出中取到输出结果:

代码语言:javascript
复制
>>> stdout = test2["192.168.52.128"]["stdout"]
             total       used       free     shared    buffers     cached
Mem:          1869       1756        112          2        314        490
-/+ buffers/cache:        951        917 
Swap:         4047          4       4043

 我写的脚本有个bug,就是当指定一组主机批量执行的时候,返回的函数中,存储内容的只剩下最后执行命令的那台主机的相关信息,做不到把所有的主机的执行信息存储,希望有大神可以解决这个问题,并不吝赐教!!(已解决,参考更改过的exec_ansible脚本)

-------后续更新---------------

注:

      新版本的api相关模块已经修改,故使用方法上也需要整改,本文档的例子已更新api的使用,如上的exec_ansible脚本。

-----bug解决----

     另外,我在脚本中新增了全局空字典参数exec_result={},分别在class ResultCallback和函数exec_result中进行全局函数声明,用以存储执行过程中所产生的stdout输出,以解决之前脚本的bug(返回函数中,存储内容的只剩下最后执行命令的那台主机的相关信息,做不到把所有的主机的执行信息存储)。

      只需在python主体重定义exec_result = {}这个空字典,即可实现。

使用如下:

代码语言:javascript
复制
exec_result = {}
a = exec_ansible("shell","free -m","test")
print(a)
{'192.168.204.128': {'changed': True, 'end': '2017-11-07 15:16:08.970746', 'stdout': '             total       used       free     shared    buffers     cached\nMem:          1990       1918         72          3         89       1280\n-/+ buffers/cache:        548       1441\nSwap:         1999          0       1999', 'cmd': 'free -m', 'rc': 0, 'start': '2017-11-07 15:16:08.964010', 'stderr': '', 'delta': '0:00:00.006736', 'invocation': {'module_args': {'warn': True, 'executable': None, '_uses_shell': True, '_raw_params': 'free -m', 'removes': None, 'creates': None, 'chdir': None, 'stdin': None}}, '_ansible_parsed': True, 'stdout_lines': ['             total       used       free     shared    buffers     cached', 'Mem:          1990       1918         72          3         89       1280', '-/+ buffers/cache:        548       1441', 'Swap:         1999          0       1999'], 'stderr_lines': [], '_ansible_no_log': False, 'failed': False}, '192.168.204.129': {'changed': True, 'end': '2017-11-07 15:16:08.975201', 'stdout': '             total       used       free     shared    buffers     cached\nMem:          1990       1918         72          3         89       1280\n-/+ buffers/cache:        548       1441\nSwap:         1999          0       1999', 'cmd': 'free -m', 'rc': 0, 'start': '2017-11-07 15:16:08.964947', 'stderr': '', 'delta': '0:00:00.010254', 'invocation': {'module_args': {'warn': True, 'executable': None, '_uses_shell': True, '_raw_params': 'free -m', 'removes': None, 'creates': None, 'chdir': None, 'stdin': None}}, '_ansible_parsed': True, 'stdout_lines': ['             total       used       free     shared    buffers     cached', 'Mem:          1990       1918         72          3         89       1280', '-/+ buffers/cache:        548       1441', 'Swap:         1999          0       1999'], 'stderr_lines': [], '_ansible_no_log': False, 'failed': False}}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/09/22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档