前言:

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://rfyiamcool.blog.51cto.com/1030776/1440624

#xiaorui.ccimport os
import time
import sqlite3
import redis
import jsondbname = '/tmp/setup.db'
TIME_FORMAT='%Y-%m-%d %H:%M:%S'try:con = sqlite3.connect(dbname)cur = con.cursor()
except:passdef log(host, data):#    if type(data) == dict:
#        invocation = data.pop('invocation', None)
#        if invocation.get('module_name', None) != 'setup':
#            return
#
#    facts = data.get('ansible_facts', None)
#
#    now = time.strftime(TIME_FORMAT, time.localtime())
#
#    try:
#        # `host` is a unique index
#        cur.execute("REPLACE INTO inventory (now, host, arch, dist, distvers, sys,kernel) VALUES(?,?,?,?,?,?,?);",
#        (
#            now,
#            facts.get('ansible_hostname', None),
#            facts.get('ansible_architecture', None),
#            facts.get('ansible_distribution', None),
#            facts.get('ansible_distribution_version', None),
#            facts.get('ansible_system', None),
#            facts.get('ansible_kernel', None)
#        ))
#        con.commit()
#    except:
#        pass
#
class CallbackModule(object):def runner_on_ok(self, host, 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)def runner_on_failed(self, host, res, ignore_errors=False):f = open('/tmp/11','a')f.write('\nbad\n')f.close()log(host, res)

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

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

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

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

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

#xiaorui.cc
原文:http://rfyiamcool.blog.51cto.com/1030776/1440624 import smtplibdef mail(subject='Ansible error mail', sender='<root>', to='root', cc=None, bcc=None, body=None):if not body:body = subjectsmtp = smtplib.SMTP('localhost')content = 'From: %s\n' % sendercontent += 'To: %s\n' % toif cc:content += 'Cc: %s\n' % cccontent += 'Subject: %s\n\n' % subjectcontent += bodyaddresses = to.split(',')if cc:addresses += cc.split(',')if bcc:addresses += bcc.split(',')for address in addresses:smtp.sendmail(sender, address, content)smtp.quit()class CallbackModule(object):"""This Ansible callback plugin mails errors to interested parties."""def runner_on_failed(self, host, res, ignore_errors=False):if ignore_errors:returnsender = '"Ansible: %s" <root>' % hostsubject = 'Failed: %(module_name)s %(module_args)s' % res['invocation']body = 'The following task failed for host ' + host + ':\n\n%(module_name)s %(module_args)s\n\n' % res['invocation']if 'stdout' in res.keys() and res['stdout']:subject = res['stdout'].strip('\r\n').split('\n')[-1]body += 'with the following output in standard output:\n\n' + res['stdout'] + '\n\n'if 'stderr' in res.keys() and res['stderr']:subject = res['stderr'].strip('\r\n').split('\n')[-1]body += 'with the following output in standard error:\n\n' + res['stderr'] + '\n\n'if 'msg' in res.keys() and res['msg']:subject = res['msg'].strip('\r\n').split('\n')[0]body += 'with the following message:\n\n' + res['msg'] + '\n\n'body += 'A complete dump of the error:\n\n' + str(res)mail(sender=sender, subject=subject, body=body)def runner_on_unreachable(self, host, res):sender = '"Ansible: %s" <root>' % hostif isinstance(res, basestring):subject = 'Unreachable: %s' % res.strip('\r\n').split('\n')[-1]body = 'An error occured for host ' + host + ' with the following message:\n\n' + reselse:subject = 'Unreachable: %s' % res['msg'].strip('\r\n').split('\n')[0]body = 'An error occured for host ' + host + ' with the following message:\n\n' + \res['msg'] + '\n\nA complete dump of the error:\n\n' + str(res)mail(sender=sender, subject=subject, body=body)def runner_on_async_failed(self, host, res, jid):sender = '"Ansible: %s" <root>' % hostif isinstance(res, basestring):subject = 'Async failure: %s' % res.strip('\r\n').split('\n')[-1]body = 'An error occured for host ' + host + ' with the following message:\n\n' + reselse:subject = 'Async failure: %s' % res['msg'].strip('\r\n').split('\n')[0]body = 'An error occured for host ' + host + ' with the following message:\n\n' + \res['msg'] + '\n\nA complete dump of the error:\n\n' + str(res)mail(sender=sender, subject=subject, body=body)

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

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

