# -*- conding:utf-8 -*-
import json
import os
import sys
import time
from collections import namedtuple
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.inventory import Inventory
from ansible.inventory.group import Group
from ansible.inventory.host import Host
from ansible.parsing.dataloader import DataLoader
from ansible.playbook.play import Play
from ansible.plugins.callback import CallbackBase
from ansible.vars import VariableManager
from ansible.executor.playbook_executor import PlaybookExecutor
class ResultsCollector(CallbackBase):
def __init__(self, *args, **kwargs):
super(ResultsCollector, self).__init__(*args, **kwargs)
self.host_ok = {}
self.host_unreachable = {}
self.host_failed = {}
def v2_runner_on_unreachable(self, result):
self.host_unreachable[result._host.get_name()] = result
def v2_runner_on_ok(self, result, *args, **kwargs):
self.host_ok[result._host.get_name()] = result
def v2_runner_on_failed(self, result, *args, **kwargs):
self.host_failed[result._host.get_name()] = result
def v2_runner_on_skipped(self, result):
self.state = 'skipped'
self.result = result._result
def v2_runner_on_no_hosts(self, task):
print('skipping: no hosts matched')
def v2_playbook_on_task_start(self, task, is_conditional):
print("TASK [%s]" % task.get_name().strip())
def v2_playbook_on_play_start(self, play):
name = play.get_name().strip()
if not name:
msg = "PLAY"
else:
msg = "PLAY [%s]" % name
print(msg)
def v2_playbook_on_stats(self, stats):
hosts = sorted(stats.processed.keys())
for h in hosts:
t = stats.summarize(h)
msg = "PLAY RECAP [%s] : %s %s %s %s %s" % (
h,
"ok: %s" % (t['ok']),
"changed: %s" % (t['changed']),
"unreachable: %s" % (t['unreachable']),
"skipped: %s" % (t['skipped']),
"failed: %s" % (t['failures']),
)
print(msg)
class MyInventory(Inventory):
"""
this is my ansible inventory object.
"""
def __init__(self, resource, loader, variable_manager):
self.resource = resource
self.inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=[])
self.gen_inventory()
def my_add_group(self, hosts, groupname, groupvars=None):
"""
add hosts to a group
"""
my_group = Group(name=groupname)
# if group variables exists, add them to group
if groupvars:
for key, value in groupvars.iteritems():
my_group.set_variable(key, value)
# add hosts to group
for host in hosts:
# set connection variables
hostname = host.get("hostname")
hostip = host.get('ip', hostname)
hostport = host.get("port")
username = host.get("username")
password = host.get("password")
ssh_key = host.get("ssh_key")
my_host = Host(name=hostname, port=hostport)
my_host.set_variable('ansible_ssh_host', hostip)
my_host.set_variable('ansible_ssh_port', hostport)
my_host.set_variable('ansible_ssh_user', username)
my_host.set_variable('ansible_ssh_pass', password)
my_host.set_variable('ansible_ssh_private_key_file', ssh_key)
# set other variables
for key, value in host.items():
if key not in ["hostname", "port", "username", "password"]:
my_host.set_variable(key, value)
# add to group
my_group.add_host(my_host)
self.inventory.add_group(my_group)
def gen_inventory(self):
"""
add hosts to inventory.
"""
if isinstance(self.resource, list):
self.my_add_group(self.resource, 'default_group')
elif isinstance(self.resource, dict):
for groupname, hosts_and_vars in self.resource.items():
self.my_add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))
class MyRunner(object):
"""
This is a General object for parallel execute modules.
"""
def __init__(self, resource, *args, **kwargs):
self.resource = resource
self.inventory = None
self.variable_manager = None
self.loader = None
self.options = None
self.passwords = None
self.callback = None
self.__initializeData()
self.results_raw = {}
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'])
# initialize needed objects
self.variable_manager = VariableManager()
self.loader = DataLoader()
self.options = Options(connection='smart', module_path='/usr/local/python36/lib/python3.6/site-packages/ansible/modules', 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)
self.passwords = dict(sshpass=None, becomepass=None)
self.inventory = MyInventory(self.resource, self.loader, self.variable_manager).inventory
self.variable_manager.set_inventory(self.inventory)
def run(self, host_list, module_name, module_args):
"""
run module from andible ad-hoc.
module_name: ansible module_name
module_args: ansible module args
"""
# create play with tasks
print(host_list, module_name, module_args)
play_source = dict(
name="Ansible Play",
hosts=host_list,
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 = ResultsCollector()
try:
tqm = TaskQueueManager(
inventory=self.inventory,
variable_manager=self.variable_manager,
loader=self.loader,
options=self.options,
passwords=self.passwords,
)
tqm._stdout_callback = self.callback
result = tqm.run(play)
time.sleep(10)
finally:
if tqm is not None:
tqm.cleanup()
# def run_playbook(self, host_list, role_name, role_uuid, temp_param):
def run_playbook(self, hosts, playbookfile, playbookvars):
"""
run ansible palybook
"""
try:
self.callback = ResultsCollector()
filenames = [playbookfile] # playbook的路径
print('ymal file path:%s' % filenames)
extra_vars = playbookvars # 额外的参数 sudoers.yml以及模板中的参数,它对应ansible-playbook test.yml --extra-vars "host='aa' name='cc' "
self.variable_manager.extra_vars = extra_vars
print('playbook 额外参数:%s' % self.variable_manager.extra_vars)
executor = PlaybookExecutor(
playbooks=filenames, inventory=self.inventory, variable_manager=self.variable_manager,
loader=self.loader,
options=self.options, passwords=self.passwords,
)
executor._tqm._stdout_callback = self.callback
executor.run()
except Exception as e:
print("run_playbook:%s" % e)
# def run_rule(self, hosts, playbookfile, playbooktag):
# """
# run ansible palybook
# """
# try:
# self.callback = ResultsCollector()
# filenames = [playbookfile] # playbook的路径
# print('ymal file path:%s' % filenames)
#
# extra_vars = {} # 额外的参数 sudoers.yml以及模板中的参数,它对应ansible-playbook test.yml --extra-vars "host='aa' name='cc' "
# extra_vars['host'] = hosts
# self.variable_manager.extra_vars = extra_vars
# print('playbook 额外参数:%s' % self.variable_manager.extra_vars)
#
# self.options = self.options._replace(tags=playbooktag)
## executor = PlaybookExecutor(
# playbooks=filenames, inventory=self.inventory, variable_manager=self.variable_manager,
## loader=self.loader,
# options=self.options, passwords=self.passwords,
# )
# executor._tqm._stdout_callback = self.callback
# executor.run()
# except Exception as e:
# print("run_playbook:%s" % e)
def get_result(self):
self.results_raw = {'success': {}, 'failed': {}, 'unreachable': {}}
for host, result in self.callback.host_ok.items():
self.results_raw['success'][host] = result._result
for host, result in self.callback.host_failed.items():
self.results_raw['failed'][host] = result._result['msg']
for host, result in self.callback.host_unreachable.items():
self.results_raw['unreachable'][host] = result._result['msg']
print("Ansible执行结果集:%s" % json.dumps(self.results_raw, indent=4))
return json.dumps(self.results_raw, indent=4)
if __name__ == '__main__':
res ={
"app": {
"hosts": [
{
'hostname': '192.168.176.112'
}
]
},
"one": {
"hosts": [
{
'username': 'root',
'hostname': '192.168.1.1',
'ip': '192.168.1.1',
'ssh_key': '/usr/local/python36/django/key/local',
'password': '12345678', #password 不能认证
'port': 22
}
]
}
}
rapi = MyRunner(res)
rapi.run('one', 'shell', 'ss -tnl')
rapi.get_result()
python调用ansibleapi ,api版本是2.3的,这段配置的是秘钥的密码:('password': '12345678', #password 不能认证)执行时没有效果,一直卡住不动, 把这段去掉,也就是my_host.set_variable('ansible_ssh_pass', password)的password为None的时候在执行会出现交互模式输入密钥密码,哪里写的有问题吗,或者该怎么写?? 0-0
注:是生成密钥时设置的密码,不是账户的密码
好主意是全用SSH keys进行远程登录.
如果你执意想用username/password方式, 可以通过建立inventory文件的方式存储.默认放到
/etc/ansible/hosts
下面, 也可以用参数的方式指定-i <path>
.版本 Ansible <2.0:
版本 Ansible >=2.0:
参考:
https://serverfault.com/quest...