ansible python api 2
最近想利用python来调用anbile来实现一些功能,发现ansible的api已经升级到了2.0,使用上比以前复杂了许多。
这里我参考了官方文档的例子,做了一些整改,写了一个python调用ansible的函数,执行过程中输出执行结果。函数返回执行结果,便于筛选和存储所需的数据:
# 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文件如下:
# more /etc/ansible/hosts
[testserver]
192.168.52.128
192.168.52.135
调用如下:
先调用testserver一组主机批量执行date命令:
>>> 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"
]
}
}
指定单台执行命令:
>>> 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 "
}
}
这里可以从输出中取到输出结果:
>>> 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 = {}这个空字典,即可实现。
使用如下:
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}}
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341