Developing Plugins
插件是增强ansible核心功能的代码片段,我们可以很方便的使用插件,编写插件代码。如果我们想要对ansible的执行结果进行分析,根据返回结果发送邮件,写入日志等都可以通过插件实现。
插件列表
- Action plugins are front ends to modules and can execute actions on the controller before calling the modules themselves.(操作插件,调用模块之前执行操作)
- Cache plugins are used to keep a cache of ‘facts’ to avoid costly fact-gathering operations.(缓存插件,缓存主机facts变量)
- Callback plugins enable you to hook into Ansible events for display or logging purposes.(回调插件,对事件进行显示和记录,这个常用)
- Connection plugins define how to communicate with inventory hosts.(连接插件,定义如何与节点主机通信)
- Filters plugins allow you to manipulate data inside Ansible plays and/or templates. This is a Jinja2 feature; Ansible ships extra filter plugins.(过滤插件,Jinja2功能)
- Lookup plugins are used to pull data from an external source. These are implemented using a custom Jinja2 function.(查找插件用于从外部源提取数据)
- Strategy plugins control the flow of a play and execution logic.(策略插件)
- Shell plugins deal with low-level commands and formatting for the different shells Ansible can encounter on remote hosts.(shell插件处理低级别命令和格式化)
- Test plugins allow you to validate data inside Ansible plays and/or templates. This is a Jinja2 feature; Ansible ships extra test plugins.(测试插件)
- Vars plugins inject additional variable data into Ansible runs that did not come from an inventory, playbook, or the command line.(Vars插件)
Callback plugins
在日常开发中使用回调插件比较多一点,通过callback插件,可以实现回调功能,里面定义了若干场景,如主机不可达,执行任务失败,执行任务成功等,分别对应不同的方法,这样就可以实现在不同的场景触发不同的操作。
设置回调功能参数
该功能ansible默认是关闭的
$ cat /etc/ansible/ansible.cfg
...
bin_ansible_callbacks = True #加载功能
# set plugin path directories here, separate with colons 定义插件位置
action_plugins = /usr/share/ansible_plugins/action_plugins
callback_plugins = /usr/share/ansible_plugins/callback_plugins
connection_plugins = /usr/share/ansible_plugins/connection_plugins
lookup_plugins = /usr/share/ansible_plugins/lookup_plugins
vars_plugins = /usr/share/ansible_plugins/vars_plugins
filter_plugins = /usr/share/ansible_plugins/filter_plugins
...
编写回调脚本
编写回调脚本放到配置文件中定义的目录中,并赋予可执行权限。我们可以将执行结果写入本地文件、数据库或发邮件等等。在日常开发中我们会将结果写入日志或跟踪记录执行的进度和异常。
写入本地文件
# -*- coding:utf-8 -*-
#!/usr/bin/env python
import json
result_file = '/tmp/result'
class CallbackModule(object):
def runner_on_ok(self, host, res):
with open(result_file,'a') as f:
f.write('success\n')
f.write(str(host))
f.write(json.dumps(res, sort_keys=True, indent=4, separators=(',', ': ')))
f.write('\n')
def runner_on_failed(self, host, res, ignore_errors=False):
with open(result_file, 'a') as f:
f.write('failed\n')
f.write(str(host))
f.write(json.dumps(res, sort_keys=True, indent=4, separators=(',', ': ')))
f.write('\n')
def runner_on_unreachable(self,host,res):
with open(result_file, 'a') as f:
f.write('unreachable\n')
f.write(str(host))
f.write(json.dumps(res, sort_keys=True, indent=4, separators=(',', ': ')))
f.write('\n')
测试
$ ansible-playbook -i hosts test.yml
PLAY [default_group] **********************************************************
TASK: [test | cp test auto install script] ************************************
ok: [172.31.30.178]
TASK: [test | install test] ***************************************************
changed: [172.31.30.178]
PLAY RECAP ********************************************************************
172.31.30.178 : ok=2 changed=1 unreachable=0 failed=0
#制造一个unreachable错误
$ ansible-playbook -i hosts test.yml
PLAY [default_group] **********************************************************
TASK: [test | cp test auto install script] ************************************
fatal: [172.31.30.178] => 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
FATAL: all hosts have already failed -- aborting
PLAY RECAP ********************************************************************
to retry, use: --limit @/root/startoftwares.retry
172.31.30.178 : ok=0 changed=0 unreachable=1 failed=0
#查看结果
$ cat /tmp/result
success
172.31.30.178{
"changed": false,
"dest": "/tmp/test.sh",
"gid": 1000,
"group": "ubuntu",
"invocation": {
"module_args": "src=test.sh dest=/tmp/test.sh owner=ubuntu group=ubuntu mode=0755",
"module_name": "copy"
},
"md5sum": "da1bd2e811a9909b96b09c3988deaec6",
"mode": "0755",
"owner": "ubuntu",
"path": "/tmp/test.sh",
"size": 58,
"state": "file",
"uid": 1000
}
success
172.31.30.178{
"changed": true,
"cmd": "bash /tmp/test.sh",
"delta": "0:00:03.004104",
"end": "2017-04-11 10:48:20.429600",
"invocation": {
"module_args": "bash /tmp/test.sh",
"module_name": "shell"
},
"rc": 0,
"start": "2017-04-11 10:48:17.425496",
"stderr": "",
"stdout": ""
}
unreachable
172.31.30.178"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"
发邮件
# -*- coding:utf-8 -*-
#!/usr/bin/env python
import smtplib
from email.mime.text import MIMEText
mail_host="smtp.xxx.com"
mail_user="xxxxx@xxx.com"
mail_pass="xxxxxxx"
user_to = "xxxxx@xxx.com"
def send_mail(context):
msg = MIMEText(context, 'plain', 'utf-8')
msg['From'] = mail_user
msg['To'] = user_to
msg['Subject'] = 'Ansible error mail'
server = smtplib.SMTP(mail_host, 25)
server.login(mail_user, mail_pass)
server.sendmail(mail_user, user_to, msg.as_string())
server.quit()
class CallbackModule(object):
def runner_on_ok(self, host, res):
pass
def runner_on_failed(self, host, res, ignore_errors=False):
pass
def runner_on_unreachable(self,host,res):
if isinstance(res,basestring):
context = 'An error occured for host ' + host + ' with the following message:\n\n' + res
else:
context = 'An error occured for host' + host + ' with the following message:\n\n' + str(res)
send_mail(context)
测试
$ ansible-playbook -i hosts test.yml
PLAY [default_group] **********************************************************
TASK: [test | cp test auto install script] ************************************
fatal: [172.31.30.178] => 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
FATAL: all hosts have already failed -- aborting
PLAY RECAP ********************************************************************
to retry, use: --limit @/root/startoftwares.retry
172.31.30.178 : ok=0 changed=0 unreachable=1 failed=0
查收邮件
以上脚本都写的比较简单,建议参考:官方插件代码样例