如何把动态生成资产信息、执行playbook以及自定义结果结合起来用呢?

#!/usr/bin/env python
# -*- coding: utf-8 -*- """
通过ansible API动态生成ansible资产信息但不产生实际的hosts文件
主机信息都可以通过数据库获得,然后生成指定格式,最后调用这个类来
生成主机信息。
""" import sys
# 用于读取YAML和JSON格式的文件
from ansible.executor.playbook_executor import PlaybookExecutor
from ansible.parsing.dataloader import DataLoader
# 用于存储各类变量信息
from ansible.vars.manager import VariableManager
# 用于导入资产文件
from ansible.inventory.manager import InventoryManager
# 操作单个主机信息
from ansible.inventory.host import Host
# 操作单个主机组信息
from ansible.inventory.group import Group
# 状态回调,各种成功失败的状态
from ansible.plugins.callback import CallbackBase
from collections import namedtuple class PlaybookCallResultCollector(CallbackBase):
"""
playbook的callback改写,格式化输出playbook执行结果
"""
CALLBACK_VERSION = 2.0 def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.task_ok = {}
self.task_unreachable = {}
self.task_failed = {}
self.task_skipped = {}
self.task_status = {} def v2_runner_on_unreachable(self, result):
"""
重写 unreachable 状态
:param result: 这是父类里面一个对象,这个对象可以获取执行任务信息
"""
self.task_unreachable[result._host.get_name()] = result def v2_runner_on_ok(self, result, *args, **kwargs):
"""
重写 ok 状态
:param result:
"""
self.task_ok[result._host.get_name()] = result def v2_runner_on_failed(self, result, *args, **kwargs):
"""
重写 failed 状态
:param result:
"""
self.task_failed[result._host.get_name()] = result def v2_runner_on_skipped(self, result):
self.task_skipped[result._host.get_name()] = result # def v2_playbook_on_stats(self, stats):
# hosts = sorted(stats.processed.keys())
# for h in hosts:
# t = stats.summarize(h)
# self.task_status[h] = {
# "ok": t["ok"],
# "changed": t["changed"],
# "unreachable": t["unreachable"],
# "skipped": t["skipped"],
# "failed": t["failed"]
# } class MyInventory:
def __init__(self, hostsresource):
"""
初始化函数
:param hostsresource: 主机资源可以有2种形式
列表形式: [{"ip": "172.16.48.171", "port": "22", "username": "root", "password": "123456"}]
字典形式: {
"Group1": {
"hosts": [{"ip": "192.168.200.10", "port": "1314", "username": "root", "password": None}],
"vars": {"var1": "ansible"}
},
"Group2": {}
}
"""
self._hostsresource = hostsresource
self._loader = DataLoader()
self._hostsfilelist = ["temphosts"]
"""
sources这个我们知道这里是设置hosts文件的地方,它可以是一个列表里面包含多个文件路径且文件真实存在,在单纯的执行ad-hoc的时候这里的
文件里面必须具有有效的hosts配置,但是当通过动态生成的资产信息的时候这个文件必须存在但是它里面可以是空的,如果这里配置成None那么
它不影响资产信息动态生成但是会有一个警告,所以还是要配置一个真实文件。
"""
self._inventory = InventoryManager(loader=self._loader, sources=self._hostsfilelist)
self._variable_manager = VariableManager(loader=self._loader, inventory=self._inventory) self._dynamic_inventory() def _add_dynamic_group(self, hosts_list, groupname, groupvars=None):
"""
动态添加主机到指定的主机组 完整的HOSTS文件格式
[test1]
hostname ansible_ssh_host=192.168.1.111 ansible_ssh_user="root" ansible_ssh_pass="123456" 但通常我们都省略hostname,端口也省略因为默认是22,这个在ansible配置文件中有,除非有非22端口的才会配置
[test1]
192.168.100.10 ansible_ssh_user="root" ansible_ssh_pass="123456" ansible_python_interpreter="/PATH/python3/bin/python3" :param hosts_list: 主机列表 [{"ip": "192.168.100.10", "port": "22", "username": "root", "password": None}, {}]
:param groupname: 组名称
:param groupvars: 组变量,格式为字典
:return:
"""
# 添加组
my_group = Group(name=groupname)
self._inventory.add_group(groupname) # 添加组变量
if groupvars:
for key, value in groupvars.items():
my_group.set_variable(key, value) # 添加一个主机
for host in hosts_list:
hostname = host.get("hostname", None)
hostip = host.get("ip", None)
if hostip is None:
print("IP地址为空,跳过该元素。")
continue
hostport = host.get("port", "")
username = host.get("username", "root")
password = host.get("password", None)
ssh_key = host.get("ssh_key", None)
python_interpreter = host.get("python_interpreter", None) try:
# hostname可以不写,如果为空默认就是IP地址
if hostname is None:
hostname = hostip
# 生成一个host对象
my_host = Host(name=hostname, port=hostport)
# 添加主机变量
self._variable_manager.set_host_variable(host=my_host, varname="ansible_ssh_host", value=hostip)
self._variable_manager.set_host_variable(host=my_host, varname="ansible_ssh_port", value=hostport)
if password:
self._variable_manager.set_host_variable(host=my_host, varname="ansible_ssh_pass", value=password)
self._variable_manager.set_host_variable(host=my_host, varname="ansible_ssh_user", value=username)
if ssh_key:
self._variable_manager.set_host_variable(host=my_host, varname="ansible_ssh_private_key_file", value=ssh_key)
if python_interpreter:
self._variable_manager.set_host_variable(host=my_host, varname="ansible_python_interpreter", value=python_interpreter) # 添加其他变量
for key, value in host.items():
if key not in ["ip", "hostname", "port", "username", "password", "ssh_key", "python_interpreter"]:
self._variable_manager.set_host_variable(host=my_host, varname=key, value=value) # 添加主机到组
self._inventory.add_host(host=hostname, group=groupname, port=hostport) except Exception as err:
print(err) def _dynamic_inventory(self):
"""
添加 hosts 到inventory
:return:
"""
if isinstance(self._hostsresource, list):
self._add_dynamic_group(self._hostsresource, "default_group")
elif isinstance(self._hostsresource, dict):
for groupname, hosts_and_vars in self._hostsresource.items():
self._add_dynamic_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars")) @property
def INVENTORY(self):
"""
返回资产实例
:return:
"""
return self._inventory @property
def VARIABLE_MANAGER(self):
"""
返回变量管理器实例
:return:
"""
return self._variable_manager class AnsibleRunner(object):
def __init__(self, hostsresource):
Options = namedtuple("Options", [
"connection", "remote_user", "ask_sudo_pass", "verbosity", "ack_pass",
"module_path", "forks", "become", "become_method", "become_user", "check",
"listhosts", "listtasks", "listtags", "syntax", "sudo_user", "sudo", "diff"
])
self._options = Options(connection='smart', remote_user=None, ack_pass=None, sudo_user=None, forks=5, sudo=None,
ask_sudo_pass=False,
verbosity=5, module_path=None, become=None, become_method=None, become_user=None, check=False,
diff=False,
listhosts=None, listtasks=None, listtags=None, syntax=None)
self._passwords = dict(sshpass=None, becomepass=None) # 这个可以为空,因为在hosts文件中
self._loader = DataLoader()
myinven = MyInventory(hostsresource=hostsresource)
self._inventory = myinven.INVENTORY
self._variable_manager = myinven.VARIABLE_MANAGER def run_playbook(self, playbook_path, extra_vars=None):
"""
执行playbook
:param playbook_path: playbook的yaml文件路径
:param extra_vars: 额外变量
:return: 无返回值
"""
try:
if extra_vars:
self._variable_manager.extra_vars = extra_vars
playbook = PlaybookExecutor(playbooks=[playbook_path], inventory=self._inventory, variable_manager=self._variable_manager, loader=self._loader,
options=self._options, passwords=self._passwords)
# 配置使用自定义callback
self._callback = PlaybookCallResultCollector()
playbook._tqm._stdout_callback = self._callback
# 执行playbook
playbook.run()
except Exception as err:
print(err) def get_playbook_result(self):
"""
获取playbook执行结果
:return:
"""
result_raw = {"ok": {}, "failed": {}, "unreachable": {}, "skipped": {}, "status": {}}
for host, result in self._callback.task_ok.items():
result_raw["ok"][host] = result._result for host, result in self._callback.task_failed.items():
result_raw["failed"][host] = result._result for host, result in self._callback.task_unreachable.items():
result_raw["unreachable"][host] = result._result for host, result in self._callback.task_skipped.items():
result_raw["skipped"][host] = result._result for host, result in self._callback.task_status.items():
result_raw["status"][host] = result._result return result_raw def main():
temphosts_list = [{"ip": "172.16.48.250", "port": "", "username": "root", "password": "12qwaszx!@QW"}] temphosts_dict = {
"Group1": {
"hosts": [{"ip": "192.168.200.10", "port": "", "username": "root", "password": None}],
"vars": {"var1": "ansible"}
},
# "Group2": {}
} # mi = MyInventory(temphosts_list)
# for group, hosts in mi.INVENTORY.get_groups_dict().items():
# print(group, hosts)
# host = mi.INVENTORY.get_host("192.168.200.10")
# print(mi.VARIABLE_MANAGER.get_vars(host=host)) ar = AnsibleRunner(temphosts_list)
ar.run_playbook("/Users/rex.chen/PycharmProjects/IDCMigration/AnsibleStudy/f1.yml")
print(ar.get_playbook_result()) if __name__ == "__main__":
try:
main()
finally:
sys.exit()

Python调用ansible API系列(五)综合使用的更多相关文章

  1. Python调用ansible API系列(四)动态生成hosts文件

    方法一:通过最原始的操作文件的方式 #!/usr/bin/env python # -*- coding: utf-8 -*- """ 通过操作文件形式动态生成ansib ...

  2. Python调用ansible API系列(一)获取资产信息

    你想让ansible工作首先就需要设置资产信息,那么我们如何通过使用Python调取Ansible的API来获取资产信息呢? 要提前准备一个hosts文件 获取组或者主机 #!/usr/bin/env ...

  3. Python调用ansible API系列(三)带有callback的执行adhoc和playbook

    在第二篇文章中虽然可以执行adhoc和playbook但是执行结果的输出并不是特别直观,虽然没有报错但是到底什么结果其实你是不知道的尤其是在执行adhoc的时候,这时候我们要利用callback来设置 ...

  4. Python调用ansible API系列(二)执行adhoc和playbook

    执行adhoc #!/usr/bin/env python # -*- coding: utf-8 -*- import sys from collections import namedtuple ...

  5. python调用ansible api 2.0 运行playbook带callback返回

    # -*- coding:utf8 -*- ''' Created on 2017年1月13日 @author: qiancheng ''' import os import json from co ...

  6. 使用Python调用Flickr API抓取图片数据

    Flickr是雅虎旗下的图片分享网站,上面有全世界网友分享的大量精彩图片,被认为是专业的图片网站.其API也很友好,可以实现多种功能.这里我使用了Python调用其API获得了大量的照片数据.需要注意 ...

  7. 基于python调用libvirt API

    基于python调用libvirt API 1.程序代码 #!/usr/bin/python import libvirt import sys def createConnection(): con ...

  8. 关于python调用zabbix api接口

    因公司业务需要,引进了自动化运维,所用到的监控平台为zbbix3.2,最近正在学习python,计划使用python调用zabbix api接口去做些事情,如生成报表,我想最基本的是要取得zabbix ...

  9. Python调用win32 API绘制正弦波

    Python调用win32 API新建窗口与直接创建窗口的流程相同 流程:注册窗口→创建窗口→显示窗口→更新窗口→消息循环 代码: # -*- coding: utf-8 -*- import win ...

随机推荐

  1. 爬虫之urllib包

    urllib简介 简介 Python3中将python2.7的urllib和urllib2两个包合并成了一个urllib库 Python3中,urllib库包含有四个模块: urllib.reques ...

  2. c# 多线程编程中AutoResetEvent和ManualResetEvent

    作为等同于Java的wait,notify,notifyAll的存在,AutoResetEvent和ManualResetEvent分别实现了notify和notifyAll的功能,下面的代码简单讲解 ...

  3. Spring使用 --- 基本概念(一):DI,依赖注入

    Table of Contents 什么是依赖注入 怎样使用 什么时候使用 好处 本文讲述sprint基本概念之一: DI, 即依赖注入. 什么是依赖注入 说类A依赖于类B,最简单的例子是类A有一个类 ...

  4. 团队项目第二阶段个人进展——Day9

    一.昨天工作总结 冲刺第九天,完成图片的优化,与队友一起讨论如何合并并优化 二.遇到的问题 无 三.今日工作规划 合并后优化

  5. 高通spi 屏幕 -lk代码分析

    lk SPI驱动 1. 初始化时钟 在lk中,我们是从kmain开始执行下来的,而执行顺序则是先初始化时钟,也就是在platform_early_init函数中开始执行的: 在这里我们需要修改这个函数 ...

  6. Nordic官网/Infocenter/Devzone/Github简介

    1. Nordic官网及资料下载 Nordic官网主页:https://www.nordicsemi.com/,进入官网后,一般点击"Products"标签页,即进入Nordic产 ...

  7. Python基础之数据类型、变量、常量

    数据类型 整数:任意大小的整数,十六进制用0x前缀 浮点数:浮点数也就是小数,科学计数法1.23x109就是1.23e9,0.000012可以写成1.2e-5 字符串:以单引号'或双引号"括 ...

  8. 2017年BackBox5和Ubuntu16.04.1国内更新源

    BackBox是基于Ubuntu的Linux发行版,因此,我们可以使用Ubuntu的更新源作为BackBox的更新源. 1.查看系统版本信息: 输入: uname -a 显示计算机及操作系统的有关信息 ...

  9. [OPEN CV] 常用视频操作方法

    一.视频的定义 视频(Video)泛指将一系列静态影像以电信号的方式加以捕捉.纪录.处理.储存.传送与重现的各种技术.连续的图像变化每秒超过24帧(frame)画面以上时,根据视觉暂留原理,人眼无法辨 ...

  10. ViewDragHelper实战 自己打造Drawerlayout

    转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/47396187: 本文出自:[张鸿洋的博客] 一.概述 中间拖了蛮长时间了,在上 ...