#!/usr/bin/env python#-*- coding: utf8 -*-#@Author: huangmanyao
from ansible importconstantsfrom collections importnamedtuplefrom ansible.parsing.dataloader importDataLoaderfrom ansible.playbook.play importPlayfrom ansible.executor.task_queue_manager importTaskQueueManagerfrom ansible.executor.playbook_executor importPlaybookExecutorfrom ansible.plugins.callback importCallbackBasefrom ansible.inventory.manager importInventoryManagerfrom ansible.vars.manager importVariableManagerimportjsonimportIPyclassModelResultsCollector(CallbackBase):'''重构执行结果'''
def __init__(self, *args, **kwargs):
super(ModelResultsCollector, self).__init__(*args, **kwargs)
self.host_ok={}
self.host_unreachable={}
self.host_failed={}defv2_runner_on_unreachable(self, result):'''不可达'''self.host_unreachable[result._host.get_name()]=resultdef v2_runner_on_ok(self, result, *args, **kwargs):'''执行成功'''self.host_ok[result._host.get_name()]=resultdef v2_runner_on_failed(self, result, *args, **kwargs):'''执行失败'''self.host_failed[result._host.get_name()]=resultclassPlayBookResultsCollector(CallbackBase):
CALLBACK_VERSION= 2.0
def __init__(self, *args, **kwargs):
super(PlayBookResultsCollector, self).__init__(*args, **kwargs)
self.task_ok={}
self.task_skipped={}
self.task_failed={}
self.task_status={}
self.task_unreachable={}def v2_runner_on_ok(self, result, *args, **kwargs):
self.task_ok[result._host.get_name()]=resultdef v2_runner_on_failed(self, result, *args, **kwargs):
self.task_failed[result._host.get_name()]=resultdefv2_runner_on_unreachable(self, result):
self.task_unreachable[result._host.get_name()]=resultdefv2_runner_on_skipped(self, result):
self.task_ok[result._host.get_name()]=resultdefv2_playbook_on_stats(self, stats):
hosts=sorted(stats.processed.keys())for h inhosts:
t=stats.summarize(h)
self.task_status[h]={"ok": t['ok'],"changed": t['changed'],"unreachable": t['unreachable'],"skipped": t['skipped'],"failed": t['failures']
}classANSRunner(object):"""This is a General object for parallel execute modules."""
def __init__(self, ips=None, *args, **kwargs):
self.ips=ips
self.inventory=None
self.variable_manager=None
self.loader=None
self.options=None
self.passwords=None
self.callback=None
self.__initializeData()
self.results_raw={}defis_ip(self,address):try:
IPy.IP(address)returnTrueexceptException as e:returnFalsedeflist_to_str(self,ips):
ipsstr= ','.join(ips)if len(ips) == 1:
ipsstr+= ','
returnipsstrdeflist_ip_check(self,ips):
ipslist=ips
ipslist_len=len(ips)if ipslist_len > 1:for ip inipslist:if notself.is_ip(ip):
ipslist.remove(ip)returnipslistdefips_cov_str(self):if notself.ips:
self.ips= "127.0.0.1"
ifisinstance(self.ips,list):
self.ips=self.list_ip_check(self.ips)
self.ips=self.list_to_str(self.ips)elifisinstance(self.ips,str):
ipslist= self.ips.split(',')
ipslist=self.list_ip_check(ipslist)
self.ips=self.list_to_str(ipslist)def __initializeData(self):"""初始化ansible"""Options= namedtuple('Options', ['connection', 'module_path', 'forks', 'timeout', 'remote_user','ask_pass', 'private_key_file', 'ssh_common_args', 'ssh_extra_args','sftp_extra_args','scp_extra_args', 'become', 'become_method', 'become_user', 'ask_value_pass','verbosity','check', 'listhosts', 'listtasks', 'listtags', 'syntax', 'diff'])
self.options= Options(connection='smart', module_path=None, forks=100, timeout=10,
remote_user='root', ask_pass=False, private_key_file=None, ssh_common_args=None,
ssh_extra_args=None,
sftp_extra_args=None, scp_extra_args=None, become=None, become_method=None,
become_user='root', ask_value_pass=False, verbosity=None, check=False, listhosts=False,
listtasks=False, listtags=False, syntax=False, diff=True)
self.loader=DataLoader()
self.ips_cov_str()
self.inventory= InventoryManager(loader=self.loader, sources='%s'%(self.ips))
self.variable_manager= VariableManager(loader=self.loader, inventory=self.inventory)defrun_model(self, module_name, module_args):"""run module from andible ad-hoc.
module_name: ansible module_name
module_args: ansible module args"""self.ips_cov_str()
play_source=dict(
name="Ansible Play",
hosts=self.ips,
gather_facts='no',
tasks=[dict(action=dict(module=module_name, args=module_args))]
)
play= Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader)
tqm=None
self.callback=ModelResultsCollector()importtracebacktry:
tqm=TaskQueueManager(
inventory=self.inventory,
variable_manager=self.variable_manager,
loader=self.loader,
options=self.options,
passwords=self.passwords,
stdout_callback="minimal",
)
tqm._stdout_callback=self.callback
constants.HOST_KEY_CHECKING= False #关闭第一次使用ansible连接客户端是输入命令
tqm.run(play)exceptException as err:print(traceback.print_exc())finally:if tqm is notNone:
tqm.cleanup()def run_playbook(self, playbook_path, extra_vars=None):"""运行playbook"""
try:
self.callback=PlayBookResultsCollector()ifextra_vars:
self.variable_manager.extra_vars=extra_vars
executor=PlaybookExecutor(
playbooks=[playbook_path], inventory=self.inventory, variable_manager=self.variable_manager,
loader=self.loader,
options=self.options, passwords=self.passwords,
)
executor._tqm._stdout_callback=self.callback
constants.HOST_KEY_CHECKING= False #关闭第一次使用ansible连接客户端是输入命令
executor.run()exceptException as err:returnFalsedefget_model_result(self):
self.results_raw= {'success': {}, 'failed': {}, 'unreachable': {}}for host, result inself.callback.host_ok.items():
hostvisiable= host.replace('.', '_')
self.results_raw['success'][hostvisiable] =result._resultfor host, result inself.callback.host_failed.items():
hostvisiable= host.replace('.', '_')
self.results_raw['failed'][hostvisiable] =result._resultfor host, result inself.callback.host_unreachable.items():
hostvisiable= host.replace('.', '_')
self.results_raw['unreachable'][hostvisiable] =result._resultreturnself.results_rawdefget_playbook_result(self):
self.results_raw= {'skipped': {}, 'failed': {}, 'ok': {}, "status": {}, 'unreachable': {}, "changed": {}}for host, result inself.callback.task_ok.items():
self.results_raw['ok'][host] =result._resultfor host, result inself.callback.task_failed.items():
self.results_raw['failed'][host] =result._resultfor host, result inself.callback.task_status.items():
self.results_raw['status'][host] =resultfor host, result inself.callback.task_skipped.items():
self.results_raw['skipped'][host] =result._resultfor host, result inself.callback.task_unreachable.items():
self.results_raw['unreachable'][host] =result._resultreturnself.results_raw