2.3的api和2.8有一些区别,一个是inventory方面的,2.3直接导入Inventory,而2.8是InventoryManager,这两个类的方法不太一样。
最近有用到2.3版本的,所以这里记一下,详细介绍还是看之前博客Python调用ansible 2.8 API吧
先安装依赖和包,如果是2.7的python版本,pip版本不能超过21
安装依赖和包
yum install python-devel sshpass -y
yum install python-pip -y
pip install --upgrade "pip < 21.0"
pip install ansible==2.3.1
#/usr/bin/python
# coding=UTF-8
import json
import sys
from collections import namedtuple
from ansible.parsing.dataloader import DataLoader
from ansible.vars import VariableManager
from ansible.inventory import Inventory
from ansible.executor.playbook_executor import PlaybookExecutor
from ansible.plugins.callback import CallbackBase
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.inventory.host import Group #对 主机组 执行操作 ,可以给组添加变量等操作,扩展
from ansible.inventory.host import Host #对 主机 执行操作 ,可以给主机添加变量等操作,扩展
class ResultsCallback(CallbackBase):
def __init__(self,*args,**kwargs):
super(ResultsCallback,self).__init__(*args,**kwargs)
self.task_ok = {}
self.task_unreachable = {}
self.task_failed = {}
self.task_skipped = {}
self.task_stats = {}
# self.host_ok = {}
# self.host_unreachable = {}
# self.host_failed = {}
def v2_runner_on_unreachable(self, result):
self.task_unreachable[result._host.get_name()] = result
def v2_runner_on_ok(self, result, *args, **kwargs):
self.task_ok[result._host.get_name()] = result
def v2_runner_on_failed(self, result, *args, **kwargs):
self.task_failed[result._host.get_name()] = result
def v2_runner_on_skipped(self, result, *args, **kwargs):
self.task_skipped[result._host.get_name()] = result
def v2_runner_on_stats(self, result, *args, **kwargs):
self.task_stats[result._host.get_name()] = result
class Runner(object):
def __init__(self,
connection='ssh', # 连接方式 local 本地方式,smart ssh方式
remote_user="None", # 远程用户
host_list='/etc/ansible/hosts',
ack_pass=None, # 提示输入密码
sudo=None,
sudo_user="root",
ask_sudo_pass=None,
module_path=None, # 模块路径,可以指定一个自定义模块的路径
become=None, # 是否提权
become_method="sudo", # 提权方式 默认 sudo 可以是 su
become_user="root", # 提权后,要成为的用户,并非登录用户
check=False,
diff = False,
listhosts = None,
listtasks = None,
listtags = None,
forks = 5, # 同时执行的主机数量
tags = [], # 执行的tags列表
skip_tags = [], # skip跳过的tags列表
verbosity = 3,
syntax = None,
start_at_task = None,
inventory = None,
passwords=None,
*args,**kwargs):
#三元表达式,假如没有传递 inventory文件, 就使用 "localhost,"
#这里需要注意如果不使用host文件,即inventory未传入,直接动态传入host列表的情况,这里会将localhost加入主机中,所以执行all主机组也会执行本机,所以要么改为未传入就为“”,要么就设置其他的主机组名称,不使用all执行全部
#inventory 就是平时用到的存放主机ip以及变量的资源库文件,-i 参数后面跟的文件
self.inventory = inventory if inventory else "localhost,"
# 实例化数据解析器,用于解析 存放主机列表的资源库文件 (比如: /etc/ansible/hosts) 中的数据和变量数据的
self.loader = DataLoader()
# 实例化 资产配置对象,InventoryManager管理资源库,可以指定一个loader数据解析器和一个inventory文件
#self.inv_obj = InventoryManager(loader=self.loader, sources=self.inventory)
# 设置密码,可以为空字典,但必须有此参数
self.passwords = {"conn_pass":passwords}
# 实例化回调插件对象
self.results_callback = ResultsCallback()
# 变量管理器,假如有变量,所有的变量应该交给他管理。 这里他会从 inventory 对象中获取到所有已定义好的变量。 这里也需要数据解析器。
#self.variable_manager = VariableManager(self.loader, self.inv_obj)
#self.loader = DataLoader()
self.variable_manager = VariableManager()
#self.results_callback = ResultsCallback()
#default host_list='/etc/ansible/hosts'
self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager,host_list=host_list)
self.variable_manager.set_inventory(self.inventory)
#self.passwords = None
Options = namedtuple('Options',
['connection',
'remote_user',
'verbosity',
'ack_pass',
'module_path',
'forks',
'become',
'become_method',
'become_user',
'check',
'listhosts',
'listtasks',
'listtags',
'syntax',
"skip_tags",
'tags',
"start_at_task",
])
# 初始化需要的对象
self.options = Options(connection=connection,
remote_user=remote_user,
ack_pass=ack_pass,
forks=forks,
verbosity=5,
module_path=module_path,
become=become,
become_method=become_method,
become_user=become_user,
check=check,
listhosts=listhosts,
listtasks=listtasks,
listtags=listtags,
syntax=syntax,
skip_tags=skip_tags,
tags=tags,
start_at_task=start_at_task,)
def run_ad_hoc(self,hosts='all', gether_facts="no", module="ping", args=''):
play_source = dict(
name="Ad-hoc",
hosts=hosts,
gather_facts=gether_facts,
tasks=[
#dict(action=dict(module='shell', args='ls /home'), register='shell_out'),
#dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}'))),
{"action": {"module": module, "args": args}}
]
)
play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader)
tqm = None
try:
tqm = TaskQueueManager(
inventory=self.inventory,
variable_manager=self.variable_manager,
loader=self.loader,
options=self.options,
passwords=self.passwords,
stdout_callback=self.results_callback,
)
result = tqm.run(play)
finally:
if tqm is not None:
tqm.cleanup()
##定义字典用于接收或者处理结果
result_raw = {'success': {}, 'failed': {}, 'unreachable': {}, 'skipped': {}, 'status': {}}
# 循环打印这个结果,success,failed,unreachable需要每个都定义一个
for host, result in self.results_callback.task_ok.items():
result_raw['success'][host] = result._result
for host, result in self.results_callback.task_failed.items():
result_raw['failed'][host] = result._result
for host, result in self.results_callback.task_unreachable.items():
result_raw['unreachable'][host] = result._result
return result_raw
def run_playbook(self,playbook,extra_vars={}):
#自定义变量是用一个字典保存的
#使用变量管理器VariableManager().extra_vars.update(extra_vars_dict)的方法进行添加
self.variable_manager.extra_vars.update(extra_vars)
playbook = PlaybookExecutor(playbooks=playbook, inventory=self.inventory,
variable_manager=self.variable_manager,
loader=self.loader, options=self.options, passwords=self.passwords)
playbook._tqm._stdout_callback = self.results_callback
results = playbook.run()
##定义字典用于接收或者处理结果
result_raw = {'success': {}, 'failed': {}, 'unreachable': {}, 'skipped': {}, 'status': {}}
# 循环打印这个结果,success,failed,unreachable需要每个都定义一个
for host, result in self.results_callback.task_ok.items():
result_raw['success'][host] = result._result
for host, result in self.results_callback.task_failed.items():
result_raw['failed'][host] = result._result
for host, result in self.results_callback.task_unreachable.items():
result_raw['unreachable'][host] = result._result
for host, result in self.results_callback.task_skipped.items():
result_raw['skipped'][host] = result._result
for host, result in self.results_callback.task_stats.items():
result_raw['status'][host] = result._result
return result_raw
#动态添加主机,传入主机列表和组名
def add_dynamic_hosts(self, hostip_list, groupname=None, groupvars=None):
"""
add hosts to a group
"""
#如果有传入组名,则添加组,并创建Group实例
if groupname:
my_group = Group(name=groupname)
else:
#or ungruped
my_group=Group(name="all")
#如果有传入组变量,则将组变量设置给上面创建的Group实例
if groupvars:
for key, value in groupvars.iteritems():
my_group.set_variable(key, value)
# add hosts to group
#则遍历主机列表,添加主机并且设置组
for hostip in hostip_list:
my_host = Host(name=hostip, port="22")
my_group.add_host(my_host)
self.inventory.add_group(my_group)
if __name__ == '__main__':
# 1、执行hoc 传入机器机器IP列表的方式
# run1 = Runner(remote_user="root",passwords="123456",become=True,become_user="root")
# run1.add_dynamic_hosts(hostip_list=["10.0.0.108"],groupname="remote")
#print(run1.run_ad_hoc(hosts= "remote", module="shell", args="/sbin/ethtool ens33 | grep Speed | awk '{print $2}'"))
# 2、执行hoc 使用某个host文件的方式
#run2 = Runner(remote_user="root",passwords="123456",host_list="/root/PycharmProjects/ansibletest/ansiblehosts")
#print(run2.run_ad_hoc(hosts= "all", module="shell", args='pwd'))
#3、执行playbook
# run3 = Runner(remote_user="root",passwords="123456",)
# run3.add_dynamic_hosts(hostip_list=["10.0.0.108"],groupname="remote")
#print(run3.run_playbook(playbook=["/root/PycharmProjects/ansibletest/playbook.yaml"]))