日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

【Ansible】的python api

發布時間:2025/4/5 python 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Ansible】的python api 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【Ansible API】

  Ansible本身就是由python寫成,所有其對python形式的API的支持應該不錯。

  其API分不同的版本,這個版本也就是ansible本身的版本,可以通過ansible --version命令查看或者在python中import ansible然后查看anisble.__version__。

  在2.0的版本以前,ansible的API十分簡單。通過大概十幾行代碼就可以模擬通過ad-hoc的方式運行annsible命令的。

  但是在2.0及以后的版本,難度突然陡增,與此同時更多的更加底層的東西被開放給一般開發,雖然復雜了,但是也更加靈活了。

  對于一些簡單的需求,可能我們還是喜歡老版API,因此這里有個網上別人封裝好的2.0版本API簡化文件,通過這里的代碼我們可以依然簡單地運行ansible的ad-hoc。同時,它的源碼支持修改,從而達到更個性化的改造。

  *** 需要注意,下面這個代碼只在2.0開頭的幾個版本中適用。至少到2.4.0之后,API又有了一些改動,下面的代碼運行會出錯。我懶得再研究2.4了,就干脆pip install ansible==2.0來配合這個庫

  ansible_api.py:

# -*- coding:utf-8 -*-import os import sys from collections import namedtuple from ansible.parsing.dataloader import DataLoader from ansible.vars import VariableManager from ansible.inventory import Inventory from ansible.inventory.group import Group from ansible.inventory.host import Host from ansible.playbook.play import Play from ansible.executor.task_queue_manager import TaskQueueManager from ansible.executor.playbook_executor import PlaybookExecutor from ansible.plugins.callback import CallbackBaseclass ResultsCollector(CallbackBase):def __init__(self, *args, **kwargs):super(ResultsCollector, 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()] = resultdef v2_runner_on_ok(self, result, *args, **kwargs):self.host_ok[result._host.get_name()] = resultdef v2_runner_on_failed(self, result, *args, **kwargs):self.host_failed[result._host.get_name()] = resultclass MyInventory(Inventory):""" this is my ansible inventory object. """def __init__(self, resource, loader, variable_manager):""" resource的數據格式是一個列表字典,比如 { "group1": { "hosts": [{"hostname": "10.0.0.0", "port": "22", "username": "test", "password": "pass"}, ...], "vars": {"var1": value1, "var2": value2, ...} } } 如果你只傳入1個列表,這默認該列表內的所有主機屬于my_group組,比如 [{"hostname": "10.0.0.0", "port": "22", "username": "test", "password": "pass"}, ...] """self.resource = resourceself.inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=[])self.gen_inventory()def my_add_group(self, hosts, groupname, groupvars=None):""" add hosts to a group """my_group = Group(name=groupname)# if group variables exists, add them to groupif groupvars:for key, value in groupvars.iteritems():my_group.set_variable(key, value)# add hosts to groupfor host in hosts:# set connection variableshostname = host.get("hostname")hostip = host.get('ip', hostname)hostport = host.get("port")username = host.get("username")password = host.get("password")ssh_key = host.get("ssh_key")my_host = Host(name=hostname, port=hostport)my_host.set_variable('ansible_ssh_host', hostip)my_host.set_variable('ansible_ssh_port', hostport)my_host.set_variable('ansible_ssh_user', username)my_host.set_variable('ansible_ssh_pass', password)my_host.set_variable('ansible_ssh_private_key_file', ssh_key)# set other variablesfor key, value in host.iteritems():if key not in ["hostname", "port", "username", "password"]:my_host.set_variable(key, value)# add to group my_group.add_host(my_host)self.inventory.add_group(my_group)def gen_inventory(self):""" add hosts to inventory. """if isinstance(self.resource, list):self.my_add_group(self.resource, 'default_group')elif isinstance(self.resource, dict):for groupname, hosts_and_vars in self.resource.iteritems():self.my_add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))class AnsibleAPI(object):""" This is a General object for parallel execute modules. """def __init__(self, resource, *args, **kwargs):self.resource = resourceself.inventory = Noneself.variable_manager = Noneself.loader = Noneself.options = Noneself.passwords = Noneself.callback = Noneself.__initializeData()self.results_raw = {}def __initializeData(self):""" 初始化ansible """Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'timeout', 'remote_user','ask_pass', 'private_key_file', 'ssh_common_args', 'ssh_extra_args','sftp_extra_args','scp_extra_args', 'become', 'become_method', 'become_user', 'ask_value_pass','verbosity','check', 'listhosts', 'listtasks', 'listtags', 'syntax'])# initialize needed objectsself.variable_manager = VariableManager()self.loader = DataLoader()self.options = Options(connection='smart', module_path='/usr/share/ansible', forks=100, timeout=10,remote_user='root', ask_pass=False, private_key_file=None, ssh_common_args=None,ssh_extra_args=None,sftp_extra_args=None, scp_extra_args=None, become=None, become_method=None,become_user='root', ask_value_pass=False, verbosity=None, check=False, listhosts=False,listtasks=False, listtags=False, syntax=False)self.passwords = dict(sshpass=None, becomepass=None)self.inventory = MyInventory(self.resource, self.loader, self.variable_manager).inventoryself.variable_manager.set_inventory(self.inventory)def run(self, host_list, module_name, module_args):""" run module from andible ad-hoc. module_name: ansible module_name module_args: ansible module args """# create play with tasksplay_source = dict(name="Ansible Play",hosts=host_list,gather_facts='no',tasks=[dict(action=dict(module=module_name, args=module_args))])play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader)# actually run ittqm = Noneself.callback = ResultsCollector()try:tqm = TaskQueueManager(inventory=self.inventory,variable_manager=self.variable_manager,loader=self.loader,options=self.options,passwords=self.passwords,)tqm._stdout_callback = self.callbacktqm.run(play)finally:if tqm is not None:tqm.cleanup()def run_playbook(self, host_list, role_name, role_uuid, temp_param):""" run ansible palybook """try:self.callback = ResultsCollector()filenames = ['' + '/handlers/ansible/v1_0/sudoers.yml'] # playbook的路徑template_file = '' # 模板文件的路徑if not os.path.exists(template_file):sys.exit()extra_vars = {} # 額外的參數 sudoers.yml以及模板中的參數,它對應ansible-playbook test.yml --extra-vars "host='aa' name='cc' "host_list_str = ','.join([item for item in host_list])extra_vars['host_list'] = host_list_strextra_vars['username'] = role_nameextra_vars['template_dir'] = template_fileextra_vars['command_list'] = temp_param.get('cmdList')extra_vars['role_uuid'] = 'role-%s' % role_uuidself.variable_manager.extra_vars = extra_vars# actually run itexecutor = PlaybookExecutor(playbooks=filenames, inventory=self.inventory, variable_manager=self.variable_manager,loader=self.loader,options=self.options, passwords=self.passwords,)executor._tqm._stdout_callback = self.callbackexecutor.run()except Exception as e:print "error:",e.messagedef get_result(self):self.results_raw = {'success': {}, 'failed': {}, 'unreachable': {}}for host, result in self.callback.host_ok.items():self.results_raw['success'][host] = result._resultfor host, result in self.callback.host_failed.items():self.results_raw['failed'][host] = result._result.get('msg') or result._resultfor host, result in self.callback.host_unreachable.items():self.results_raw['unreachable'][host] = result._result['msg']return self.results_raw

