官網示例(python3)
說明:
在學習2.0 api的過程中遇到了一個坑,最新版的ansible(2.4)和2.3版本api引用時發生了變化,本文主要使用2.3 api進行操作,2.4只做分析
ansible api (ansible2.4)
#!/usr/bin/env python #-*-coding:utf-8 -*- import json from collections import namedtuple from ansible.parsing.dataloader import DataLoader from ansible.vars.manager import VariableManager #這里用的ansbile 2.4 from ansible.inventory.manager import InventoryManager #這里用的ansible 2.4 from ansible.playbook.play import Play from ansible.executor.task_queue_manager import TaskQueueManager from ansible.plugins.callback import CallbackBase #自定義運行callback,即運行完api后調用v2_runner_on_ok函數,打印host和result class ResultCallback(CallbackBase): def v2_runner_on_ok(self, result, **kwargs):
#result所包含屬性(_check_key..可用dir方法查看所包含的所有屬性)
host = result._host print(json.dumps({host.name: result._result}, indent=4)) #創建一個Options類型,列表里為屬性,這里用來設置ansible執行時的參數,如ask_pass,sudo_user等等(namedtuple創建一個和tuple類似的對象,而且對象擁有可以訪問的屬性) Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check', 'diff']) # initialize needed objects loader = DataLoader() #可以通過options.(屬性) 的方法去獲取屬性的值,如獲取connection的值可以直接寫成options.connection options = Options(connection='local', module_path='/path/to/mymodules', 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() # 加載inventory變量,這里的sources的值可以是hosts文件,也可以是ip列表,如['xxx.xxx.xx.x','xx.xx.xx.xx'] inventory = InventoryManager(loader=loader, sources=['/etc/ansible/hosts']) #管理變量的類,包括主機、組、擴展等變量 variable_manager = VariableManager(loader=loader, inventory=inventory) # 創建一個任務 play_source = dict( name = "Ansible Play", hosts = 'test', #這里寫在上面inventory里設置的sources所指定的文件里的組名 gather_facts = 'no', tasks = [ dict(action=dict(module='shell', args='ls'), register='shell_out'), dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}'))) ] ) play = Play().load(play_source, variable_manager=variable_manager, loader=loader) # actually run it tqm = None try: tqm = TaskQueueManager( #詳細參數看源碼 inventory=inventory, variable_manager=variable_manager, loader=loader, #ansible.parsing.dataloader模塊創建,用於數據解析 options=options, #存放各類配置信息,ansible執行時的各種參數 passwords=passwords, #登錄密碼 stdout_callback=results_callback, #回調函數,調用最上面定義的callback函數 ) result = tqm.run(play) finally: if tqm is not None: tqm.cleanup()
ansible2.3 api
#!/usr/bin/env python
# -*-coding:utf-8 -*-
import json
from collections import namedtuple
from ansible.parsing.dataloader import DataLoader
from ansible.vars import VariableManager
from ansible.inventory import Inventory
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.plugins.callback import CallbackBase
# 自定義運行callback,即運行完api后調用v2_runner_on_ok函數,打印host和result
class ResultCallback(CallbackBase):
def v2_runner_on_ok(self, result, **kwargs): #執行完會生成一個result結果,通過result.__ditct__可打印所有的方法,其中_result和_host方法為主要內容
host = result._host
print(json.dumps({host.name: result._result}, indent=4))
# 創建一個Options類型,列表里為屬性,這里用來設置ansible執行時的參數,如ask_pass,sudo_user等等(namedtuple創建一個和tuple類似的對象,而且對象擁有可以訪問的屬性)
Options = namedtuple('Options',
['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check', 'diff'])
# initialize needed objects
loader = DataLoader()
# 可以通過options.(屬性) 的方法去獲取屬性的值,如獲取connection的值可以直接寫成options.connection
options = Options(connection='local', module_path='/path/to/mymodules', 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()
# 管理變量的類,包括主機、組、擴展等變量
variable_manager = VariableManager()
# 加載inventory變量,這里的sources的值可以是hosts文件,也可以是ip列表,如['xxx.xxx.xx.x','xx.xx.xx.xx']
inventory = Inventory(loader=loader, variable_manager=variable_manager,host_list='/etc/ansible/hosts')
# 創建一個任務
play_source = dict(
name="Ansible Play",
hosts='test',
gather_facts = 'no',
tasks = [
dict(action=dict(module='shell', args='ls'), register='shell_out'),
dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}')))
]
)
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
# actually run it
tqm = None
try:
tqm = TaskQueueManager(
inventory = inventory,
variable_manager = variable_manager,
loader = loader,
options = options,
passwords = passwords,
stdout_callback = results_callback,
)
result = tqm.run(play)
finally:
if tqm is not None:
tqm.cleanup()
ansible-playbook api調用方式(ansible 2.3.1)
#!/usr/bin/env python import json from collections import namedtuple from ansible.parsing.dataloader import DataLoader from ansible.vars import VariableManager from ansible.inventory import Inventory from ansible.executor.playbook_executor import PlaybookExecutor #引入executor模塊
#用來加載解析yml文件或者json內容 loader = DataLoader() variable_manager = VariableManager()
# 根據inventory加載對應變量,此處host_list參數可以有兩種格式: # 1: hosts文件(需要), # 2: 可以是IP列表,此處使用IP列表
inventory = Inventory(loader=loader, variable_manager=variable_manager,host_list='/etc/ansible/hosts') #這里可通過分析源碼得到參數
variable_manager.set_inventory(inventory)
passwords=None
#初始化 Options = namedtuple('Options', ['connection', 'remote_user', 'ask_sudo_pass', 'verbosity', 'ack_pass', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check', 'listhosts', 'listtasks', 'listtags', 'syntax', 'sudo_user', 'sudo'])
#初始化需要的對象 options = Options(connection='smart', remote_user='root', ack_pass=None, sudo_user='root', forks=100, sudo='yes', ask_sudo_pass=False, verbosity=5, module_path=None, become=True, become_method='sudo', become_user='root', check=None, listhosts=None, listtasks=None, listtags=None, syntax=None) # 多個yaml文件則以列表形式 playbook = PlaybookExecutor(playbooks=['/etc/ansible/test.yml'],inventory=inventory, variable_manager=variable_manager, loader=loader,options=options,passwords=passwords) result = playbook.run() print (result) #ansible-playbook模塊沒有與callback模塊共用
test.yml
[root@bogon ~]# cat test.yml --- - hosts: 10.10.10.11 gather_facts: false sudo: True remote_user: root tasks: - shell: ifconfig register: output - debug: var=output.stdout [root@bogon ~]#
執行結果:

