Ansible API 2.10.5 运行playbook记录
前言
最近想着看看ansible的api,然后写一个日常报表的生成脚本,这样就不用每天人力一个个去检查了,毕竟涉及的服务器有上百台。
正文
版本准备
- Python3.8.8
- Ansible2.10.5 (这个版本API又和之前不一样)
搭建开发环境
Python的安装就不说了,这里使用的是python3.8版本,windows装ansible实在是麻烦,我直接在linux弄了,使用pip安装就好:
pip3 install ansible==2.10.5 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip安装后,并不会创建ansible相关命令的软连接,如果需要可以手动创建,跑一个for就可以了,如下:
for i in `ls /usr/local/python3/bin/|grep ansible`;do ln -s /usr/local/python3/bin/$i /usr/bin/$i;done
一切就绪后,我们自己创建配置文件并测试一下,经典的ping模块和Hello World:
捕捉回显结果
借鉴案例
借鉴网上的样例,先写了一个回调函数:
class MyPlaybookCallback(CallbackBase):
def __init__(self, *args):
super(MyPlaybookCallback, 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
这个回显运行ad-hoc没有问题,但是如果运行playbook,只会显示最后一次运行任务结果,比如下面这个playbook:
- hosts: myhost
remote_user: root
gather_facts: false
tasks:
- name: 磁盘只读及坏盘巡检
shell: touch /data*
ignore_errors: true
- name: 磁盘容量巡检
shell: df -hP|awk 'NR>1 && int($5) > 80'
ignore_errors: true
- name: 内存巡检
shell: export usag=`free | awk '/-\/+/{print $3}'`;free | awk -v test="$usag" '/Mem/{printf("%.2f%"), test/$2*100}'
ignore_errors: true
- name: CPU巡检
shell: cat /proc/stat | awk '/cpu/{printf("%.2f%\n"), ($2+$4)*100/($2+$4+$5)}' | awk '{print $0}' | head -1
ignore_errors: true
打印最终结果的TASK会发现只有最后一个TASK的结果,这显然不是我想要的:
适配每个任务结果获取
笔者代码能力一般,不知道这样的写法是否适用于项目,仅仅做个记录,根据ansible的源码可以知道这几个信息:
- v2_playbook_on_start会在每个playbook运行前调用;
- v2_playbook_on_task_start会在每个task运行前调用;
- v2_runner_on_ok等会在每个task运行后调用,
因此,重写回调类的时候,可以直接在v2_runner_on_ok进行编写,failed状态的可以参考编写:
def v2_runner_on_ok(self, result):
host = result._host.get_name()
self.runner_on_ok(host, result._result)
self.host_ok[host] = result
t = {
"hostname": host,
"taskname": result._task,
"result": result._result
}
self.result.append(t)
最终只需要实际的playbook执行类中获取结果并打印就好,比如:
def get_result(self):
self.result_all = {'success': {}, 'fail': {}, 'unreachable': {}}
print(self.results_callback.result)
执行任务时获取组名
因为需要出报表,所以对服务器ip进行了分组,包括了应用,gis等,为了能够在报表生成时自动对分组内容填写,找到一种方法可以直接打印出组名:
pbex = PlaybookExecutor(playbooks=[self.playbook_path],
inventory=self.inv_obj,
variable_manager=self.variable_manager,
loader=self.loader,
passwords=self.passwords)
pbex._tqm._stdout_callback = self.results_callback
print(pbex._tqm.get_variable_manager().get_vars()['groups'])
实际使用肯定还是需要进一步处理的,这样获取的返回值如下:
|