天天看点

ansible python api 2.0使用

 最近想利用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>&gt;&gt;&gt; from exec_ansible </code><code>import</code> <code>exec_ansible                             </code>

<code>&gt;&gt;&gt; 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>&gt;&gt;&gt; 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>&gt;&gt;&gt; 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,如需转载请自行联系原作者