import os
import time
import jsonTIME_FORMAT="%b %d %Y %H:%M:%S"
MSG_FORMAT="%(now)s - %(category)s - %(data)s\n\n"if not os.path.exists("/var/log/ansible/hosts"):os.makedirs("/var/log/ansible/hosts")def log(host, category, data):if type(data) == dict:if 'verbose_override' in data:# avoid logging extraneous data from factsdata = 'omitted'else:data = data.copy()invocation = data.pop('invocation', None)data = json.dumps(data)if invocation is not None:data = json.dumps(invocation) + " => %s " % datapath = 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()class CallbackModule(object):"""logs playbook results, per host, in /var/log/ansible/hosts"""def on_any(self, *args, **kwargs):passdef runner_on_failed(self, host, res, ignore_errors=False):log(host, 'FAILED', res)def runner_on_ok(self, host, res):log(host, 'OK', res)def runner_on_skipped(self, host, item=None):log(host, 'SKIPPED', '...')def runner_on_unreachable(self, host, res):log(host, 'UNREACHABLE', res)def runner_on_no_hosts(self):passdef runner_on_async_poll(self, host, res, jid, clock):passdef runner_on_async_ok(self, host, res, jid):passdef runner_on_async_failed(self, host, res, jid):log(host, 'ASYNC_FAILED', res)def playbook_on_start(self):passdef playbook_on_notify(self, host, handler):passdef playbook_on_no_hosts_matched(self):passdef playbook_on_no_hosts_remaining(self):passdef playbook_on_task_start(self, name, is_conditional):passdef playbook_on_vars_prompt(self, varname, private=True, prompt=None, encrypt=None, confirm=False, salt_size=None, salt=None, default=None):passdef playbook_on_setup(self):passdef playbook_on_import_for_host(self, host, imported_file):log(host, 'IMPORTED', imported_file)def playbook_on_not_import_for_host(self, host, missing_file):log(host, 'NOTIMPORTED', missing_file)def playbook_on_play_start(self, name):passdef playbook_on_stats(self, stats):pass

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

也可以把结果以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执行的时候

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

class CallbackModule(object):def on_any(self, *args, **kwargs):passdef runner_on_failed(self, host, res, ignore_errors=False):log(host, 'FAILED', res)def runner_on_ok(self, host, res):log(host, 'OK', res)def runner_on_skipped(self, host, item=None):log(host, 'SKIPPED', '...')def runner_on_unreachable(self, host, res):log(host, 'UNREACHABLE', res)def runner_on_no_hosts(self):passdef runner_on_async_poll(self, host, res, jid, clock):passdef runner_on_async_ok(self, host, res, jid):passdef runner_on_async_failed(self, host, res, jid):log(host, 'ASYNC_FAILED', res)def playbook_on_start(self):passdef playbook_on_notify(self, host, handler):passdef playbook_on_no_hosts_matched(self):passdef playbook_on_no_hosts_remaining(self):passdef playbook_on_task_start(self, name, is_conditional):passdef playbook_on_vars_prompt(self, varname, private=True, prompt=None, encrypt=None, confirm=False, salt_size=None, salt=None, default=None):passdef playbook_on_setup(self):passdef playbook_on_import_for_host(self, host, imported_file):log(host, 'IMPORTED', imported_file)def playbook_on_not_import_for_host(self, host, missing_file):log(host, 'NOTIMPORTED', missing_file)def playbook_on_play_start(self, name):passdef playbook_on_stats(self, stats):pass

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

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

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

好了,就这样了 !!!!

