Created
March 3, 2017 10:22
-
-
Save choldrim/3211f1660291f871739379082f204c83 to your computer and use it in GitHub Desktop.
Revisions
-
choldrim created this gist
Mar 3, 2017 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,261 @@ #!/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))