第六章:扩展ansible组件
6.1、扩展facts
1、 定义facts.d信息
为了区别每一台业务和角色,会将业务相关信息保存到本机。通过Ansible的setup模块会检测被控制键的fact_path目录下以fact结尾的文件,读取文件内容当做facts信息收集。
module_utils/facts.py文件Facts类的get_local_facts函数:中看不懂地方收集。
#获取指定目录下的所有图片
print (glob.glob(r"/home/qiaoyunhao/*/*.png"),"\n")#加上r让字符串不转义
#获取上级目录的所有.py文件
print (glob.glob(r'../*.py')) #相对路径
#等于os.listdir()
#将python格式转换成ini格式(key=value)
import configparser #引入模块
config = configparser.ConfigParser() #类中一个方法 #实例化一个对象
config["DEFAULT"] = {'ServerAliveInterval': '45',
'Compression': 'yes',
'CompressionLevel': '9',
'ForwardX11':'yes'
} #类似于操作字典的形式
config['bitbucket.org'] = {'User':'Atlan'} #类似于操作字典的形式
config['topsecret.server.com'] = {'Host Port':'50022','ForwardX11':'no'}
with open('example.ini', 'w') as configfile:
config.write(configfile) #将对象写入文件
#读取ini格式文件
import configparser
config = configparser.ConfigParser()
config.read('example.ini')
print(config.sections()) #显示内容['bitbucket.org', 'topsecret.server.com']
print('bytebong.com' in config) # False
print('bitbucket.org' in config) # True
#函数对所有可迭代的对象进行排序操作。
sorted()
#shlex 模块最常用的是 split() 函数,用来分割字符串,通常与 subprocess 结合使用
import shlex
shlex.split('my name is tom')
['my', 'name', 'is', 'tom']
import shlex, subprocess
subprocess.Popen(shlex.split('ls -l /data'))#执行命令
import json
data = {'name' : 'myname',
'age' : 200,}
#Python--》JSON:
json_str = json.dumps(data)
#JSON--》Python:
data = json.loads(json_str)
还是有很多地方看不懂,都是python2的代码,建议跳过,书上代码先贴出来,不然白敲了。
import os,glob,json,configparser
def get_local_facts(self):
#fact_path = module.params.get('fact_path',None)
fact_path = '/'
if not fact_path or not os.path.exists(fact_path):
return
local = {}
for fn in sorted(glob.glob(fact_path + '/*.fact')):#遍历fact_path目录下.fact文件
fact_base=os.path.basename(fn).replace('.fact','')
if stat.S_IXUSR & os.stat(fn)[stat.ST_MODE]:
rc,out,err = module.run_command(fn)
else:
out = get_file_content(fn, default='')
fact = 'loading %s'%fact_base
try:
fact = json.loads(out)
except ValueError as e:
cp = configparser.ConfigParser()
try:
cp.readfp(StringIO.StringIO(out))
except configparser.Error as e:
fact='error loading fact - please check content'
else:
fact = {}
for sect in cp.sections():
if sect not in fact:
fact[sect] = {}
for opt in cp.options(sect):
val = cp.get(sect,opt)
fact[sect][opt] = val
local[fact_base] = fact
if not local:
return
self.facts['local'] = local
os.listdir()
2、编写facts模块
使用模块来收集信息,而不用向上面一样每个机器上保存一个文件。
#!/usr/bin/python3
import json
import sys
args_file = sys.argv[1]#
args_data = open(args_file).read()#
arguments = args_data.split()#
for arg in arguments:
if "=" in arg:
(key,value) = arg.split('=')
if key == 'enable' and value == 'yes':
data = {}
data['key'] = 'value'
data['list'] = ['one','two','three']
data['dict'] = {'A':'a'}
print(json.dumps({'ansible_facts':data},indent=4))
#indent不懂。这里的ansible_facts是固定的,改变此键,后面的模板会找不到变量。
else:
print('info modules usage error')
else:
print('info modules need one parameter')
前3句看不懂,不知道参数从什么地方传递过来,通过ansible启动的话。
ansible all -M library/ -m info -a 'enable=yes' -o
#enable=yes指的是arg变量
把library/目录加入到ANSIBLE_LIBRARY环境变量。然后就可以通过playbook的template取引用facts信息。
#info.j2
key is {{ key }}
list is {% for i in list %} {{ i }} {% endfor %}
dict['A'] is {{ dict['A'] }}
#info.yaml
---
- hosts: all
tasks:
- name: test info facts module
info: enable=yes
- name: debug info facts
template: src=info.j2 dest=/tmp.cpis
#注意此处info必须与name对其,否则会错误
ansible-playbook 要操作的主机 info.yaml
6.2扩展模块(略)
6.3callback插件
添加链接描述 1、了解插件流程
2、编写插件
把playbook执行状态信息写入Mysql。
vim status.py
import pymysqlroot
import os,time,datetime
TIME_FORMAT='%Y-%m-%d %H:%M:%S'
now = datetime.datetime.now()
def insert(host, res):
db = pymysql.connect('localhost','root','123456','testDB')
cur = db.cursor()
sql = 'insert into status(hosts,result,date) values(%s,%s,%s)'%(host,res,now.strftime(TIME_FORMAT))
try:
cur.execute(sql)
db.commit()
except:
db.rollback()
db.close()
def CallbackModule(object):
def on_any(self,*args,**kwargs):
pass
def runner_on_failed(self,host,res,ignore_errors=False):
insert(host,res)
def runner_on_ok(self,host,res):
insert(host,res)
def runner_on_unreachable(self,host,res):
insert(host,res)
def playbook_on_import_for_host(self,host,imported_file):
pass
def playbook_on_not_import_for_host(self,host,missing_file):
pass
def playbook_on_stats(self,stats):
hosts = stats.processed.keys()
for i in hosts:
info = stats.summarize(i)
if info['failures'] > 0 or info['unreachable'] > 0:
has_errors = True
msg = 'Hostinfo: %s,ok: %d,failures: %d,unreachable: %d,changed:%d,' \
'skipped: %d'%(i,info['ok'],info['failures'],info['unreachable'],
info['changed'],info['skipped'])
print(msg)
无法启动callback??? 已解决
vim /etc/ansible/ansible.cfg
#用yum安装时才会生成这个配置文件,所以建议安装两次第一次用pip安装,
可以生成/usr/local/lib/python3.6/site-packages/ansible/plugins/callback/在类似这个目录下一些默认的callback。
callback_plugins = /usr/share/ansible/plugins/callback/
#这里是callback文件的路径,把要执行的callback放在这个目录下
bin_ansible_callbacks = Ture
callback_whitelist = XXX
#这里是要执行的模块名称,比如有一个test.py模块,就写test
运行时object错误。暂时跳过。
添加链接描述callback存入sqlit3后,再用分解数据