Python调用Ansible 2.0 API执行playbook
2017-09-14 17:12
706 查看
Ansible社区目前非常活跃,从1.x到2.x,以及2.x以后的版本都有一些变化,Ansible官方并不支持Python API,不保证API向后兼容。2.0版本重写了大部分Python API,官网上说2.0后使用Ansible
API有些复杂了。
由于最开始没有重视版本间的差异,本地git clone了最新的dev分支代码,按照dev分支的实现用Python调用Ansible API,结果放到运行环境上就报找不到import的module。最后发现运行环境上的是2.3.2.0版本的Ansible,API跟最新的dev分支有很大不同,所以只好把本地代码切换到2.3 stable版本。下面的代码实现了用Python调用Ansible在本机执行playbook的功能,但仅支持2.3版本,代码参考ansible/cli/playbook.py,实际上就是从命令行的执行逻辑中抽取出来的。
因为上面的方法不能在gevent环境中执行,所以退而求其次,尝试直接调用CLI命令。其实Ansible在执行时根据task不同经常是需要fork process的,一般使用Ansible的场景对执行速度要求不会很高,所以多创建几个进程也无伤大雅。
初步学习Ansible,特别是第一种方式调用Python API,可能理解不完全正确,如果哪位看官有解决方案,请不吝赐教,在此谢过。
API有些复杂了。
由于最开始没有重视版本间的差异,本地git clone了最新的dev分支代码,按照dev分支的实现用Python调用Ansible API,结果放到运行环境上就报找不到import的module。最后发现运行环境上的是2.3.2.0版本的Ansible,API跟最新的dev分支有很大不同,所以只好把本地代码切换到2.3 stable版本。下面的代码实现了用Python调用Ansible在本机执行playbook的功能,但仅支持2.3版本,代码参考ansible/cli/playbook.py,实际上就是从命令行的执行逻辑中抽取出来的。
!/usr/bin/env python import os import sys from collections import namedtuple from ansible.parsing.dataloader import DataLoader from ansible.vars import VariableManager from ansible.inventory import Inventory from ansible.utils.vars import load_extra_vars from ansible.utils.vars import load_options_vars from ansible.executor.playbook_executor import PlaybookExecutor Options = namedtuple('Options', ['listtags', 'listtasks', 'listhosts', 'syntax', 'connection','module_path', 'forks', 'remote_user', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check', 'extra_vars']) options = Options(listtags=False, listtasks=False, listhosts=False, syntax=False, connection='local', module_path=None, forks=1, remote_user='', private_key_file=None, ssh_common_args='', ssh_extra_args='', sftp_extra_args='', scp_extra_args='', become=True, become_method='sudo', become_user='root', verbosity=3, check=False, extra_vars={}) loader = DataLoader() # create the variable manager, which will be shared throughout # the code, ensuring a consistent view of global variables variable_manager = VariableManager() variable_manager.extra_vars = load_extra_vars(loader=loader, options=options) variable_manager.options_vars = load_options_vars(options) # create the inventory, and filter it based on the subset specified (if any) inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=['localhost']) variable_manager.set_inventory(inventory) playbook_path = './p1.yaml' if not os.path.exists(playbook_path): print '[INFO] The playbook does not exist' sys.exit() passwords = {'conn_pass': '', 'become_pass': ''} pbex = PlaybookExecutor(playbooks=[playbook_path], inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords) results = pbex.run() print results上面的方法使用独立的Python进程执行没有问题,返回的结果跟直接用命令行执行完全一样。但是如果需要运行在gevent环境中,代码可能会hang。原因是Ansible使用了multiprocessing的queue来保存执行结果,ansible一开始执行就初始化结果队列,尝试取结果,但是因为queue为空,且queue()函数默认是block的,所以相当于独占了整个线程,gevent无法切换。下面是问题的复现代码:
import gevent from multiprocessing import Queue qq=Queue() def foo(): print('Running in foo') gevent.sleep(0) print('Explicit context switch to foo again') def bar(): print('Explicit context to bar') gevent.sleep(0) print('Implicit context switch back to bar') def test_queue(): print "getting queue" v = qq.get() print "got %s" % v def run_gevent(): gevent.joinall([ gevent.spawn(foo), gevent.spawn(test_queue), gevent.spawn(bar), ]) if __name__ == '__main__': run_gevent()一旦test_queue函数获得执行,整个进程就挂死了。
因为上面的方法不能在gevent环境中执行,所以退而求其次,尝试直接调用CLI命令。其实Ansible在执行时根据task不同经常是需要fork process的,一般使用Ansible的场景对执行速度要求不会很高,所以多创建几个进程也无伤大雅。
import subprocess import os cmd = "ansible-playbook /opt/ansible/play.yaml" my_env = os.environ.copy() my_env["TOKEN"] = _get_token() process = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, env=my_env) output, error = process.communicate() print output上面给新创建的进程增加了一个环境变量TOKEN。
初步学习Ansible,特别是第一种方式调用Python API,可能理解不完全正确,如果哪位看官有解决方案,请不吝赐教,在此谢过。
相关文章推荐
- python调用ansible接口API执行命令
- python之ansible 2.0 API
- ansible python api 2.0使用
- ansible执行playbook时间显示的python脚本
- Python3.5 调用Ansible 执行命令
- ansible playbook API得到任务执行返回结果
- Ansible playbook API 开发 调用测试
- 关于ansible2.0版本的ansible-playbook方法的调用
- ansible (2.4.2.0) API python调用重写 | 适用于 web
- 对python调用微软API代码的理解
- python调用win32下的API__&&__Win32Com__[转]使用 python 写 COM
- paip.java c# .net php python调用c++ c dll so windows api 总结
- C/C++中调用执行python脚本文件
- 利用python调用elasticsearch-api来分析数据并作图进行日报邮件发送
- Python调用REST API接口的几种方式 推荐
- Python2,python3调用face++api
- python 如何判断调用系统命令是否执行成功
- python模拟登录新浪微博自动获得调用新浪api所需的code
- cmd执行python错误提示api-ms-win-crt-runtime-l1-1-0.dll 丢失
- 在独立的python文件调用django api