最近想利用python来调用anbile来实现一些功能,发现ansible的api已经升级到了2.0,使用上比以前复杂了许多。
这里我参考了官方文档的例子,做了一些整改,写了一个python调用ansible的函数,执行过程中输出执行结果。函数返回执行结果,便于筛选和存储所需的数据:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<code># vim exec_ansible.py</code>
<code>from ansible.inventory.manager </code><code>import</code> <code>InventoryManager</code>
<code>from ansible.playbook.play </code><code>import</code> <code>Play</code>
<code>from ansible.executor.task_queue_manager </code><code>import</code> <code>TaskQueueManager</code>
<code>from ansible.plugins.callback </code><code>import</code> <code>CallbackBase</code>
<code>class ResultCallback(CallbackBase):</code>
<code> </code><code>""</code><code>"A sample callback plugin used </code><code>for</code> <code>performing an action as results come </code><code>in</code>
<code> </code><code>If you want to collect all results into a single object </code><code>for</code> <code>processing at</code>
<code> </code><code>the end of the execution, </code><code>look</code> <code>into utilizing the ``json`` callback plugin</code>
<code> </code><code>or writing your own custom callback plugin</code>
<code> </code><code>""</code><code>"</code>
<code> </code><code>def v2_runner_on_ok(self, result, **kwargs):</code>
<code> </code><code>""</code><code>"Print a json representation of the result</code>
<code> </code><code>This method could store the result </code><code>in</code> <code>an instance attribute </code><code>for</code> <code>retrieval later</code>
<code> </code><code>""</code><code>"</code>
<code> </code><code>global exec_result</code>
<code> </code><code>host = result._host</code>
<code> </code><code>self.data = json.dumps({host.name: result._result}, indent=4)</code>
<code> </code><code>exec_result = dict(exec_result,**json.loads(self.data))</code>
<code>def exec_ansible(module,args,host): </code>
<code> </code><code>Options = namedtuple(</code><code>'Options'</code><code>, [</code><code>'connection'</code><code>, </code><code>'module_path'</code><code>, </code><code>'forks'</code><code>, </code><code>'become'</code><code>, </code><code>'become_method'</code><code>, </code><code>'become_user'</code><code>, </code><code>'check'</code><code>, </code><code>'diff'</code><code>])</code>
<code> </code><code># initialize needed objects</code>
<code> </code><code>loader = DataLoader()</code>
<code> </code><code>options = Options(connection=</code><code>'ssh'</code><code>, module_path=</code><code>'/usr/local/lib/python3.6/site-packages/ansible-2.4.1.0-py3.6.egg/ansible/modules/'</code><code>, forks=100, become=None, become_method=None, become_user=None, check=False,</code><code>diff</code><code>=False)</code>
<code> </code><code>passwords = dict(vault_pass=</code><code>'secret'</code><code>)</code>
<code> </code><code># Instantiate our ResultCallback for handling results as they come in</code>
<code> </code><code>results_callback = ResultCallback()</code>
<code> </code><code># create inventory and pass to var manager</code>
<code> </code><code>inventory = InventoryManager(loader=loader, sources=[</code><code>'/etc/ansible/hosts'</code><code>])</code>
<code> </code><code>variable_manager = VariableManager(loader=loader, inventory=inventory)</code>
<code> </code><code># create play with tasks</code>
<code> </code><code>play_source = dict(</code>
<code> </code><code>name = </code><code>"Ansible Play"</code><code>,</code>
<code> </code><code>hosts = host,</code>
<code> </code><code>gather_facts = </code><code>'no'</code><code>,</code>
<code> </code><code>tasks = [</code>
<code> </code><code>dict(action=dict(module=module, args=args), register=</code><code>'shell_out'</code><code>),</code>
<code> </code><code>]</code>
<code> </code><code>)</code>
<code> </code><code>play = Play().load(play_source, variable_manager=variable_manager, loader=loader)</code>
<code> </code><code># actually run it</code>
<code> </code><code>tqm = None</code>
<code> </code><code>global exec_result</code>
<code> </code><code>try:</code>
<code> </code><code>tqm = TaskQueueManager(</code>
<code> </code><code>inventory=inventory,</code>
<code> </code><code>variable_manager=variable_manager,</code>
<code> </code><code>loader=loader,</code>
<code> </code><code>options=options,</code>
<code> </code><code>passwords=passwords,</code>
<code> </code><code>stdout_callback=results_callback, </code><code># Use our custom callback instead of the ``default`` callback plugin</code>
<code> </code><code>)</code>
<code> </code><code>result = tqm.run(play)</code>
<code> </code><code>finally:</code>
<code> </code><code>if</code> <code>tqm is not None:</code>
<code> </code><code>tqm.cleanup()</code>
<code> </code><code>return</code> <code>exec_result</code>
调用例子:
我本地ansible的hosts文件如下:
<code># more /etc/ansible/hosts</code>
<code>[testserver]</code>
<code>192.168.52.128</code>
<code>192.168.52.135</code>
调用如下:
先调用testserver一组主机批量执行date命令:
<code>>>> from exec_ansible </code><code>import</code> <code>exec_ansible </code>
<code>>>> test1 = exec_ansible(module=</code><code>'shell'</code><code>,args=</code><code>'date'</code><code>,host=</code><code>'testserver'</code><code>)</code>
<code>{</code>
<code> </code><code>"192.168.52.135"</code><code>: {</code>
<code> </code><code>"warnings"</code><code>: [],</code>
<code> </code><code>"stderr"</code><code>: </code><code>""</code><code>,</code>
<code> </code><code>"delta"</code><code>: </code><code>"0:00:00.003688"</code><code>,</code>
<code> </code><code>"_ansible_no_log"</code><code>: </code><code>false</code><code>,</code>
<code> </code><code>"stdout"</code><code>: </code><code>"Sat Nov 5 18:54:17 CST 2016"</code><code>,</code>
<code> </code><code>"cmd"</code><code>: </code><code>"date"</code><code>,</code>
<code> </code><code>"_ansible_parsed"</code><code>: </code><code>true</code><code>,</code>
<code> </code><code>"rc"</code><code>: 0,</code>
<code> </code><code>"invocation"</code><code>: {</code>
<code> </code><code>"module_args"</code><code>: {</code>
<code> </code><code>"removes"</code><code>: null,</code>
<code> </code><code>"executable"</code><code>: null,</code>
<code> </code><code>"creates"</code><code>: null,</code>
<code> </code><code>"chdir"</code><code>: null,</code>
<code> </code><code>"warn"</code><code>: </code><code>true</code><code>,</code>
<code> </code><code>"_raw_params"</code><code>: </code><code>"date"</code><code>,</code>
<code> </code><code>"_uses_shell"</code><code>: </code><code>true</code>
<code> </code><code>},</code>
<code> </code><code>"module_name"</code><code>: </code><code>"command"</code>
<code> </code><code>},</code>
<code> </code><code>"start"</code><code>: </code><code>"2016-11-05 18:54:17.563525"</code><code>,</code>
<code> </code><code>"changed"</code><code>: </code><code>true</code><code>,</code>
<code> </code><code>"end"</code><code>: </code><code>"2016-11-05 18:54:17.567213"</code><code>,</code>
<code> </code><code>"stdout_lines"</code><code>: [</code>
<code> </code><code>"Sat Nov 5 18:54:17 CST 2016"</code>
<code> </code><code>]</code>
<code> </code><code>}</code>
<code>}</code>
<code> </code><code>"192.168.52.128"</code><code>: {</code>
<code> </code><code>"delta"</code><code>: </code><code>"0:00:00.003244"</code><code>,</code>
<code> </code><code>"stdout"</code><code>: </code><code>"Sat Nov 5 21:48:38 CST 2016"</code><code>,</code>
<code> </code><code>"start"</code><code>: </code><code>"2016-11-05 21:48:38.252785"</code><code>,</code>
<code> </code><code>"end"</code><code>: </code><code>"2016-11-05 21:48:38.256029"</code><code>,</code>
<code> </code><code>"Sat Nov 5 21:48:38 CST 2016"</code>
指定单台执行命令:
<code>>>> test2 = exec_ansible(module=</code><code>'shell'</code><code>,args=</code><code>'free -m'</code><code>,host=</code><code>'192.168.52.128'</code><code>)</code>
<code> </code><code>"_raw_params"</code><code>: </code><code>"free -m"</code><code>,</code>
<code> </code><code>"_uses_shell"</code><code>: </code><code>true</code><code>,</code>
<code> </code><code>"warn"</code><code>: </code><code>true</code>
<code> </code><code>"start"</code><code>: </code><code>"2016-11-05 21:53:10.738545"</code><code>,</code>
<code> </code><code>"delta"</code><code>: </code><code>"0:00:00.002871"</code><code>,</code>
<code> </code><code>" total used free shared buffers cached"</code><code>,</code>
<code> </code><code>"Mem: 1869 1786 83 3 312 512"</code><code>,</code>
<code> </code><code>"-/+ buffers/cache: 961 908 "</code><code>,</code>
<code> </code><code>"Swap: 4047 3 4044 "</code>
<code> </code><code>],</code>
<code> </code><code>"end"</code><code>: </code><code>"2016-11-05 21:53:10.741416"</code><code>,</code>
<code> </code><code>"cmd"</code><code>: </code><code>"free -m"</code><code>,</code>
<code> </code><code>"stdout"</code><code>: </code><code>" total used free shared buffers cached\nMem: 1869 1786 83 3 312 512\n-/+ buffers/cache: 961 908 \nSwap: 4047 3 4044 "</code>
这里可以从输出中取到输出结果:
<code>>>> stdout = test2[</code><code>"192.168.52.128"</code><code>][</code><code>"stdout"</code><code>]</code>
<code> </code><code>total used </code><code>free</code> <code>shared buffers cached</code>
<code>Mem: 1869 1756 112 2 314 490</code>
<code>-/+ buffers</code><code>/cache</code><code>: 951 917 </code>
<code>Swap: 4047 4 4043</code>
我写的脚本有个bug,就是当指定一组主机批量执行的时候,返回的函数中,存储内容的只剩下最后执行命令的那台主机的相关信息,做不到把所有的主机的执行信息存储,希望有大神可以解决这个问题,并不吝赐教!!(已解决,参考更改过的exec_ansible脚本)
-------后续更新---------------
注:
新版本的api相关模块已经修改,故使用方法上也需要整改,本文档的例子已更新api的使用,如上的exec_ansible脚本。
-----bug解决----
另外,我在脚本中新增了全局空字典参数exec_result={},分别在class ResultCallback和函数exec_result中进行全局函数声明,用以存储执行过程中所产生的stdout输出,以解决之前脚本的bug(返回函数中,存储内容的只剩下最后执行命令的那台主机的相关信息,做不到把所有的主机的执行信息存储)。
只需在python主体重定义exec_result = {}这个空字典,即可实现。
使用如下:
<code>exec_result </code><code>=</code> <code>{}</code>
<code>a </code><code>=</code> <code>exec_ansible(</code><code>"shell"</code><code>,</code><code>"free -m"</code><code>,</code><code>"test"</code><code>)</code>
<code>print</code><code>(a)</code>
<code>{</code><code>'192.168.204.128'</code><code>: {</code><code>'changed'</code><code>: </code><code>True</code><code>, </code><code>'end'</code><code>: </code><code>'2017-11-07 15:16:08.970746'</code><code>, </code><code>'stdout'</code><code>: </code><code>' t</code>
本文转自 icenycmh 51CTO博客,原文链接:http://blog.51cto.com/icenycmh/1870642,如需转载请自行联系原作者