Ansible 2.0+版本api使用方法
Posted python运维技术
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ansible 2.0+版本api使用方法相关的知识,希望对你有一定的参考价值。
Ansible这个工具在现在运维中用的越来越多,它可以方便的批量执行命令,上传文件,配置playbook初始化一些新机器非常快速方便,当然除了我们命令行使用外,我们还可以通过ansible提供的api接口编写一些自动化脚本工作,用过ansible 的api的小伙伴可能知道在2.0版本之前,调用ansible的api是一件非常简单容易的事,几行代码就可以搞定,而且还非常直观,但到了2.0版本后会发现调用没那么容易了,如果没有python基础,是没法玩了,有基础的也会感觉很麻烦,因为在2.0版本一些数据处理是要自己来写的,不像2.0版本之前,基本都是ansible给实现了,不过别急,今天我们就把跟2.0版本的api调用逐一看一遍,先来一个简单的调用:
#!/usr/bin/env python
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.executor.playbook_executor import PlaybookExecutor
variable_manager = VariableManager()
loader = DataLoader()
inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list='/etc/ansible/hosts')
playbook_path = '/tmp/onedir/main.yml'
if not os.path.exists(playbook_path):
print '[INFO] The playbook does not exist'
sys.exit()
Options = namedtuple('Options', ['listtags', 'listtasks', 'listhosts', 'syntax', 'connection','module_path', 'forks', 'remote_user', 'p
rivate_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', '
verbosity', 'check'])
options = Options(listtags=False, listtasks=False, listhosts=False, syntax=False, connection='ssh', module_path=None, forks=100, remote
_user='slotlocker', private_key_file=None, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become
=True, become_method=None, become_user='root', verbosity=None, check=False)
variable_manager.extra_vars = {'hosts': 'port'}
passwords = {}
pbex = PlaybookExecutor(playbooks=[playbook_path], inventory=inventory, variable_manager=variable_manager, loader=loader, options=optio
ns, passwords=passwords)
results = pbex.run()
这是最简单的方法,也没定义自己回调函数,就是让大家看看调用api的时候都需要哪些初始化参数,它运行的结果跟用ansible-playbook 命令执行的结果显示是一样的。
当然这种方式我们用的时候还不太方便,我们有时候期望运行完的结果返回的是json格式数据,方便我们做进一步处理,我们来看下一个实现了自己回调函数的例子,例子参考了网络上的一个例子,自己做了微调,不过大部分例子实现方式都差不多,都时候自己定义回调类,自己然后定义一个任务类,然后开始执行,我们先看第一个回调类,回调类继承CallbackBase父类,如下:
import os
import json
from collections import namedtuple
from ansible.inventory import Inventory
from ansible.vars import VariableManager
from ansible.parsing.dataloader import DataLoader
from ansible.executor.playbook_executor import PlaybookExecutor
from ansible.plugins.callback import CallbackBase
from ansible.errors import AnsibleParserError
class mycallback(CallbackBase):
def __init__(self,*args):
super(mycallback,self).__init__(display=None)
self.status_ok=json.dumps({})
self.status_fail=json.dumps({})
self.status_unreachable=json.dumps({})
self.status_playbook=''
self.status_no_hosts=False
self.host_ok = {}
self.host_failed={}
self.host_unreachable={}
def v2_runner_on_ok(self,result):
host=result._host.get_name()
self.runner_on_ok(host, result._result)
self.host_ok[host] = result
def v2_runner_on_failed(self, result, ignore_errors=False):
host = result._host.get_name()
self.runner_on_failed(host, result._result, ignore_errors)
self.host_failed[host] = result
def v2_runner_on_unreachable(self, result):
host = result._host.get_name()
self.runner_on_unreachable(host, result._result)
self.host_unreachable[host] = result
def v2_playbook_on_no_hosts_matched(self):
self.playbook_on_no_hosts_matched()
self.status_no_hosts=True
def v2_playbook_on_play_start(self, play):
self.playbook_on_play_start(play.name)
self.playbook_path=play.name
任务类:
class my_ansible_play():
def __init__(self, playbook, extra_vars={},
host_list='/etc/ansible/hosts',
connection='ssh',
become=False,
become_user=None,
module_path=None,
fork=50,
passwords={},
check=False):
self.playbook_path=playbook
self.passwords=passwords
self.extra_vars=extra_vars
Options = namedtuple('Options',
['listtags', 'listtasks', 'listhosts', 'syntax', 'connection','module_path',
'forks', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args',
'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check'])
self.options = Options(listtags=False, listtasks=False,
listhosts=False, syntax=False,
connection=connection, module_path=module_path,
forks=fork, private_key_file=None,
ssh_common_args=None, ssh_extra_args=None,
sftp_extra_args=None, scp_extra_args=None,
become=become, become_method=None,
become_user=become_user,
verbosity=None, check=check)
if ansible_cfg != None:
os.environ["ANSIBLE_CONFIG"] = ansible_cfg
self.variable_manager=VariableManager()
self.loader=DataLoader()
self.inventory=Inventory(loader=self.loader,variable_manager=self.variable_manager,host_list=host_list)
def run(self):
complex_msg={}
if not os.path.exists(self.playbook_path):
code=1000
results={'playbook':self.playbook_path,'msg':self.playbook_path+' playbook is not exist','flag':False}
pbex= PlaybookExecutor(playbooks=[self.playbook_path],
inventory=self.inventory,
variable_manager=self.variable_manager,
loader=self.loader,
options=self.options,
passwords=self.passwords)
self.results_callback=mycallback()
print dir(pbex._tqm)
pbex._tqm._stdout_callback=self.results_callback
try:
code=pbex.run()
except AnsibleParserError:
code=1001
results={'playbook':self.playbook_path,'msg':self.playbook_path+' playbook have syntax error','flag':False}
return code,results
if self.results_callback.status_no_hosts:
code=1002
results={'playbook':self.playbook_path,'msg':self.results_callback.status_no_hosts,'flag':False,'executed':False}
return code,results
def get_result(self):
self.result_all={'success':{},'fail':{},'unreachable':{}}
for host, result in self.results_callback.host_ok.items():
self.result_all['success'][host] = result._result
for host, result in self.results_callback.host_failed.items():
self.result_all['failed'][host] = result._result['msg']
for host, result in self.results_callback.host_unreachable.items():
self.result_all['unreachable'][host]= result._result['msg']
for i in self.result_all['success'].keys():
return self.result_all
主函数执行:
if __name__ =='__main__':
play_book=my_ansible_play('/tmp/onedir/main.yml')
play_book.run()
data = play_book.get_result()
print data
这里说一下PlaybookExecutor初始化的几个参数:
inventory –> 由ansible.inventory模块创建,用于导入inventory文件
variable_manager –> 由ansible.vars模块创建,用于存储各类变量信息
loader –> 由ansible.parsing.dataloader模块创建,用于数据解析
options –> 存放各类配置信息的数据字典
passwords –> 登录密码,可设置加密信息
stdout_callback –> 回调函数
写在最后,因为ansible要求返回的数据是Json格式,所以如果你想自定义一些模块,我建议最好用python去实现比较方便,如果一定要用shell,需要在shell脚本里 加上#WANT_JSON, 然后返回构造的json格式数据,例如:
{
"changed": true,
"msg": "OK",
}
以上是关于Ansible 2.0+版本api使用方法的主要内容,如果未能解决你的问题,请参考以下文章