ansible调用callbacks插件实现结果nosql输出回调

前端之家收集整理的这篇文章主要介绍了ansible调用callbacks插件实现结果nosql输出回调前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

前言:

ansible的结果默认是输出到cli终端和日志里面的,用惯了saltsatck的returners数据回调后,也很是喜欢ansible也有,一开始不知道有这个功能,自己也简单实现了这样的功能


我的实现方式是,在模块里面做一些输出的逻辑。当使用ansible runner api的时候,是在后面runner代码,最后加了一段往redis输出的逻辑。 这里实现数据的输出有些独特,但是只能是在模块和 api方面搞 。 如果是用playbook的话,按照我以前的思路的话,再继续改ansbile的源码。 这两天听沈灿说,ansible有个callback_plugins的功能,可以对于执行的状态做一些判断,比如,执行成功,执行失败,异步执行,异步执行失败,playbook开始,结束等等。

沈灿这货先写了关于ansible callbacks的文章,我看到了后,才知道有而一个东西。大家可以看看 。

http://www.shencan.net/index.php/2014/07/17/ansible-%E6%8F%92%E4%BB%B6%E4%B9%8Bcallback_plugins-%EF%BC%88%E5%AE%9E%E6%88%98%EF%BC%89/



我也不说复杂了,就简单说一个例子,把执行的结果,都推到redis里面,也可以暂存到sqlite数据库里面,只是这段代码我给屏蔽了,有兴趣的朋友再搞搞。对于redis里面的数据可以写一个页面展现下,专门记录错误的问题,成功的就pass掉。


原文:http://www.jb51.cc/article/p-yqfmjlfe-ng.html


#xiaorui.cc

importos
importtime
importsqlite3
importredis
importjson

dbname='/tmp/setup.db'
TIME_FORMAT='%Y-%m-%d%H:%M:%S'

try:
con=sqlite3.connect(dbname)
cur=con.cursor()
except:
pass

deflog(host,data):

#iftype(data)==dict:
#invocation=data.pop('invocation',None)
#ifinvocation.get('module_name',None)!='setup':
#return
#
#facts=data.get('ansible_facts',None)
#
#now=time.strftime(TIME_FORMAT,time.localtime())
#
#try:
##`host`isauniqueindex
#cur.execute("REPLACEINTOinventory(now,host,arch,dist,distvers,sys,kernel)VALUES(?,?,?);",#(
#now,#facts.get('ansible_hostname',None),#facts.get('ansible_architecture',#facts.get('ansible_distribution',#facts.get('ansible_distribution_version',#facts.get('ansible_system',#facts.get('ansible_kernel',None)
#))
#con.commit()
#except:
#pass
#
classCallbackModule(object):
defrunner_on_ok(self,res):
r=redis.Redis(host='127.0.0.1',port=6379,db=0)
r.set(host,str(res))

f=open('/tmp/11','a')
f.write(str(host))
f.write(str(res))
f.close()
log(host,res)
defrunner_on_Failed(self,res,ignore_errors=False):
f=open('/tmp/11','a')
f.write('\nbad\n')
f.close()
log(host,res)



wKiom1PLxF7RgYIpAANcxv3ltOA830.jpg

还是可以接收所有的facts数据的。

原文:http://www.jb51.cc/article/p-yqfmjlfe-ng.html


wKiom1PLz6jT6hSxAAvukgGOdaA867.jpg

原文:http://www.jb51.cc/article/p-yqfmjlfe-ng.html


虽然我上面的例子用了redis,sqlite数据库,其实我个人推荐用mongodb这样的文档数据库的。因为ansible主runner函数,给callbacks传递了一个叫res的变量,他本身就是一个dict对象,如果放到redis的hash,sqlite的各种字段,够你烦的了,如果直接mongo,那就简单了,直接insert ! 欧了


wKiom1PL2CqjPJdLAAi3W-Hd6Xs379.jpg


这里在show一个邮件的callbacks代码,场景是,非常消耗时间的任务,当执行完成后,查看结果咋办?  但是你也可以在终端继续看,既然咱们讲了callbacks_plugins,就可以把结果push到你的邮箱里面,当然只给你发错误的,有问题的。 下面的callback代码需要自己替换成自己用的邮箱、密码、smtp服务器。


#xiaorui.cc
原文:http://rfyiamcool.blog.51cto.com/1030776/1440624

importsmtplib

defmail(subject='Ansibleerrormail',sender='<root>',to='root',cc=None,bcc=None,body=None):
ifnotbody:
body=subject

smtp=smtplib.SMTP('localhost')

content='From:%s\n'%sender
content+='To:%s\n'%to
ifcc:
content+='Cc:%s\n'%cc
content+='Subject:%s\n\n'%subject
content+=body

addresses=to.split(',')
ifcc:
addresses+=cc.split(',')
ifbcc:
addresses+=bcc.split(',')

foraddressinaddresses:
smtp.sendmail(sender,address,content)

smtp.quit()


classCallbackModule(object):

"""
ThisAnsiblecallbackpluginmailserrorstointerestedparties.
"""