[root@bogon ~]# python aa.py PLAY [10.10.10.11] **************************************************************************************************************************************************************************** TASK [command] ******************************************************************************************************************************************************************************** changed: [10.10.10.11] {"_ansible_parsed": true, "stderr_lines": [], "cmd": "ifconfig", "end": "2018-02-01 14:49:00.920984", "_ansible_no_log": false, "stdout": "ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n inet 10.10.10.11 netmask 255.255.255.0 broadcast 10.10.10.255\n inet6 fe80::250:56ff:fe93:e5c6 prefixlen 64 scopeid 0x20<link>\n ether 00:50:56:93:e5:c6 txqueuelen 1000 (Ethernet)\n RX packets 10048045 bytes 1340025577 (1.2 GiB)\n RX errors 0 dropped 0 overruns 0 frame 0\n TX packets 9885546 bytes 975436242 (930.2 MiB)\n TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0\n\nlo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536\n inet 127.0.0.1 netmask 255.0.0.0\n inet6 ::1 prefixlen 128 scopeid 0x10<host>\n loop txqueuelen 1 (Local Loopback)\n RX packets 5214029 bytes 417704433 (398.3 MiB)\n RX errors 0 dropped 0 overruns 0 frame 0\n TX packets 5214029 bytes 417704433 (398.3 MiB)\n TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0\n\nvirbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500\n inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255\n ether 52:54:00:b7:6f:ef txqueuelen 1000 (Ethernet)\n RX packets 0 bytes 0 (0.0 B)\n RX errors 0 dropped 0 overruns 0 frame 0\n TX packets 0 bytes 0 (0.0 B)\n TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0", "changed": true, "rc": 0, "start": "2018-02-01 14:49:00.908486", "stderr": "", "delta": "0:00:00.012498", "invocation": {"module_args": {"warn": true, "executable": null, "_uses_shell": true, "_raw_params": "ifconfig", "removes": null, "creates": null, "chdir": null}}, "stdout_lines": ["ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500", " inet 10.10.10.11 netmask 255.255.255.0 broadcast 10.10.10.255", " inet6 fe80::250:56ff:fe93:e5c6 prefixlen 64 scopeid 0x20<link>", " ether 00:50:56:93:e5:c6 txqueuelen 1000 (Ethernet)", " RX packets 10048045 bytes 1340025577 (1.2 GiB)", " RX errors 0 dropped 0 overruns 0 frame 0", " TX packets 9885546 bytes 975436242 (930.2 MiB)", " TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0", "", "lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536", " inet 127.0.0.1 netmask 255.0.0.0", " inet6 ::1 prefixlen 128 scopeid 0x10<host>", " loop txqueuelen 1 (Local Loopback)", " RX packets 5214029 bytes 417704433 (398.3 MiB)", " RX errors 0 dropped 0 overruns 0 frame 0", " TX packets 5214029 bytes 417704433 (398.3 MiB)", " TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0", "", "virbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500", " inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255", " ether 52:54:00:b7:6f:ef txqueuelen 1000 (Ethernet)", " RX packets 0 bytes 0 (0.0 B)", " RX errors 0 dropped 0 overruns 0 frame 0", " TX packets 0 bytes 0 (0.0 B)", " TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0"]} TASK [debug] ********************************************************************************************************************************************************************************** ok: [10.10.10.11] => { "output.stdout": "ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n inet 10.10.10.11 netmask 255.255.255.0 broadcast 10.10.10.255\n inet6 fe80::250:56ff:fe93:e5c6 prefixlen 64 scopeid 0x20<link>\n ether 00:50:56:93:e5:c6 txqueuelen 1000 (Ethernet)\n RX packets 10048045 bytes 1340025577 (1.2 GiB)\n RX errors 0 dropped 0 overruns 0 frame 0\n TX packets 9885546 bytes 975436242 (930.2 MiB)\n TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0\n\nlo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536\n inet 127.0.0.1 netmask 255.0.0.0\n inet6 ::1 prefixlen 128 scopeid 0x10<host>\n loop txqueuelen 1 (Local Loopback)\n RX packets 5214029 bytes 417704433 (398.3 MiB)\n RX errors 0 dropped 0 overruns 0 frame 0\n TX packets 5214029 bytes 417704433 (398.3 MiB)\n TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0\n\nvirbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500\n inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255\n ether 52:54:00:b7:6f:ef txqueuelen 1000 (Ethernet)\n RX packets 0 bytes 0 (0.0 B)\n RX errors 0 dropped 0 overruns 0 frame 0\n TX packets 0 bytes 0 (0.0 B)\n TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0" } {"output.stdout": "ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n inet 10.10.10.11 netmask 255.255.255.0 broadcast 10.10.10.255\n inet6 fe80::250:56ff:fe93:e5c6 prefixlen 64 scopeid 0x20<link>\n ether 00:50:56:93:e5:c6 txqueuelen 1000 (Ethernet)\n RX packets 10048045 bytes 1340025577 (1.2 GiB)\n RX errors 0 dropped 0 overruns 0 frame 0\n TX packets 9885546 bytes 975436242 (930.2 MiB)\n TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0\n\nlo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536\n inet 127.0.0.1 netmask 255.0.0.0\n inet6 ::1 prefixlen 128 scopeid 0x10<host>\n loop txqueuelen 1 (Local Loopback)\n RX packets 5214029 bytes 417704433 (398.3 MiB)\n RX errors 0 dropped 0 overruns 0 frame 0\n TX packets 5214029 bytes 417704433 (398.3 MiB)\n TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0\n\nvirbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500\n inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255\n ether 52:54:00:b7:6f:ef txqueuelen 1000 (Ethernet)\n RX packets 0 bytes 0 (0.0 B)\n RX errors 0 dropped 0 overruns 0 frame 0\n TX packets 0 bytes 0 (0.0 B)\n TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0", "_ansible_no_log": false, "_ansible_verbose_always": true} PLAY RECAP ************************************************************************************************************************************************************************************ 10.10.10.11 : ok=2 changed=1 unreachable=0 failed=0
附:2.4源碼目錄結構:
vars目錄
##ansible2.4 [root@slave3 ansible]# tree vars/ vars/ ├── hostvars.py ├── hostvars.pyc ├── hostvars.pyo ├── __init__.py ├── __init__.pyc ├── __init__.pyo ├── manager.py ├── manager.pyc ├── manager.pyo ├── reserved.py ├── reserved.pyc ├── reserved.pyo ├── unsafe_proxy.py ├── unsafe_proxy.pyc └── unsafe_proxy.pyo 0 directories, 15 files #ansible2.3 root@ubuntu:/usr/local/lib/python3.5/dist-packages/ansible# tree vars/ vars/ ├── hostvars.py ├── __init__.py #具體類和方法看下圖 ├── __pycache__ │ ├── hostvars.cpython-35.pyc │ ├── __init__.cpython-35.pyc │ ├── reserved.cpython-35.pyc │ └── unsafe_proxy.cpython-35.pyc ├── reserved.py └── unsafe_proxy.py 1 directory, 8 files
2.3
2.4的就不貼了,
2.3 的 VariableManager 類放到了 __init__下,可直接引用,2.4的則放在了manager下,
inventory
##ansible 2.3 root@ubuntu:/usr/local/lib/python3.5/dist-packages/ansible# tree inventory/ inventory/ ├── dir.py ├── expand_hosts.py ├── group.py ├── host.py ├── ini.py ├── __init__.py ├── __pycache__ │ ├── dir.cpython-35.pyc │ ├── expand_hosts.cpython-35.pyc │ ├── group.cpython-35.pyc │ ├── host.cpython-35.pyc │ ├── ini.cpython-35.pyc │ ├── __init__.cpython-35.pyc │ ├── script.cpython-35.pyc │ └── yaml.cpython-35.pyc ├── script.py ├── vars_plugins │ ├── __init__.py │ ├── noop.py │ └── __pycache__ │ ├── __init__.cpython-35.pyc │ └── noop.cpython-35.pyc └── yaml.py 3 directories, 20 files
##ansible2.4 [root@slave3 ansible]# tree inventory/ inventory/ ├── data.py ├── data.pyc ├── data.pyo ├── group.py ├── group.pyc ├── group.pyo ├── helpers.py ├── helpers.pyc ├── helpers.pyo ├── host.py ├── host.pyc ├── host.pyo ├── __init__.py ├── __init__.pyc ├── __init__.pyo ├── manager.py ├── manager.pyc └── manager.pyo
2.3
2.4略
模塊導入時:
##ansible2.3 from collections import namedtuple from ansible.parsing.dataloader import DataLoader from ansible.vars import VariableManager from ansible.inventory import Inventory from ansible.executor.playbook_executor import PlaybookExecutor ##ansible2.4 from collections import namedtuple from ansible.parsing.dataloader import DataLoader from ansible.vars.manager import VariableManager from ansible.inventory.manager import InventoryManager #參數略有改變 from ansible.executor.playbook_executor import PlaybookExecutor
簡單整合 2.3.1
#!/usr/bin/env python import json from collections import namedtuple from ansible.parsing.dataloader import DataLoader from ansible.vars import VariableManager from ansible.inventory import Inventory from ansible.executor.playbook_executor import PlaybookExecutor from ansible.plugins.callback import CallbackBase from ansible.playbook.play import Play from ansible.executor.task_queue_manager import TaskQueueManager class ResultsCallback(CallbackBase): def __init__(self,*args,**kwargs): super(ResultsCallback,self).__init__(*args,**kwargs) self.task_ok = {} self.task_unreachable = {} self.task_failed = {} self.task_skipped = {} self.task_stats = {} # self.host_ok = {} # self.host_unreachable = {} # self.host_failed = {} def v2_runner_on_unreachable(self, result): self.task_unreachable[result._host.get_name()] = result def v2_runner_on_ok(self, result, *args, **kwargs): self.task_ok[result._host.get_name()] = result def v2_runner_on_failed(self, result, *args, **kwargs): self.task_failed[result._host.get_name()] = result def v2_runner_on_skipped(self, result, *args, **kwargs): self.task_skipped[result._host.get_name()] = result def v2_runner_on_stats(self, result, *args, **kwargs): self.task_stats[result._host.get_name()] = result #chushihua class Runner(object): def __init__(self,*args,**kwargs): self.loader = DataLoader() self.variable_manager = VariableManager() self.results_callback = ResultsCallback() self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list='/etc/ansible/hosts') self.variable_manager.set_inventory(self.inventory) self.passwords = None Options = namedtuple('Options', ['connection', 'remote_user', 'verbosity', 'ack_pass', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check', 'listhosts', 'listtasks', 'listtags', 'syntax', ]) # 初始化需要的對象 self.options = Options(connection='smart', remote_user='root', ack_pass=None, forks=100, verbosity=5, module_path=None, become=True, become_method='sudo', become_user='root', check=None, listhosts=None, listtasks=None, listtags=None, syntax=None) def run_ad_hoc(self): play_source = dict( name="Ansible Play", hosts='test', gather_facts='no', tasks=[ dict(action=dict(module='shell', args='ls /home'), register='shell_out'), dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}'))) ] ) play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader) tqm = None try: tqm = TaskQueueManager( inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords, stdout_callback=self.results_callback, ) result = tqm.run(play) finally: if tqm is not None: tqm.cleanup() ##定義字典用於接收或者處理結果 result_raw = {'success': {}, 'failed': {}, 'unreachable': {}, 'skipped': {}, 'status': {}} # 循環打印這個結果,success,failed,unreachable需要每個都定義一個 for host, result in self.results_callback.task_ok.items(): result_raw['success'][host] = result._result for host, result in self.results_callback.task_failed.items(): result_raw['failed'][host] = result._result for host, result in self.results_callback.task_unreachable.items(): result_raw['unreachable'][host] = result._result return result_raw def run_playbook(self): playbook = PlaybookExecutor(playbooks=['/root/test.yml'], inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords) playbook._tqm._stdout_callback = self.results_callback results = playbook.run() ##定義字典用於接收或者處理結果 result_raw = {'success': {}, 'failed': {}, 'unreachable': {}, 'skipped': {}, 'status': {}} # 循環打印這個結果,success,failed,unreachable需要每個都定義一個 for host, result in self.results_callback.task_ok.items(): result_raw['success'][host] = result._result for host, result in self.results_callback.task_failed.items(): result_raw['failed'][host] = result._result for host, result in self.results_callback.task_unreachable.items(): result_raw['unreachable'][host] = result._result for host, result in self.results_callback.task_skipped.items(): result_raw['skipped'][host] = result._result for host, result in self.results_callback.task_stats.items(): result_raw['status'][host] = result._result return result_raw c = Runner() print (c.run_ad_hoc(),c.run_playbook())
2.4.1
#!/usr/bin/env python import json from collections import namedtuple from ansible.parsing.dataloader import DataLoader from ansible.vars.manager import VariableManager from ansible.inventory.manager import InventoryManager from ansible.executor.playbook_executor import PlaybookExecutor from ansible.plugins.callback import CallbackBase from ansible.playbook.play import Play from ansible.executor.task_queue_manager import TaskQueueManager class ResultsCallback(CallbackBase): def __init__(self,*args,**kwargs): super(ResultsCallback,self).__init__(*args,**kwargs) self.task_ok = {} self.task_unreachable = {} self.task_failed = {} self.task_skipped = {} self.task_stats = {} # self.host_ok = {} # self.host_unreachable = {} # self.host_failed = {} def v2_runner_on_unreachable(self, result): self.task_unreachable[result._host.get_name()] = result def v2_runner_on_ok(self, result, *args, **kwargs): self.task_ok[result._host.get_name()] = result def v2_runner_on_failed(self, result, *args, **kwargs): self.task_failed[result._host.get_name()] = result def v2_runner_on_skipped(self, result, *args, **kwargs): self.task_skipped[result._host.get_name()] = result def v2_runner_on_stats(self, result, *args, **kwargs): self.task_stats[result._host.get_name()] = result #chushihua class Runner(object): def __init__(self,*args,**kwargs): self.loader = DataLoader() self.results_callback = ResultsCallback() self.inventory = InventoryManager(loader=self.loader,sources=['/etc/ansible/hosts']) self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory) self.passwords = None Options = namedtuple('Options', ['connection', 'remote_user', 'ask_sudo_pass', 'verbosity', 'ack_pass', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check', 'listhosts', 'listtasks', 'listtags', 'syntax', 'sudo_user', 'sudo', 'diff']) # 初始化需要的對象 self.options = Options(connection='smart', remote_user=None, ack_pass=None, sudo_user=None, forks=5, sudo=None, ask_sudo_pass=False, verbosity=5, module_path=None, become=None, become_method=None, become_user=None, check=False, diff=False, listhosts=None, listtasks=None, listtags=None, syntax=None) def run_ad_hoc(self): play_source = dict( name="Ansible Play ad-hoc", hosts='test', gather_facts='no', tasks=[ dict(action=dict(module='shell', args='ls /home'), register='shell_out'), #dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}'))) ] ) play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader) tqm = None try: tqm = TaskQueueManager( inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords, stdout_callback=self.results_callback, ) result = tqm.run(play) finally: if tqm is not None: tqm.cleanup() ##定義字典用於接收或者處理結果 result_raw = {'success': {}, 'failed': {}, 'unreachable': {}, 'skipped': {}, 'status': {}} # 循環打印這個結果,success,failed,unreachable需要每個都定義一個 for host, result in self.results_callback.task_ok.items(): result_raw['success'][host] = result._result for host, result in self.results_callback.task_failed.items(): result_raw['failed'][host] = result._result for host, result in self.results_callback.task_unreachable.items(): result_raw['unreachable'][host] = result._result return result_raw def run_playbook(self): playbook = PlaybookExecutor(playbooks=['/root/test.yml'], inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords) playbook._tqm._stdout_callback = self.results_callback results = playbook.run() ##定義字典用於接收或者處理結果 result_raw = {'success': {}, 'failed': {}, 'unreachable': {}, 'skipped': {}, 'status': {}} # 循環打印這個結果,success,failed,unreachable需要每個都定義一個 for host, result in self.results_callback.task_ok.items(): result_raw['success'][host] = result._result for host, result in self.results_callback.task_failed.items(): result_raw['failed'][host] = result._result for host, result in self.results_callback.task_unreachable.items(): result_raw['unreachable'][host] = result._result for host, result in self.results_callback.task_skipped.items(): result_raw['skipped'][host] = result._result for host, result in self.results_callback.task_stats.items(): result_raw['status'][host] = result._result return result_raw c = Runner() print (c.run_ad_hoc(),c.run_playbook())

