Skip to content

Instantly share code, notes, and snippets.

@choldrim
Created March 3, 2017 10:22
Show Gist options
  • Save choldrim/3211f1660291f871739379082f204c83 to your computer and use it in GitHub Desktop.
Save choldrim/3211f1660291f871739379082f204c83 to your computer and use it in GitHub Desktop.
#!/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