defrunner_on_Failed(self,ignore_errors=False):
ifignore_errors:
return
sender='"Ansible:%s"<root>'%host
subject='Failed:%(module_name)s%(module_args)s'%res['invocation']
body='ThefollowingtaskFailedforhost'+host+':\n\n%(module_name)s%(module_args)s\n\n'%res['invocation']
if'stdout'inres.keys()andres['stdout']:
subject=res['stdout'].strip('\r\n').split('\n')[-1]
body+='withthefollowingoutputinstandardoutput:\n\n'+res['stdout']+'\n\n'
if'stderr'inres.keys()andres['stderr']:
subject=res['stderr'].strip('\r\n').split('\n')[-1]
body+='withthefollowingoutputinstandarderror:\n\n'+res['stderr']+'\n\n'
if'msg'inres.keys()andres['msg']:
subject=res['msg'].strip('\r\n').split('\n')[0]
body+='withthefollowingmessage:\n\n'+res['msg']+'\n\n'
body+='Acompletedumpoftheerror:\n\n'+str(res)
mail(sender=sender,subject=subject,body=body)

defrunner_on_unreachable(self,res):
sender='"Ansible:%s"<root>'%host
ifisinstance(res,basestring):
subject='Unreachable:%s'%res.strip('\r\n').split('\n')[-1]
body='Anerroroccuredforhost'+host+'withthefollowingmessage:\n\n'+res
else:
subject='Unreachable:%s'%res['msg'].strip('\r\n').split('\n')[0]
body='Anerroroccuredforhost'+host+'withthefollowingmessage:\n\n'+\
res['msg']+'\n\nAcompletedumpoftheerror:\n\n'+str(res)
mail(sender=sender,body=body)

defrunner_on_async_Failed(self,jid):
sender='"Ansible:%s"<root>'%host
ifisinstance(res,basestring):
subject='Asyncfailure:%s'%res.strip('\r\n').split('\n')[-1]
body='Anerroroccuredforhost'+host+'withthefollowingmessage:\n\n'+res
else:
subject='Asyncfailure:%s'%res['msg'].strip('\r\n').split('\n')[0]
body='Anerroroccuredforhost'+host+'withthefollowingmessage:\n\n'+\
res['msg']+'\n\nAcompletedumpoftheerror:\n\n'+str(res)
mail(sender=sender,body=body)

如果不想发邮件,又不想搞到数据库里面,怎么办? 那来点低端的。  直接写入到文件里面。

官方给出一个例子,大家照着模板写就行了。


importos
importtime
importjson

TIME_FORMAT="%b%d%Y%H:%M:%S"
MSG_FORMAT="%(now)s-%(category)s-%(data)s\n\n"

ifnotos.path.exists("/var/log/ansible/hosts"):
os.makedirs("/var/log/ansible/hosts")

deflog(host,category,data):
iftype(data)==dict:
if'verbose_override'indata:
#avoidloggingextraneousdatafromfacts
data='omitted'
else:
data=data.copy()
invocation=data.pop('invocation',None)
data=json.dumps(data)
ifinvocationisnotNone:
data=json.dumps(invocation)+"=>%s"%data

path=os.path.join("/var/log/ansible/hosts",host)
now=time.strftime(TIME_FORMAT,time.localtime())
fd=open(path,"a")
fd.write(MSG_FORMAT%dict(now=now,category=category,data=data))
fd.close()

classCallbackModule(object):
"""
logsplaybookresults,perhost,in/var/log/ansible/hosts
"""

defon_any(self,*args,**kwargs):
pass

defrunner_on_Failed(self,ignore_errors=False):
log(host,'Failed',res)

defrunner_on_ok(self,res):
log(host,'OK',res)

defrunner_on_skipped(self,item=None):
log(host,'SKIPPED','...')

defrunner_on_unreachable(self,'UNREACHABLE',res)

defrunner_on_no_hosts(self):
pass

defrunner_on_async_poll(self,jid,clock):
pass

defrunner_on_async_ok(self,jid):
pass

defrunner_on_async_Failed(self,jid):
log(host,'ASYNC_Failed',res)

defplaybook_on_start(self):
pass

defplaybook_on_notify(self,handler):
pass

defplaybook_on_no_hosts_matched(self):
pass

defplaybook_on_no_hosts_remaining(self):
pass

defplaybook_on_task_start(self,name,is_conditional):
pass

defplaybook_on_vars_prompt(self,varname,private=True,prompt=None,encrypt=None,confirm=False,salt_size=None,salt=None,default=None):
pass

defplaybook_on_setup(self):
pass

defplaybook_on_import_for_host(self,imported_file):
log(host,'IMPORTED',imported_file)

defplaybook_on_not_import_for_host(self,missing_file):
log(host,'NOTIMPORTED',missing_file)

defplaybook_on_play_start(self,name):
pass

defplaybook_on_stats(self,stats):
pass

wKioL1PLzZbDY29sAAWL-68tvIQ014.jpg


也可以把结果以webhooks钩子的方式,做些你想做的东西。


callbacks的各种状态还是很多的,每个函数的字眼还是很好理解的。

比如:

on_any 哪都有他 !任何的状态他触发。

runner_on_Failed 失败

runner_on_ok 成功

runner_on_unreachable 网络不可达

runner_on_no_hosts 没有主机

runner_on_async_poll 任务的异步执行

playbook_on_start playbook执行的时候

等等。。。。 自己尝试吧 !


classCallbackModule(object):


defon_any(self,'Microsoft YaHei';">

咱们可以简单看看ansible的callbacks源码。

规定了两个类,一个是供应ansible-playbook用的,还有一个是供应ansible,也就是cli。 根据各种的情况,调用不同的函数,首先会打到终端,再log日志,最后是自定义的callbacks的插件




好了,就这样了 !!!!

猜你在找的NoSQL相关文章