ansible调用callbacks插件实现结果nosql输出回调相关推荐

  1. ansible调用callbacks插件 保存执行结果

    cd /usr/share/ansible/plugins/callback ansible1.7.2 ansible2 脚本完全不同,这个要注意 1 2 3 4 5 6 7 8 9 10 11 12 ...

  2. Python调用大漠插件

    Python版本要用32位的?我去官网下载,太慢了,就在腾讯软件里面下载了一个,结果实验成功 import win32com.clientdm = win32com.client.Dispatch(' ...

  3. python调用大漠写辅助_Python调用大漠插件

    Python版本要用32位的?我去官网下载,太慢了,就在腾讯软件里面下载了一个,结果实验成功 import win32com.client dm = win32com.client.Dispatch( ...

  4. Python调用大漠插件(一)

    Python版本要用32位的?我去官网下载,太慢了,就在腾讯软件里面下载了一个,结果实验成功,吼吼. 直接上源码 import win32com.clientdm = win32com.client. ...

  5. java程序员的开发Python游戏自动化脚本(调用大漠插件)系列(二)java?

    前言 既然大家都调用大漠插件,那肯定是有原因的,咱也用.插件确定下来了,接下来就是开发语言了,易语言.C++基本卖外挂的都是这些语言,懂得都懂.python网上资源也很多,java?极其少.不过作为一 ...

  6. 易语言免注册调用大漠插件dm.dll

    实现所谓的免注册,其实还是通过运行命令regsvr32写入到了系统.本视频教程还讲述了在64位WIN7下大漠注册失败的解决方法,更好的免注册调用大漠插件,参考以下文章: 易语言大漠多线程免注册调用大漠 ...

  7. 【Java】-在Java中调用大漠插件

    目录 在Java中调用大漠插件步骤 常见问题 Java与Dll函数的数据通信(一个比较大的坑) 注册了大漠高版本后,如何更换为低版本? Description: 80020010 / 无效的被呼叫方. ...

  8. 【Ansible】Ansible控制windows插件安装及运行error与解决方法

    一. 问:因pip版本问题无法安装kerberos 答:安装提示需要先安装pip升级包 下载pip9.0.1升级包: ![1_2] 二.问:安装kerberos报错 答:需要先安装libkrb5开发包 ...

  9. 最新易语言调用大漠插件制作脚本入门教程

    最新易语言调用大漠插件制作脚本入门教程 这是田野学院的一套零基础视频.学习做辅助脚本入门还是不错的. https://pan.baidu.com/s/1BWd2_kIjL6OLE7q-VcDVlw 提 ...

最新文章

  1. PowerBI随笔(4)-关系模型与报表-1
  2. CCIE学习(7)——VLAN相关命令汇总
  3. 《移动应用开发》作业——JavaScript
  4. wxWidgets:wxFileDialog类用法
  5. 向上造型和向下造型_国标舞So easy?!亲,你怕是凹错造型咯~
  6. java中哈希表怎么表示_java中HashMap概念是什么?怎么存取实现它?
  7. HTTP协议(1)—HTTP的连接
  8. 论文浅尝 | 基于Universal Schema与Memory Network的知识+文本问答
  9. IBM发布32纳米芯片技术 明年下半年量产
  10. 洛谷——P1428 小鱼比可爱
  11. 第八届蓝桥杯省赛真题--最大公共子串
  12. java swing 提示信息,java swing工具提示与不同的消息
  13. 简单好用的应用加密软件:Cisdem AppCrypt Mac版
  14. Excel如何批量导入图片
  15. 【模块】ESP32连接PS4手柄
  16. 肇事逃逸人会受到什么处罚
  17. 电子护照阅读器便捷通行管理系统
  18. 翁恺java考试卷_翁恺java期末考试题
  19. JUnit测试提示java.lang.Exception: No runnable methods
  20. 美团、饿了么“喜极而泣”,搞定了!外卖骑手终于可以愉快的送餐了

热门文章

  1. vorwerk 机器人_福维克(Vorwerk)--吸尘器行业的quot;安利quot;
  2. java当前月份减一个月_在java编程中怎样用%表示当前月份的上一个月和下一个月...
  3. C#教程01:关于C#
  4. oracle var/tmp,关于/var/tmp/.oracle 目录(ZT)
  5. html load方法的区别,jQuery  中的.load()、$get()、$,post()用法和区别
  6. apache 编译安装php mysql_编译安装APACHE+PHP+MYSQL
  7. java equal 不等于_java Integer判断相等只能使用equals(不能使用==)
  8. 数据结构实验之串二:字符串匹配
  9. 机器学习系列(1)_逻辑回归初步
  10. 从零开始玩转JMX(一)——简介和Standard MBean