Created
March 3, 2017 10:22
-
-
Save choldrim/3211f1660291f871739379082f204c83 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# coding=utf-8 | |
import json | |
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 | |
class CallbackModule(CallbackBase): | |
""" | |
Reference: https://github.com/ansible/ansible/blob/v2.0.0.2-1/lib/ansible/plugins/callback/default.py | |
""" | |
CALLBACK_VERSION = 2.0 | |
CALLBACK_TYPE = 'stored' | |
CALLBACK_NAME = 'database' | |
def __init__(self): | |
super(CallbackModule, self).__init__() | |
self.state = None | |
self.result = None | |
def v2_runner_on_failed(self, result, ignore_errors=False): | |
self.state = 'failed' | |
self.result = result._result | |
def v2_runner_on_ok(self, result): | |
self.result = result._result | |
self.state = 'ok' | |
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): | |
def __init__(self, resource, loader, variable_manager, host_list=[]): | |
""" | |
resource的数据格式是一个列表字典,比如 | |
{ | |
"group1": { | |
"hosts": [{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...], | |
"vars": {"var1": value1, "var2": value2, ...} | |
} | |
} | |
如果你只传入1个列表,这默认该列表内的所有主机属于my_group组,比如 | |
[{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...] | |
""" | |
super(MyInventory, self).__init__(loader=loader, variable_manager=variable_manager, host_list=host_list) | |
self.resource = resource | |
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.items(): | |
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.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.iteritems(): | |
self.my_add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars")) | |
class Options(object): | |
""" | |
Options class to replace Ansible OptParser | |
""" | |
def __init__(self, verbosity=None, inventory=None, listhosts=None, subset=None, module_paths=None, extra_vars=None, | |
forks=None, ask_vault_pass=None, vault_password_files=None, new_vault_password_file=None, | |
output_file=None, tags=None, skip_tags=None, one_line=None, tree=None, ask_sudo_pass=None, ask_su_pass=None, | |
sudo=None, sudo_user=None, become=None, become_method=None, become_user=None, become_ask_pass=None, | |
ask_pass=None, private_key_file=None, remote_user=None, connection=None, timeout=None, ssh_common_args=None, | |
sftp_extra_args=None, scp_extra_args=None, ssh_extra_args=None, poll_interval=None, seconds=None, check=None, | |
syntax=None, diff=None, force_handlers=None, flush_cache=None, listtasks=None, listtags=None, module_path=None): | |
self.verbosity = verbosity | |
self.inventory = inventory | |
self.listhosts = listhosts | |
self.subset = subset | |
self.module_paths = module_paths | |
self.extra_vars = extra_vars | |
self.forks = forks | |
self.ask_vault_pass = ask_vault_pass | |
self.vault_password_files = vault_password_files | |
self.new_vault_password_file = new_vault_password_file | |
self.output_file = output_file | |
self.tags = tags | |
self.skip_tags = skip_tags | |
self.one_line = one_line | |
self.tree = tree | |
self.ask_sudo_pass = ask_sudo_pass | |
self.ask_su_pass = ask_su_pass | |
self.sudo = sudo | |
self.sudo_user = sudo_user | |
self.become = become | |
self.become_method = become_method | |
self.become_user = become_user | |
self.become_ask_pass = become_ask_pass | |
self.ask_pass = ask_pass | |
self.private_key_file = private_key_file | |
self.remote_user = remote_user | |
self.connection = connection | |
self.timeout = timeout | |
self.ssh_common_args = ssh_common_args | |
self.sftp_extra_args = sftp_extra_args | |
self.scp_extra_args = scp_extra_args | |
self.ssh_extra_args = ssh_extra_args | |
self.poll_interval = poll_interval | |
self.seconds = seconds | |
self.check = check | |
self.syntax = syntax | |
self.diff = diff | |
self.force_handlers = force_handlers | |
self.flush_cache = flush_cache | |
self.listtasks = listtasks | |
self.listtags = listtags | |
self.module_path = module_path | |
class Runner: | |
def __init__(self, resource): | |
self.options = Options() | |
self.options.connection = 'ssh' # Need a connection type "smart" or "ssh" | |
self.options.become = True | |
self.options.become_method = 'sudo' | |
self.options.become_user = 'root' | |
# Become Pass Needed if not logging in as user root (do not support now) | |
passwords = {'become_pass': ''} | |
# Gets data from YAML/JSON files | |
self.loader = DataLoader() | |
# All the variables from all the various places | |
self.variable_manager = VariableManager() | |
# Set inventory, using most of above objects | |
self.inventory = MyInventory(resource=resource, loader=self.loader, variable_manager=self.variable_manager) | |
self.variable_manager.set_inventory(self.inventory) | |
# set callback object | |
self.results_callback = CallbackModule() | |
# playbook | |
self.tqm = TaskQueueManager( | |
inventory=self.inventory, | |
variable_manager=self.variable_manager, | |
loader=self.loader, | |
options=self.options, | |
passwords=passwords, | |
stdout_callback=self.results_callback, | |
) | |
def run(self, module_name='shell', module_args='',): | |
play_source = dict( | |
name='Ansible Play', | |
hosts='*', | |
gather_facts='no', | |
tasks=[ | |
dict(action=dict(module=module_name, args=module_args)), | |
] | |
) | |
self.play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader) | |
try: | |
ret = self.tqm.run(self.play) | |
print(ret) | |
return ret, self.results_callback.result | |
finally: | |
self.tqm.cleanup() | |
if __name__ == '__main__': | |
res = [{ | |
'ssh_key': 'deepin.pem', | |
'username': 'deepin', | |
'ip': '10.10.120.114', | |
'hostname': 'payOrder-provider01', | |
'port': 16001, | |
'password': 'deepin' | |
}] | |
tqm = Runner(res) | |
ret, result = tqm.run(module_args='ls /') | |
print(json.dumps(result, indent=4)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment