【Python】ansible api学习

ansbile1.9版本如下

1 ansible基础模块


  1. 详见《自动化运维软件设计实战 ,吴文豪著》ansible部分:
  2. file shell command  script raw cron group service user 模块


2ansible yml
  1. 如:
  2. [root@host-192-168-1-56 ansible]# more test.yml 
    ---
    - hosts: webservers
      remote_user: root
      tasks:
      - name: touch /soft/ansible/1.txt
        shell: touch /soft/ansible/1.txt
      - name: mkdir /soft/ansible/testdir
        shell: mkdir /soft/ansible/testdir
      - name: copy file
        copy: src=/soft/log.txt dest=/soft/ansible/
      - name: backup mysql db
        shell: mysqldump -uroot -pESBecs00 mysql > /soft/ansible/mysql.sql
      - name : fetch sql
        fetch: dest=/tmp src=/soft/ansible/mysql.sql
      - name : clean sql
        shell: rm -rf /soft/ansible/mysql.sql


  3. [root@host-192-168-1-56 ansible]# ansible-playbook test.yml
  4. PLAY [webservers] ************************************************************* 


    GATHERING FACTS *************************************************************** 
    ok: [218.78.186.162]


    TASK: [touch /soft/ansible/1.txt] ********************************************* 
    changed: [218.78.186.162]


    TASK: [mkdir /soft/ansible/testdir] ******************************************* 
    changed: [218.78.186.162]


    TASK: [copy file] ************************************************************* 
    changed: [218.78.186.162]


    TASK: [backup mysql db] ******************************************************* 
    changed: [218.78.186.162]


    TASK: [fetch sql] ************************************************************* 
    changed: [218.78.186.162]


    TASK: [clean sql] ************************************************************* 
    changed: [218.78.186.162]
    {
        "218.78.186.162": {
            "unreachable": 0, 
            "skipped": 0, 
            "ok": 7, 
            "changed": 6, 
            "failures": 0
        }
    }



3 ansible api


  1. 列子: 
    1. #!/usr/bin/env python
    2. # coding=utf-8
    3. import ansible.runner
    4. import json
    5. dbname='mysql'
    6. tablename='user testdb'
    7. runner = ansible.runner.Runner(
    8.        module_name='shell',                                                        ###模块
    9.        module_args='sh /soft/ansible/beifen.sh %s %s ' %(dbname,tablename),        ###对应的命令
    10.        pattern='all',                                                              ###对象
    11.        forks=10
    12.     )
    13. datastructure = runner.run()                                                      ###运行
    14. #data = json.dumps(datastructure,indent=4)                                        ##josn化
    15. print datastructure                             

    16. if len(datastructure['dark']) == 0:
    17.    print 'status is ok'
    18. else:
    19.    print datastructure['dark']

    其输出结果如下:

    ansible-api

    注:如果主机是不通或失败的,结果将会输出到dark部分里,一个含有失败主机的结果类似如下:

    1. {
    2.  "dark" : {
    3.  "web1.example.com" : "failure message"
    4.  },
    5.  "contacted" : {
    6.  "web2.example.com" : 1
    7.  }
    8. }




    再为看下第二个示例:

    1. #!/usr/bin/python
    2. import ansible.runner
    3. import sys
    4. # construct the ansible runner and execute on all hosts
    5. results = ansible.runner.Runner(
    6.  pattern='*', forks=10,
    7.  module_name='command', module_args='/usr/bin/uptime',
    8. ).run()
    9. if results is None:
    10.  print "No hosts found"
    11.  sys.exit(1)
    12. print "UP ***********"
    13. for (hostname, result) in results['contacted'].items():
    14.  if not 'failed' in result:
    15.  print "%s >>> %s" % (hostname, result['stdout'])
    16. print "FAILED *******"
    17. for (hostname, result) in results['contacted'].items():
    18.  if 'failed' in result:
    19.  print "%s >>> %s" % (hostname, result['msg'])
    20. print "DOWN *********"
    21. for (hostname, result) in results['dark'].items():
    22.  print "%s >>> %s" % (hostname, result)


    上面的示例中对主机的输出结果进行了判断,并且结果的输出进行了定制化,上面执行的结果你可以和ansible all -m command -a 'uptime' 的结果进行下比对,看下有什么不同。

    上面的示例基本上都是参照官方页面进行执行的,更多用法可以通过pydoc ansible或者通过python里的help(ansible)查看。另外在多主机执行时,可以使用async(异部)方式运行。

    二、ansible_playbook api

    ansible_playbook api 部分在官方文档上并没有提,不过通过查看ansible模块的帮助信息可以看到其是支持的。在ansible google论坛里(需翻墙),有老外也给出里代码,其实它和执行ansible的api方式一样,只是多了个几个参数:

    1. import ansible.playbook
    2. from ansible import callbacks
    3. from ansible import utils
    4. stats = callbacks.AggregateStats()
    5. playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY)
    6. runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY)
    7. pb = ansible.playbook.PlayBook(
    8.  playbook="nseries.yml",
    9.  stats=stats,
    10.  callbacks=playbook_cb,
    11.  runner_callbacks=runner_cb,
    12.  check=True
    13. )
    14. for (play_ds, play_basedir) in zip(pb.playbook, pb.play_basedirs):
    15.  import ipdb
    16.  ipdb.set_trace()
    17.  # Can play around here to see what


    18. 大致看了下代码,在用api的方式执行playbook的时候,playbook,stats,callbacks,runner_callbacks这几个参数是必须的。不使用的时候会报错。           
    19. arguments = []
    20. if playbook is None:
    21.  arguments.append('playbook')
    22. if callbacks is None:
    23.  arguments.append('callbacks')
    24. if runner_callbacks is None:
    25.  arguments.append('runner_callbacks')
    26. if stats is None:
    27.  arguments.append('stats')
    28. if arguments:
    29.  raise Exception('PlayBook missing required arguments: %s' % ', '.join(arguments))


    playbook用来指定playbook的yaml文件

    stats用来收集playbook执行期间的状态信息,最后会进行汇总

    callbacks用来输出playbook执行的结果

    runner_callbacks用来输出playbook执行期间的结果。但是它返回的结果太简单,我想让它详细点,如果用自定义callback的方法插入到mongo里面的话也行,或者是直接输出,但是我想所有task都执行完后,把每个task的详细信息输出到终端上,最后发现结果输出都是靠callbacks.py里的AggregateStats这个类,在每执行完一个task后,都会调用AggregateStats进行计算,汇总。

    1. [root@361way api]# cat playbook_api.py
    2. #!/usr/bin/env python
    3. # coding=utf-8
    4. import ansible.playbook
    5. from ansible import callbacks
    6. from ansible import utils
    7. import json
    8. stats = callbacks.AggregateStats()
    9. playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY)
    10. runner_cb = callbacks.PlaybookRunnerCallbacks(stats,verbose=utils.VERBOSITY)
    11. res=ansible.playbook.PlayBook(
    12.  playbook='/etc/ansible/playbooks/user.yml',
    13.  stats=stats,
    14.  callbacks=playbook_cb,
    15.  runner_callbacks=runner_cb
    16.  ).run()
    17. data = json.dumps(res,indent=4)
    18. print data

    1. # 执行结果如下:
    2. [root@361way api]# python playbook_api.py
    3. PLAY [create user] ************************************************************
    4. TASK: [create test "{{ user }}"] **********************************************
    5. changed: [10.212.52.16]
    6. changed: [10.212.52.14]
    7. {
    8.  "10.212.52.16": {
    9.  "unreachable": 0,
    10.  "skipped": 0,
    11.  "ok": 1,
    12.  "changed": 1,
    13.  "failures": 0
    14.  },
    15.  "10.212.52.14": {
    16.  "unreachable": 0,
    17.  "skipped": 0,
    18.  "ok": 1,
    19.  "changed": 1,
    20.  "failures": 0
    21.  }
    22. }
    23. [root@361way api]#


    三、总结

    从上面的例子来看,感觉作用似乎有点鸡肋。多条ansible shell 指令的执行可以写成playbook 来执行,ansbile-playbook 也可以通过include 调用子playbook ,似乎API 部分用处并不大 。咋一听深感有理,不过细究一下,

    1、当需要先对前一次作任务执行的结果进行处理,并将相应的结果对应的作为输入再在一次任务传入时,这里使用api 更方便;

    2、需要对结果输出进行整形时,也比较api 方便;

    3、playbook 之间进行调用或都playbook比较复杂时,想要理清任务之间的关系势必累显麻烦,而通过api,从上一层任务到下一层任务之间的调用关系明子。而且playbook之间可以是平行的关系。方便小的功能模块的复用。

    4、方便二次开发及和其他程序之间的耦合调用----目前感觉这条是最实用的。



ansible2.0及以后如下:
http://www.tuicool.com/articles/uMBz2e6


参考:
http://www.361way.com/ansible-api/4446.html
http://www.jianshu.com/p/81da20dd9931   --封装成类
http://docs.ansible.com/ansible/dev_guide/developing_api.html#python-api-2-0   --官文

请使用浏览器的分享功能分享到微信等