#!/usr/bin/env python import json from collections import namedtuple from ansible.parsing.dataloader import DataLoader from ansible.vars.manager import VariableManager from ansible.inventory.manager import InventoryManager from ansible.executor.playbook_executor import PlaybookExecutor from ansible.plugins.callback import CallbackBase from ansible.playbook.play import Play from ansible.executor.task_queue_manager import TaskQueueManager class PlaybookResultsCallback(CallbackBase): def __init__(self,*args,**kwargs): super(PlaybookResultsCallback,self).__init__(*args,**kwargs) self.task_ok = {} self.task_unreachable = {} self.task_failed = {} self.task_skipped = {} self.task_stats = {} def v2_runner_on_unreachable(self, result): self.task_unreachable[result._host.get_name()] = result def v2_runner_on_ok(self, result, *args, **kwargs): self.task_ok[result._host.get_name()] = result def v2_runner_on_failed(self, result, *args, **kwargs): self.task_failed[result._host.get_name()] = result def v2_runner_on_skipped(self, result, *args, **kwargs): self.task_skipped[result._host.get_name()] = result def v2_runner_on_stats(self, result, *args, **kwargs): self.task_stats[result._host.get_name()] = result class ResultsCallback(CallbackBase): def __init__(self,*args,**kwargs): super(ResultsCallback,self).__init__(*args,**kwargs) self.host_ok = {} self.host_unreachable = {} self.host_failed = {} def v2_runner_on_unreachable(self, result): self.host_unreachable[result._host.get_name()] = result def v2_runner_on_ok(self, result, *args, **kwargs): self.host_ok[result._host.get_name()] = result def v2_runner_on_failed(self, result, *args, **kwargs): self.host_failed[result._host.get_name()] = result #chushihua class Runner(object): def __init__(self,*args,**kwargs): self.loader = DataLoader() self.results_callback = ResultsCallback() self.Playbook_results_callback = PlaybookResultsCallback() self.inventory = InventoryManager(loader=self.loader,sources=['/etc/ansible/hosts']) self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory) self.passwords = None self.results_raw = {} Options = namedtuple('Options', ['connection', 'remote_user', 'ask_sudo_pass', 'verbosity', 'ack_pass', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check', 'listhosts', 'listtasks', 'listtags', 'syntax', 'sudo_user', 'sudo', 'diff']) # 初始化需要的對象 self.options = Options(connection='smart', remote_user=None, ack_pass=None, sudo_user=None, forks=5, sudo=None, ask_sudo_pass=False, verbosity=5, module_path=None, become=None, become_method=None, become_user=None, check=False, diff=False, listhosts=None, listtasks=None, listtags=None, syntax=None) def run_ad_hoc(self): play_source = dict( name="Ansible Play ad-hoc", hosts='test', gather_facts='no', tasks=[ dict(action=dict(module='shell', args='ls /home'), register='shell_out'), #dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}'))) ] ) play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader) tqm = None try: tqm = TaskQueueManager( inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords, stdout_callback=self.results_callback, ) result = tqm.run(play) finally: if tqm is not None: tqm.cleanup() ##定義字典用於接收或者處理結果 def get_adhoc_result(self): self.results_raw = {'success': {}, 'failed': {}, 'unreachable': {}} for host, result in self.results_callback.host_ok.items(): hostvisiable = host.replace('.', '_') self.results_raw['success'][hostvisiable] = result._result for host, result in self.results_callback.host_failed.items(): hostvisiable = host.replace('.', '_') self.results_raw['failed'][hostvisiable] = result._result for host, result in self.results_callback.host_unreachable.items(): hostvisiable = host.replace('.', '_') self.results_raw['unreachable'][hostvisiable] = result._result return self.results_raw def run_playbook(self,extra_vars=None): if extra_vars: self.variable_manager.extra_vars = extra_vars playbook = PlaybookExecutor(playbooks=['/root/test.yml'], inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=self.passwords) playbook._tqm._stdout_callback = self.Playbook_results_callback results = playbook.run() def get_playbook_result(self): ##定義字典用於接收或者處理結果 self.result_raw = {'success': {}, 'failed': {}, 'unreachable': {}, 'skipped': {}, 'status': {}} # 循環打印這個結果,success,failed,unreachable需要每個都定義一個 for host, result in self.Playbook_results_callback.task_ok.items(): self.result_raw['success'][host] = result._result for host, result in self.Playbook_results_callback.task_failed.items(): self.result_raw['failed'][host] = result._result for host, result in self.Playbook_results_callback.task_unreachable.items(): self.result_raw['unreachable'][host] = result._result for host, result in self.Playbook_results_callback.task_skipped.items(): self.result_raw['skipped'][host] = result._result for host, result in self.Playbook_results_callback.task_stats.items(): self.result_raw['status'][host] = result._result return self.result_raw c = Runner() c.run_ad_hoc() c.run_playbook() print (c.get_adhoc_result(),c.get_playbook_result())