1. #!/usr/bin/env python
    2. # -*- coding:utf-8 -*-
    3. import json
    4. import shutil
    5. from collections import namedtuple
    6. from ansible.parsing.dataloader import DataLoader
    7. from ansible.inventory.manager import InventoryManager
    8. from ansible.vars.manager import VariableManager
    9. from ansible.playbook.play import Play
    10. from ansible.executor.task_queue_manager import TaskQueueManager
    11. from ansible.plugins.callback import CallbackBase
    12. import ansible.constants as C
    13. class ResultCallback(CallbackBase):
    14. """
    15. 一个用于在结果出现时执行操作的回调插件示例;
    16. 如果要将所有结果收集到单个对象中以便在执行结束时进行处理;
    17. 请查看使用``json``回调插件或编写自己的自定义回调插件。
    18. """
    19. def v2_runner_on_ok(self, result, **kwargs):
    20. """
    21. 以 JSON 形式打印结果
    22. 此方法可以将结果存储在实例属性中以便稍后检索
    23. """
    24. host = result._host
    25. print(json.dumps({host.name: result._result}, indent=4))
    26. # 由于 API 是为 CLI 构建的,因此需要始终设置某些选项,命名元组伪造的 args 解析选项对象
    27. module_path = '/usr/lib/python2.7/site-packages/ansible/module'
    28. Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check', 'diff'])
    29. options = Options(connection='ssh', module_path=[module_path], forks=10, become=None, become_method=None, become_user=None, check=False, diff=False)
    30. # 初始化所需的对象
    31. loader = DataLoader() # 负责查找和阅读 yaml、json、ini文件
    32. print(loader)
    33. # 设置ansible密码
    34. passwords = dict(conn_pass='D@ndy9989859')
    35. # 实例化 ResultCallback 以便在进入时处理结果,Ansible 希望这是它的主要展示渠道之一
    36. results_callback = ResultCallback()
    37. # 创建 inventory 使用路径将主机配置文件作为源,或以逗号分隔的字符串中的主机
    38. inventory = InventoryManager(loader=loader, sources='127.0.0.1')
    39. # inventory = InventoryManager(loader=loader, sources='/etc/ansible/hosts')
    40. # 变量管理器负责合并所有不同的源,为您提供每个上下文中可用变量的统一视图
    41. variable_manager = VariableManager(loader=loader, inventory=inventory)
    42. # 创建表示我们的 play 的数据结构,包括任务,这基本上是我们的 YAML 加载器在内部执行的操作
    43. play_source = dict(
    44. name = "Ansible Play",
    45. hosts = '127.0.0.1',
    46. gather_facts = 'yes',
    47. tasks = [
    48. dict(action=dict(module='shell', args='hostname'), register='shell_out'),
    49. #dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}')))
    50. ]
    51. )
    52. # 创建 play 对象, playbook 对象使用 .load 而不是 init 或 new 方法,这也将自动从 play_source 中提供的信息创建任务对象
    53. play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
    54. # 运行它 - 实例化任务队列管理器,它负责 forking 和设置所有对象以迭代主机列表和任务
    55. tqm = None
    56. try:
    57. tqm = TaskQueueManager(
    58. inventory=inventory,
    59. variable_manager=variable_manager,
    60. loader=loader,
    61. options=options,
    62. passwords=passwords,
    63. stdout_callback=results_callback, # 使用我们的自定义回调而不是``default``回调插件,它打印到stdout
    64. )
    65. result = tqm.run(play) # 一个 play 的数据实际上是发送到回调的方法
    66. finally:
    67. # 我们总是需要清理子进程和我们用来与它们通信的结构
    68. if tqm is not None:
    69. tqm.cleanup()
    70. # 删除 ansible 临时目录
    71. shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)