在第二篇文章中雖然可以執行adhoc和playbook但是執行結果的輸出並不是特別直觀,雖然沒有報錯但是到底什麼結果其實你是不知道的尤其是在執行adhoc的時候,這時候我們要利用callback來設定一下執行結果的輸出。
執行adhoc
#!/usr/bin/env python # -*- coding: utf-8 -*- from collections import namedtuple # 核心類 # 用於讀取YAML和JSON格式的檔案 import sys from ansible.parsing.dataloader import DataLoader # 用於儲存各類變數資訊 from ansible.vars.manager import VariableManager # 用於匯入資產檔案 from ansible.inventory.manager import InventoryManager # 儲存執行hosts的角色資訊 from ansible.playbook.play import Play # ansible底層用到的任務佇列 from ansible.executor.task_queue_manager import TaskQueueManager # 狀態回撥,各種成功失敗的狀態 from ansible.plugins.callback import CallbackBase class MyCallbackBase(CallbackBase): """ 透過api呼叫ac-hoc的時候輸出結果很多時候不是很明確或者說不是我們想要的結果,主要它還是輸出到STDOUT,而且通常我們是在工程裡面執行 這時候就需要後臺的結果前端可以解析,正常的API呼叫輸出前端很難解析。 對比之前的執行 adhoc()檢視區別。 為了實現這個目的就需要重寫CallbackBase類,需要重寫下面三個方法 """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # python3中過載父類構造方法的方式,在Python2中寫法會有區別。 self.host_ok = {} self.host_unreachable = {} self.host_failed = {} def v2_runner_on_unreachable(self, result): """ 重寫 unreachable 狀態 :param result: 這是父類裡面一個物件,這個物件可以獲取執行任務資訊 """ self.host_unreachable[result._host.get_name()] = result def v2_runner_on_ok(self, result, *args, **kwargs): """ 重寫 ok 狀態 :param result: """ self.host_ok[result._host.get_name()] = result def v2_runner_on_failed(self, result, *args, **kwargs): """ 重寫 failed 狀態 :param result: """ self.host_failed[result._host.get_name()] = result def useMyCallbackBase(): """ 這裡透過呼叫ad-hoc來使用自定義callback :return: """ dl = DataLoader() im = InventoryManager(loader=dl, sources=["hosts"]) vm = VariableManager(loader=dl, inventory=im) 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" ]) 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) play_source = dict(name="Ansible Play", # 任務名稱 hosts="test", # 目標主機,可以填寫具體主機也可以是主機組名稱 gather_facts="no", # 是否收集配置資訊 # tasks是具體執行的任務,列表形式,每個具體任務都是一個字典 tasks=[ dict(action=dict(module="shell", args="touch /tmp/bbb.txt", warn=False)) ]) play = Play().load(play_source, variable_manager=vm, loader=dl) passwords = dict() # 這個可以為空,因為在hosts檔案中 mycallback = MyCallbackBase() # 例項化自定義callback tqm = TaskQueueManager( inventory=im, variable_manager=vm, loader=dl, options=options, passwords=passwords, stdout_callback=mycallback # 配置使用自定義callback ) tqm.run(play) # print(mycallback.host_ok.items()) # 它會返回2個東西,一個主機一個是執行結果物件 # 定義資料結構 result_raw = {"success": {}, "failed": {}, "unreachable": {}} # 如果成功那麼 mycallback.host_ok.items() 才可以遍歷,上面的任務肯定能成功所以我們就直接遍歷這個 for host, result in mycallback.host_ok.items(): result_raw["success"][host] = result._result for host, result in mycallback.host_failed.items(): result_raw["failed"][host] = result._result for host, result in mycallback.host_unreachable.items(): result_raw["unreachable"][host] = result._result print(result_raw) def main(): useMyCallbackBase() if __name__ == "__main__": try: main() finally: sys.exit()
執行playbook
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys from collections import namedtuple # 核心類 # 用於讀取YAML和JSON格式的檔案 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 class MyPlaybookCallbackBase(CallbackBase): """ playbook的callback改寫,格式化輸出playbook執行結果 """ CALLBACK_VERSION = 2.0 def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.task_ok = {} self.task_unreachable = {} self.task_failed = {} self.task_skipped = {} self.task_status = {} def v2_runner_on_unreachable(self, result): """ 重寫 unreachable 狀態 :param result: 這是父類裡面一個物件,這個物件可以獲取執行任務資訊 """ self.task_unreachable[result._host.get_name()] = result def v2_runner_on_ok(self, result, *args, **kwargs): """ 重寫 ok 狀態 :param result: """ self.task_ok[result._host.get_name()] = result def v2_runner_on_failed(self, result, *args, **kwargs): """ 重寫 failed 狀態 :param result: """ self.task_failed[result._host.get_name()] = result def v2_runner_on_skipped(self, result): self.task_skipped[result._host.get_name()] = result def v2_playbook_on_stats(self, stats): hosts = sorted(stats.processed.keys()) for h in hosts: t = stats.summarize(h) self.task_status[h] = { "ok": t["ok"], "changed": t["changed"], "unreachable": t["unreachable"], "skipped": t["skipped"], "failed": t["failed"] } def usecallbackplaybook(): """ 呼叫 playbook 呼叫playboo大致和呼叫ad-hoc相同,只是真正呼叫的是使用PlaybookExecutor :return: """ dl = DataLoader() im = InventoryManager(loader=dl, sources=["hosts"]) vm = VariableManager(loader=dl, inventory=im) 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" ]) 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) passwords = dict() # 這個可以為空,因為在hosts檔案中 # try: playbook = PlaybookExecutor(playbooks=["f1.yml"], inventory=im, variable_manager=vm, loader=dl, options=options, passwords=passwords) callback = MyPlaybookCallbackBase() playbook._tqm._stdout_callback = callback # 配置callback playbook.run() # print(callback.task_ok.items()) result_raw = {"ok": {}, "failed": {}, "unreachable": {}, "skipped": {}, "status": {}} for host, result in callback.task_ok.items(): result_raw["ok"][host] = result._result for host, result in callback.task_failed.items(): result_raw["failed"][host] = result._result for host, result in callback.task_unreachable.items(): result_raw["unreachable"][host] = result._result for host, result in callback.task_skipped.items(): result_raw["skipped"][host] = result._result for host, result in callback.task_status.items(): result_raw["status"][host] = result._result print(result_raw) except Exception as err: print(err) def main(): usecallbackplaybook() if __name__ == "__main__": try: main() finally: sys.exit()