概括前端
核心類 | 用途 | 所在的模塊路徑 |
DataLoader | 用於讀取yaml、json格式的文件 | ansible.parsing.dataloader |
Play | 存儲執行hosts的角色信息 | ansible.playbook.play |
TaskQueueManager | ansible底層用到的任務隊列 | ansible.executor.task_queue_manager |
PlaybookExecutor | 核心類執行playbook劇本 | ansible.executor.playbook_executor |
CallbackBase | 狀態回調,各類成功失敗的狀態 | ansible.plugins.callback |
InventoryManager | 用於導入inventory文件 | ansible.inventory.manager |
VariableManager | 用於存儲各種變量信息 | ansible.var.manager |
Host,Group | 操做單個主機或者主機組信息 | ansible.inventory.host |
功能:用來管理主機和主機組相關的資源設備信息python
from ansible.parsing.dataloader import DataLoader from ansible.inventory.manager import InventoryManager from ansible.vars.manager import VariableManager # InventoryManager類 loader = DataLoader() # 實例化對象 inv = InventoryManager(loader=loader,sources=['auto_hosts'])
# add_host()方法,添加主機到指定的主機組 inv.add_host(host='192.168.1.112',port=22,group='test_group3') # get_groups_dict()方法,查看主機組資源 inv.get_groups_dict() """ {'all': ['192.168.1.112', '192.168.1.101', '192.168.1.110'], 'test_group1': ['192.168.1.112', '192.168.1.101', '192.168.1.110'], 'test_group2': ['192.168.1.112', '192.168.1.101'], 'test_group3': ['192.168.1.110', '192.168.1.112'], 'ungrouped': []} """ # get_hosts() 獲取全部的主機信息,返回的爲列表 inv.get_hosts # [192.168.1.112, 192.168.1.101, 192.168.1.110] # get_host() 獲取指定的主機對象 inv.get_host(hostname='192.168.1.112') # 192.168.1.112
功能:進行主機變量的讀取web
from ansible.parsing.dataloader import DataLoader from ansible.inventory.manager import InventoryManager from ansible.vars.manager import VariableManager # InventoryManager類 loader = DataLoader() # 實例化對象 inv = InventoryManager(loader=loader,sources=['auto_hosts']) #VariableManager類 variable_manager = VariableManager(loader=loader,inventory=inv) # get_vars() # 查看變量方法 variable_manager.get_vars() """ {'ansible_playbook_python': '/usr/bin/python3', 'groups': {'all': ['192.168.1.112', '192.168.1.101', '192.168.1.110'], 'test_group1': ['192.168.1.112', '192.168.1.101', '192.168.1.110'], 'test_group2': ['192.168.1.112', '192.168.1.101'], 'test_group3': ['192.168.1.110', '192.168.1.112'], 'ungrouped': []}, 'omit': '__omit_place_holder__04e40184623ea65c38973233a8c804a29215f21d', 'playbook_dir': '/u01/autoops/script'} """ # get_vars() # 查詢主機指定的變量信息 host = inv.get_host(hostname='192.168.1.110') variable_manager.get_vars(host=host) """ {'ansible_playbook_python': '/usr/bin/python3', 'ansible_port': 22, 'ansible_ssh_pass': 123456, 'ansible_ssh_user': 'root', 'group_names': ['test_group1', 'test_group3'], 'groups': {'all': ['192.168.1.112', '192.168.1.101', '192.168.1.110'], 'test_group1': ['192.168.1.112', '192.168.1.101', '192.168.1.110'], 'test_group2': ['192.168.1.112', '192.168.1.101'], 'test_group3': ['192.168.1.110', '192.168.1.112'], 'ungrouped': []}, 'inventory_dir': '/u01/autoops/script', 'inventory_file': '/u01/autoops/script/auto_hosts', 'inventory_hostname': '192.168.1.110', 'inventory_hostname_short': '192', 'omit': '__omit_place_holder__3d8bb8c134c30295abd201bee6ef34093e580c2f', 'playbook_dir': '/u01/autoops/script'} """ # set_host_variable() # 修改指定主機的變量信息 variable_manager.set_host_variable(host=host,varname='ansible_ssh_pass',value='111111') variable_manager.get_vars(host=host) """ {'ansible_playbook_python': '/usr/bin/python3', 'ansible_port': 22, 'ansible_ssh_pass': '111111', 'ansible_ssh_user': 'root', 'group_names': ['test_group1', 'test_group3'], 'groups': {'all': ['192.168.1.112', '192.168.1.101', '192.168.1.110'], 'test_group1': ['192.168.1.112', '192.168.1.101', '192.168.1.110'], 'test_group2': ['192.168.1.112', '192.168.1.101'], 'test_group3': ['192.168.1.110', '192.168.1.112'], 'ungrouped': []}, 'inventory_dir': '/u01/autoops/script', 'inventory_file': '/u01/autoops/script/auto_hosts', 'inventory_hostname': '192.168.1.110', 'inventory_hostname_short': '192', 'omit': '__omit_place_holder__3d8bb8c134c30295abd201bee6ef34093e580c2f', 'playbook_dir': '/u01/autoops/script'}
""" # extra_vars={} # 添加指定對象的擴展變量,全局有效 variable_manager.extra_vars={'myweb':'jd.com','myname':'jacob'} variable_manager.get_vars(host=host) """ {'ansible_playbook_python': '/usr/bin/python3', 'ansible_port': 22, 'ansible_ssh_pass': '111111', 'ansible_ssh_user': 'root', 'group_names': ['test_group1', 'test_group2', 'test_group3'], 'groups': {'all': ['192.168.1.112', '192.168.1.101', '192.168.1.110'], 'test_group1': ['192.168.1.112', '192.168.1.101', '192.168.1.110'], 'test_group2': ['192.168.1.112', '192.168.1.101'], 'test_group3': ['192.168.1.110', '192.168.1.112'], 'ungrouped': []}, 'inventory_dir': '/u01/autoops/script', 'inventory_file': '/u01/autoops/script/auto_hosts', 'inventory_hostname': '192.168.1.110', 'inventory_hostname_short': '192', 'myname': 'jacob', 'myweb': 'jd.com', 'omit': '__omit_place_holder__04e40184623ea65c38973233a8c804a29215f21d', 'playbook_dir': '/u01/autoops/script'}
"""
ansible的ad-hoc模式的調用示例:shell
ad-hoc模式通常用於批量執行簡單命令,文件替換等。此處的重點是執行對象和模塊,資源資產配置清單,執行選項。json
所需類及其調用關係爲:後端
2.3.1 namedtuple的用法回顧api
from collections import namedtuple # User = namedtuple('User', 'name age id') User = namedtuple('User', ['name', 'age', 'id']) user = User('tester', '22', '24242432') print(user) # User(name='tester', age='22', id='24242432')
2.3.2 ansible的ad-hoc模式options總結併發
-v, --verbose:輸出更詳細的執行過程信息,-vvv可獲得全部執行過程信息。 -i PATH, --inventory=PATH:指定inventory信息,默認/etc/ansible/hosts。 -f NUM, --forks=NUM:併發線程數,默認5個線程。 --private-key=PRIVATE_KEY_FILE:指定密鑰文件。 -m NAME, --module-name=NAME:指定執行使用的模塊。 -M DIRECTORY, --module-path=DIRECTORY:指定模塊存放路徑,默認/usr/share/ansible,也能夠經過ANSIBLE_LIBRARY設定默認路徑。 -a 'ARGUMENTS', --args='ARGUMENTS':模塊參數。 -k, --ask-pass SSH:認證密碼。 -K, --ask-sudo-pass sudo:用戶的密碼(—sudo時使用)。 -o, --one-line:標準輸出至一行。 -s, --sudo:至關於Linux系統下的sudo命令。 -t DIRECTORY, --tree=DIRECTORY:輸出信息至DIRECTORY目錄下,結果文件以遠程主機名命名。 -T SECONDS, --timeout=SECONDS:指定鏈接遠程主機的最大超時,單位是:秒。 -B NUM, --background=NUM:後臺執行命令,超NUM秒後kill正在執行的任務。 -P NUM, --poll=NUM:按期返回後臺任務進度。 -u USERNAME, --user=USERNAME:指定遠程主機以USERNAME運行命令。 -U SUDO_USERNAME, --sudo-user=SUDO_USERNAM:E使用sudo,至關於Linux下的sudo命令。 -c CONNECTION, --connection=CONNECTION:指定鏈接方式,可用選項paramiko (SSH), ssh, local。Local方式經常使用於crontab 和 kickstarts。 -l SUBSET, --limit=SUBSET:指定運行主機。 -l ~REGEX, --limit=~REGEX:指定運行主機(正則)。 --list-hosts:列出符合條件的主機列表,不執行任何其餘命令
2.3.3 結合options和play類的使用的簡單案例框架
# -*- coding: utf-8 -*- #!/usr/bin/env python #核心類 from collections import namedtuple from ansible.parsing.dataloader import DataLoader from ansible.vars.manager import VariableManager from ansible.inventory.manager import InventoryManager from ansible.playbook.play import Play from ansible.executor.task_queue_manager import TaskQueueManager from ansible.plugins.callback import CallbackBase #InventoryManager類 loader = DataLoader() inventory = InventoryManager(loader=loader,sources=['auto_hosts']) #VariableManager類 variable_manager = VariableManager(loader=loader,inventory=inventory) #Options 執行選項 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 執行對象和模塊 play_source = dict( name = "Ansible Play ad-hoc test", # 任務執行的名稱 hosts = '192.168.102.101', # # 控制着任務執行的目標主機,能夠經過逗號填入多臺主機,或者正則匹配,或者主機組 gather_facts = 'no', # 執行任務以前去獲取響應主機的相關信息,建議關閉,提升執行效率 tasks = [ # 以dict的方式實現,一個任務一個dict,能夠寫多個,module 爲對應模塊,args爲傳入的參數 dict(action=dict(module='shell', args='touch /tmp/ad_hoc_test1')), # dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}'))) ] ) play = Play().load(play_source, variable_manager=variable_manager, loader=loader) passwords = dict() # 沒有實際做用,實際中密碼已經寫在文件中了 tqm = TaskQueueManager( inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords, ) result = tqm.run(play)
[root@test01 script]# python3 ansible_api_k1.py PLAY [Ansible Play ad-hoc test] ******************************************************************************************************************************************* TASK [command] ************************************************************************************************************************************************************ [WARNING]: Consider using file module with state=touch rather than running touch changed: [192.168.102.101] # 且在192.168.102.101生成/tmp/ad_hoc_test1文件
ansible的paybook模式的調用示例:ssh
palybook模式通常用於批量執行復雜的自動化任務,如批量安裝等。此處的重點是資源資產配置清單,執行選項等。
所需類及其調用關係爲:
2.4.1 playbook結合options和play類的使用的簡單案例
# -*- coding: utf-8 -*- #!/usr/bin/env python #核心類 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.playbook.play import Play from ansible.executor.task_queue_manager import TaskQueueManager #InventoryManager類 loader = DataLoader() inventory = InventoryManager(loader=loader,sources=['auto_hosts']) #VariableManager類 variable_manager = VariableManager(loader=loader,inventory=inventory) #Options 執行選項 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) #PlaybookExecutor 執行playbook passwords = dict() playbook = PlaybookExecutor(playbooks=['touch.yml'], # 注意路徑,多個基本直接添加便可 inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords, ) playbook.run()
--- - hosts: 192.168.102.101 remote_user: root vars: touch_file: touch.file tasks: - name: touch file shell: "touch /tmp/{{touch_file}}"
PLAY [192.168.102.101] **************************************************************************************************************************************************** TASK [Gathering Facts] **************************************************************************************************************************************************** ok: [192.168.102.101] TASK [touch file] ********************************************************************************************************************************************************* [WARNING]: Consider using file module with state=touch rather than running touch changed: [192.168.102.101] PLAY RECAP **************************************************************************************************************************************************************** 192.168.102.101 : ok=2 changed=1 unreachable=0 failed=0 # 會在192.168.102.101上生成/tmp/touch.file
經過上面腳本的執行咱們會發現腳本執行結果並非很友善,好比執行任務的時間,執行任務所耗費時間,執行了什麼,特別是工程中咱們將輸出結果發送到前端進行展現以及後端日誌保存,若是隻是簡單地字符串則就不易操做,此時就要使用callback的改寫。
2.5.1 爲何要重寫callback
爲了自定義格式輸出
2.5.2 怎麼改寫callback
1. 經過子類繼承父類(callbackbase)
2. 經過子類改寫父類的部分方法
v2_runner_on_unreachable
v2_runner_on_ok
v2_runner_on_failed
2.5.3 重寫ad-hoc模式的類
# -*- coding: utf-8 -*- # !/usr/bin/env python # 核心類 from collections import namedtuple from ansible.parsing.dataloader import DataLoader from ansible.vars.manager import VariableManager from ansible.inventory.manager import InventoryManager from ansible.playbook.play import Play from ansible.executor.task_queue_manager import TaskQueueManager from ansible.plugins.callback import CallbackBase # InventoryManager類 loader = DataLoader() inventory = InventoryManager(loader=loader, sources=['auto_hosts']) # VariableManager類 variable_manager = VariableManager(loader=loader, inventory=inventory) # Options 執行選項 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 執行對象和模塊 play_source = dict( name="Ansible Play ad-hoc test", # 任務執行的名稱 hosts='192.168.102.101', # 控制着任務執行的目標主機,能夠經過逗號填入多臺主機,或者正則匹配,或者主機組 gather_facts='no', # 執行任務以前去獲取響應主機的相關信息,建議關閉,提升執行效率 tasks=[ # 以dict的方式實現,一個任務一個dict,能夠寫多個,module 爲對應模塊,args爲傳入的參數 dict(action=dict(module='shell', args='touch /tmp/ad_hoc_test1')), # dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}'))) ] ) play = Play().load(play_source, variable_manager=variable_manager, loader=loader) class ModelResultsCollector(CallbackBase): # 繼承父類CallbackBase """ 重寫callbackBase類的部分方法 """ def __init__(self, *args, **kwargs): super(ModelResultsCollector, self).__init__(*args, **kwargs) # 初始化父類方法 self.host_ok = {} self.host_unreachable = {} self.host_failed = {} def v2_runner_on_unreachable(self, result): # result 爲父類中獲取全部執行結果信息的對象 self.host_unreachable[result._host.get_name()] = result def v2_runner_on_ok(self, result): self.host_ok[result._host.get_name()] = result def v2_runner_on_failed(self, result): self.host_failed[result._host.get_name()] = result callback = ModelResultsCollector() passwords = dict() tqm = TaskQueueManager( inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords, # 沒有實際的做用 stdout_callback=callback, ) result = tqm.run(play) print(callback.host_ok.items()) # [(u"192.168.102.101",<ansible.executor.task_result.TaskResult object at 0x10406b790>)] result_raw = {'success': {}, 'failed': {}, 'unreachable': {}} for host, result in callback.host_ok.items(): result_raw['success'][host] = result._result # _result屬性來獲取任務執行的結果 for host, result in callback.host_failed.items(): result_raw['failed'][host] = result._result for host, result in callback.host_unreachable.items(): result_raw['unreachable'][host] = result._result print(result_raw)
{ 'success': { '192.168.102.101': { 'changed': True, 'end': '2019-03-03 21:24:29.426184', 'stdout': '', 'cmd': 'touch /tmp/ad_hoc_test1', 'rc': 0, 'start': '2019-03-03 21:24:29.422987', 'stderr': '', 'delta': '0:00:00.003197', 'invocation': { 'module_args': { 'warn': True, 'executable': None, '_uses_shell': True, '_raw_params': 'touch /tmp/ad_hoc_test1', 'removes': None, 'creates': None, 'chdir': None, 'stdin': None } }, 'warnings': ['Consider using file module with state=touch rather than running touch'], '_ansible_parsed': True, 'stdout_lines': [], 'stderr_lines': [], '_ansible_no_log': False, 'failed': False } }, 'failed': {}, 'unreachable': {} }
2.5.4 重寫playbook模式的類
# -*- coding: utf-8 -*- # !/usr/bin/env python # 核心類 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.playbook.play import Play from ansible.executor.task_queue_manager import TaskQueueManager from ansible.plugins.callback import CallbackBase # InventoryManager類 loader = DataLoader() inventory = InventoryManager(loader=loader, sources=['auto_hosts']) # VariableManager類 variable_manager = VariableManager(loader=loader, inventory=inventory) # Options 執行選項 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) # CallbackBase改寫 class PlayBookResultsCollector(CallbackBase): CALLBACK_VERSION = 2.0 def __init__(self, *args, **kwargs): super(PlayBookResultsCollector, self).__init__(*args, **kwargs) self.task_ok = {} self.task_skipped = {} self.task_failed = {} self.task_status = {} self.task_unreachable = {} 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_unreachable(self, result): self.task_unreachable[result._host.get_name()] = result def v2_runner_on_skipped(self, result): self.task_ok[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['failures'] } callback = PlayBookResultsCollector() # PlaybookExecutor 執行playbook passwords = dict() playbook = PlaybookExecutor(playbooks=['touch.yml'], # 若是有多個劇本則在列表中寫入 inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords, ) playbook._tqm._stdout_callback = callback # 此處調用與ad-hoc模式不一樣 playbook.run() results_raw = {'skipped': {}, 'failed': {}, 'success': {}, "status": {}, 'unreachable': {}, "changed": {}} for host, result in callback.task_ok.items(): results_raw['success'][host] = result._result # _result屬性來獲取任務執行的結果 for host, result in callback.task_failed.items(): results_raw['failed'][host] = result._result for host, result in callback.task_unreachable.items(): results_raw['unreachable'][host] = result._result print(results_raw)
{ 'skipped': {}, 'failed': {}, 'success': { '192.168.102.101': { 'changed': True, 'end': '2019-03-03 21:49:44.851042', 'stdout': '', 'cmd': 'touch /tmp/touch.file', 'rc': 0, 'start': '2019-03-03 21:49:44.848321', 'stderr': '', 'delta': '0:00:00.002721', 'invocation': { 'module_args': { 'warn': True, 'executable': None, '_uses_shell': True, '_raw_params': 'touch /tmp/touch.file', 'removes': None, 'creates': None, 'chdir': None, 'stdin': None } }, 'warnings': ['Consider using file module with state=touch rather than running touch'], '_ansible_parsed': True, 'stdout_lines': [], 'stderr_lines': [], '_ansible_no_log': False, 'failed': False } }, 'status': {}, 'unreachable': {}, 'changed': {} }