?

  簡單的用法是這樣的:

# -*- coding:utf-8 -*-from ansible_api import AnsibleAPIresource = [{'hostname':'localtest','ip','192.168.178.59','username':'root','password':'xxx'},{'hostname':'localtest2','ip':'192.168.178.141','username':'root','password':'yyy'} #有個小坑,hostname中不能有空格,否則這個host會被ansible無視 ]api = AnsibleAPI(resource)# 開始模擬以ad-hoc方式運行ansible命令 api.run(['localtest','localtest2'], # 指出本次運行涉及的主機,在resource中定義'command', # 本次運行使用的模塊'hostname' # 模塊的參數 )# 獲取結果,是一個字典格式,如果是print可以用json模塊美化一下 import json print json.dumps(api.get_result(),indent=4)

?

  從邏輯上看,首先我們聲明了一個resource,在這是一個list結構,其中包含了各個被操作主機的信息。hostname,ip,username,password這些是作為ansible連接所用的最基本的幾個參數,此外port也可指定。resource被api類加載,這個過程其實就是生成了一個動態的inventory。從源碼中的90多行可以看出,當傳入一個list時api默認將其中所有host信息都放入一個default_group的inventory組,當傳入一個dict就默認這個dict的各個鍵值對分別是組名和組中host信息。

  run方法是真正的執行方法,其參數從前往后三個分別是host_list, module, module_args。command的話args比較簡單。像類似于copy這類模塊的參數可以這么寫:

  api.run(['test'],'copy','src="/tmp/testfille" dest="/tmp/newfile"')

  而file就可以這樣:

  api.run(['test'],'path="/tmp/test.py" mode=0755 owner="tmpuser"')

  通過這兩個例子基本就可以看清楚如何向run方法傳遞ansible模塊的參數了。

  api在執行run方法之后并不會主動輸出結果,需要我們手動地get_result()。result在空的情況下是這樣一個結構:

{"success": {},"failed": {},"unreachable":{} }

?

  不難看出,從主機層面上,主機們被分成了執行成功,執行失敗,和連接不到三類,分別給出結果。

  下面給出一個返回結果的示例

{"failed": {"node-one": {"cmd": ["cat", "/tmp/test"], "end": "2018-05-08 16:27:29.327685", "_ansible_no_log": false, "stdout": "", "changed": true, "failed": true, "delta": "0:00:00.003369", "stderr": "cat: /tmp/test: \u6ca1\u6709\u90a3\u4e2a\u6587\u4ef6\u6216\u76ee\u5f55", "rc": 1, "invocation": {"module_name": "command", "module_args": {"creates": null, "executable": null, "chdir": null, "_raw_params": "cat /tmp/test", "removes": null, "warn": true, "_uses_shell": false}}, "stdout_lines": [], "start": "2018-05-08 16:27:29.324316", "warnings": []}}, "success": {"localtest": {"cmd": ["cat", "/tmp/test"], "end": "2018-05-08 16:27:30.692616", "_ansible_no_log": false, "stdout": "", "changed": true, "start": "2018-05-08 16:27:30.689329", "delta": "0:00:00.003287", "stderr": "", "rc": 0, "invocation": {"module_name": "command", "module_args": {"creates": null, "executable": null, "chdir": null, "_raw_params": "cat /tmp/test", "removes": null, "warn": true, "_uses_shell": false}}, "stdout_lines": [], "warnings": []}}, "unreachable": {"node-two": "ERROR! SSH encountered an unknown error during the connection. We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue"} } View Code

?

  localtest執行成功,返回中有changed,delta,start/end,stdout等可能要在后續處理中用到的各種數據

  node-one執行失敗,所以可以讀取stderr中的內容。由于返回是中文,在這里以unicode的形式展現

  node-two無法連接,只給出了簡單的無法連接的提示信息

?

  基本使用就說到這里吧。下面我要使用了,過程中可能會要回過頭來改源碼。

總結

以上是生活随笔為你收集整理的【Ansible】的python api的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。