diff --git a/scripts/common/myansible.py b/scripts/common/ansible.py similarity index 100% rename from scripts/common/myansible.py rename to scripts/common/ansible.py diff --git a/scripts/common/ansible/__init__.py b/scripts/common/ansible/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/scripts/common/ansible/ansible2.9.5.py b/scripts/common/ansible/ansible2.9.5.py deleted file mode 100644 index c312bc3..0000000 --- a/scripts/common/ansible/ansible2.9.5.py +++ /dev/null @@ -1,194 +0,0 @@ -import sys -import os -import json -import shutil -from ansible.module_utils.common.collections import ImmutableDict -from ansible.parsing.dataloader import DataLoader -from ansible.vars.manager import VariableManager -from ansible.inventory.manager import InventoryManager -from ansible.playbook.play import Play -from ansible.executor.task_queue_manager import TaskQueueManager -from ansible.plugins.callback import CallbackBase -from ansible import context -import ansible.constants as C - - -class ResultCallback(CallbackBase): - """ - 重写callbackBase类的部分方法 - """ - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.host_ok = {} - self.host_unreachable = {} - self.host_failed = {} - self.task_ok = {} - - def v2_runner_on_unreachable(self, result): - self.host_unreachable[result._host.get_name()] = result - - def v2_runner_on_ok(self, result, **kwargs): - self.host_ok[result._host.get_name()] = result - - def v2_runner_on_failed(self, result, **kwargs): - self.host_failed[result._host.get_name()] = result - - -class MyAnsiable2(): - def __init__(self, - connection='local', # 连接方式 local 本地方式,smart ssh方式 - remote_user=None, # ssh 用户 - remote_password=None, # ssh 用户的密码,应该是一个字典, key 必须是 conn_pass - private_key_file=None, # 指定自定义的私钥地址 - sudo=None, sudo_user=None, ask_sudo_pass=None, - module_path=None, # 模块路径,可以指定一个自定义模块的路径 - become=None, # 是否提权 - become_method=None, # 提权方式 默认 sudo 可以是 su - become_user=None, # 提权后,要成为的用户,并非登录用户 - check=False, diff=False, - listhosts=None, listtasks=None, listtags=None, - verbosity=3, - syntax=None, - start_at_task=None, - inventory=None): - - # 函数文档注释 - """ - 初始化函数,定义的默认的选项值, - 在初始化的时候可以传参,以便覆盖默认选项的值 - """ - context.CLIARGS = ImmutableDict( - connection=connection, - remote_user=remote_user, - private_key_file=private_key_file, - sudo=sudo, - sudo_user=sudo_user, - ask_sudo_pass=ask_sudo_pass, - module_path=module_path, - become=become, - become_method=become_method, - become_user=become_user, - verbosity=verbosity, - listhosts=listhosts, - listtasks=listtasks, - listtags=listtags, - syntax=syntax, - start_at_task=start_at_task, - ) - - # 三元表达式,假如没有传递 inventory, 就使用 "localhost," - # 指定 inventory 文件 - # inventory 的值可以是一个 资产清单文件 - # 也可以是一个包含主机的元组,这个仅仅适用于测试 - # 比如 : 1.1.1.1, # 如果只有一个 IP 最后必须有英文的逗号 - # 或者: 1.1.1.1, 2.2.2.2 - - self.inventory = inventory if inventory else "localhost," - - # 实例化数据解析器 - self.loader = DataLoader() - - # 实例化 资产配置对象 - self.inv_obj = InventoryManager( - loader=self.loader, sources=self.inventory) - - # 设置密码 - self.passwords = remote_password - - # 实例化回调插件对象 - self.results_callback = ResultCallback() - - # 变量管理器 - self.variable_manager = VariableManager(self.loader, self.inv_obj) - - def run(self, hosts='localhost', gether_facts="no", module="ping", args='', task_time=0): - """ - 参数说明: - task_time -- 执行异步任务时等待的秒数,这个需要大于 0 ,等于 0 的时候不支持异步(默认值)。这个值应该等于执行任务实际耗时时间为好 - """ - play_source = dict( - name="Ad-hoc", - hosts=hosts, - gather_facts=gether_facts, - tasks=[ - # 这里每个 task 就是这个列表中的一个元素,格式是嵌套的字典 - # 也可以作为参数传递过来,这里就简单化了。 - {"action": {"module": module, "args": args}, "async": task_time, "poll": 0}]) - - play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader) - - tqm = None - try: - tqm = TaskQueueManager( - inventory=self.inv_obj, - variable_manager=self.variable_manager, - loader=self.loader, - passwords=self.passwords, - stdout_callback=self.results_callback) - - result = tqm.run(play) - - finally: - if tqm is not None: - tqm.cleanup() - shutil.rmtree(C.DEFAULT_LOCAL_TMP, True) - - def playbook(self, playbooks, run_data): - """ - Keyword arguments: - playbooks -- 需要是一个列表类型 - """ - from ansible.executor.playbook_executor import PlaybookExecutor - self.variable_manager.extra_vars = run_data - playbook = PlaybookExecutor(playbooks=playbooks, - inventory=self.inv_obj, - variable_manager=self.variable_manager, - loader=self.loader, - passwords=self.passwords) - - # 使用回调函数 - playbook._tqm._stdout_callback = self.results_callback - - result = playbook.run() - - def get_result(self): - result_raw = {'success': {}, 'failed': {}, 'unreachable': {}} - - # print(self.results_callback.host_ok) - for host, result in self.results_callback.host_ok.items(): - result_raw['success'][host] = result._result - for host, result in self.results_callback.host_failed.items(): - result_raw['failed'][host] = result._result - for host, result in self.results_callback.host_unreachable.items(): - result_raw['unreachable'][host] = result._result - - # 最终打印结果,并且使用 JSON 继续格式化 - print(json.dumps(result_raw, indent=4)) - - return json.dumps(result_raw) - - -def test_run_cmd(): - hosts = "192.168.100.42" - ansible3 = MyAnsiable2( - inventory='hosts', connection='smart') # 创建资源库对象 - ansible3.run(hosts=hosts, module="shell", - args=' ps -ef |grep python') - stdout_dict = json.loads(ansible3.get_result()) - print(stdout_dict, type(stdout_dict)) - print(stdout_dict['success'][hosts]['stdout'], '######wc') - - -def test_run_playbook(): - ansible3 = MyAnsiable2( - inventory='hosts', connection='smart') - run_data = { - "dest_paths": "/data/apps/temp", - "source": "/root/temp/host", - "dest_filename": "/data/apps/temp/host.new" - } - ansible3.playbook(playbooks=['test.yml']) - stdout_dict = json.loads(ansible3.get_result()) - print(stdout_dict, type(stdout_dict)) - # print(stdout_dict['success']['192.168.0.94']['stdout']) diff --git a/scripts/common/ansible/ansible4.py b/scripts/common/ansible/ansible4.py deleted file mode 100644 index e346f10..0000000 --- a/scripts/common/ansible/ansible4.py +++ /dev/null @@ -1,137 +0,0 @@ -#!/usr/bin/env python -# pip3 install ansible -# pip3 install ansible_runner -# pip3 install ansible_inventory -# pip3 install ansible_playbook -# Ansible will require Python 3.8 or newer on the controller starting with Ansible 2.12 -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import json -import shutil - -import ansible.constants as C -from ansible.executor.task_queue_manager import TaskQueueManager -from ansible.module_utils.common.collections import ImmutableDict -from ansible.inventory.manager import InventoryManager -from ansible.parsing.dataloader import DataLoader -from ansible.playbook.play import Play -from ansible.plugins.callback import CallbackBase -from ansible.vars.manager import VariableManager -from ansible import context - - -# Create a callback plugin so we can capture the output -class ResultsCollectorJSONCallback(CallbackBase): - """A sample callback plugin used for performing an action as results come in. - - If you want to collect all results into a single object for processing at - the end of the execution, look into utilizing the ``json`` callback plugin - or writing your own custom callback plugin. - """ - - def __init__(self, *args, **kwargs): - super(ResultsCollectorJSONCallback, self).__init__(*args, **kwargs) - self.host_ok = {} - self.host_unreachable = {} - self.host_failed = {} - - def v2_runner_on_unreachable(self, result): - host = result._host - self.host_unreachable[host.get_name()] = result - - def v2_runner_on_ok(self, result, *args, **kwargs): - """Print a json representation of the result. - - Also, store the result in an instance attribute for retrieval later - """ - host = result._host - self.host_ok[host.get_name()] = result - print(json.dumps({host.name: result._result}, indent=4)) - - def v2_runner_on_failed(self, result, *args, **kwargs): - host = result._host - self.host_failed[host.get_name()] = result - - -def main(): - host_list = ['localhost', 'www.example.com', 'www.google.com'] - # since the API is constructed for CLI it expects certain options to always be set in the context object - context.CLIARGS = ImmutableDict(connection='smart', module_path=['/to/mymodules', '/usr/share/ansible'], forks=10, become=None, - become_method=None, become_user=None, check=False, diff=False) - # required for - # https://github.com/ansible/ansible/blob/devel/lib/ansible/inventory/manager.py#L204 - sources = ','.join(host_list) - if len(host_list) == 1: - sources += ',' - - # initialize needed objects - loader = DataLoader() # Takes care of finding and reading yaml, json and ini files - passwords = dict(vault_pass='secret') - - # Instantiate our ResultsCollectorJSONCallback for handling results as they come in. Ansible expects this to be one of its main display outlets - results_callback = ResultsCollectorJSONCallback() - - # create inventory, use path to host config file as source or hosts in a comma separated string - inventory = InventoryManager(loader=loader, sources=sources) - - # variable manager takes care of merging all the different sources to give you a unified view of variables available in each context - variable_manager = VariableManager(loader=loader, inventory=inventory) - - # instantiate task queue manager, which takes care of forking and setting up all objects to iterate over host list and tasks - # IMPORTANT: This also adds library dirs paths to the module loader - # IMPORTANT: and so it must be initialized before calling `Play.load()`. - tqm = TaskQueueManager( - inventory=inventory, - variable_manager=variable_manager, - loader=loader, - passwords=passwords, - # Use our custom callback instead of the ``default`` callback plugin, which prints to stdout - stdout_callback=results_callback, - ) - - # create data structure that represents our play, including tasks, this is basically what our YAML loader does internally. - play_source = dict( - name="Ansible Play", - hosts=host_list, - gather_facts='no', - tasks=[ - dict(action=dict(module='shell', args='ls'), register='shell_out'), - dict(action=dict(module='debug', args=dict( - msg='{{shell_out.stdout}}'))), - dict(action=dict(module='command', args=dict(cmd='/usr/bin/uptime'))), - ] - ) - - # Create play object, playbook objects use .load instead of init or new methods, - # this will also automatically create the task objects from the info provided in play_source - play = Play().load(play_source, variable_manager=variable_manager, loader=loader) - - # Actually run it - try: - # most interesting data for a play is actually sent to the callback's methods - result = tqm.run(play) - finally: - # we always need to cleanup child procs and the structures we use to communicate with them - tqm.cleanup() - if loader: - loader.cleanup_all_tmp_files() - - # Remove ansible tmpdir - shutil.rmtree(C.DEFAULT_LOCAL_TMP, True) - - print("UP ***********") - for host, result in results_callback.host_ok.items(): - print('{0} >>> {1}'.format(host, result._result['stdout'])) - - print("FAILED *******") - for host, result in results_callback.host_failed.items(): - print('{0} >>> {1}'.format(host, result._result['msg'])) - - print("DOWN *********") - for host, result in results_callback.host_unreachable.items(): - print('{0} >>> {1}'.format(host, result._result['msg'])) - - -if __name__ == '__main__': - main() diff --git a/scripts/common/ansible/mylog.py b/scripts/common/ansible/mylog.py deleted file mode 100644 index a251f70..0000000 --- a/scripts/common/ansible/mylog.py +++ /dev/null @@ -1,198 +0,0 @@ -from datetime import datetime -from ansible.plugins.callback import CallbackBase - -# A custom object to store to the database -from some_project.storage import Logs - - -class PlayLogger: - """Store log output in a single object. - We create a new object per Ansible run - """ - - def __init__(self): - self.log = '' - self.runtime = 0 - - def append(self, log_line): - """append to log""" - self.log += log_line+"\n\n" - - def banner(self, msg): - """Output Trailing Stars""" - width = 78 - len(msg) - if width < 3: - width = 3 - filler = "*" * width - return "\n%s %s " % (msg, filler) - - -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.logger = PlayLogger() - self.start_time = datetime.now() - - def v2_runner_on_failed(self, result, ignore_errors=False): - delegated_vars = result._result.get('_ansible_delegated_vars', None) - - # Catch an exception - # This may never be called because default handler deletes - # the exception, since Ansible thinks it knows better - if 'exception' in result._result: - # Extract the error message and log it - error = result._result['exception'].strip().split('\n')[-1] - self.logger.append(error) - - # Remove the exception from the result so it's not shown every time - del result._result['exception'] - - # Else log the reason for the failure - if result._task.loop and 'results' in result._result: - # item_on_failed, item_on_skipped, item_on_ok - self._process_items(result) - else: - if delegated_vars: - self.logger.append("fatal: [%s -> %s]: FAILED! => %s" % (result._host.get_name( - ), delegated_vars['ansible_host'], self._dump_results(result._result))) - else: - self.logger.append("fatal: [%s]: FAILED! => %s" % ( - result._host.get_name(), self._dump_results(result._result))) - - def v2_runner_on_ok(self, result): - self._clean_results(result._result, result._task.action) - delegated_vars = result._result.get('_ansible_delegated_vars', None) - if result._task.action == 'include': - return - elif result._result.get('changed', False): - if delegated_vars: - msg = "changed: [%s -> %s]" % (result._host.get_name(), - delegated_vars['ansible_host']) - else: - msg = "changed: [%s]" % result._host.get_name() - else: - if delegated_vars: - msg = "ok: [%s -> %s]" % (result._host.get_name(), - delegated_vars['ansible_host']) - else: - msg = "ok: [%s]" % result._host.get_name() - - if result._task.loop and 'results' in result._result: - # item_on_failed, item_on_skipped, item_on_ok - self._process_items(result) - else: - self.logger.append(msg) - - def v2_runner_on_skipped(self, result): - if result._task.loop and 'results' in result._result: - # item_on_failed, item_on_skipped, item_on_ok - self._process_items(result) - else: - msg = "skipping: [%s]" % result._host.get_name() - self.logger.append(msg) - - def v2_runner_on_unreachable(self, result): - delegated_vars = result._result.get('_ansible_delegated_vars', None) - if delegated_vars: - self.logger.append("fatal: [%s -> %s]: UNREACHABLE! => %s" % (result._host.get_name( - ), delegated_vars['ansible_host'], self._dump_results(result._result))) - else: - self.logger.append("fatal: [%s]: UNREACHABLE! => %s" % ( - result._host.get_name(), self._dump_results(result._result))) - - def v2_runner_on_no_hosts(self, task): - self.logger.append("skipping: no hosts matched") - - def v2_playbook_on_task_start(self, task, is_conditional): - self.logger.append("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 - - self.logger.append(msg) - - def v2_playbook_item_on_ok(self, result): - delegated_vars = result._result.get('_ansible_delegated_vars', None) - if result._task.action == 'include': - return - elif result._result.get('changed', False): - if delegated_vars: - msg = "changed: [%s -> %s]" % (result._host.get_name(), - delegated_vars['ansible_host']) - else: - msg = "changed: [%s]" % result._host.get_name() - else: - if delegated_vars: - msg = "ok: [%s -> %s]" % (result._host.get_name(), - delegated_vars['ansible_host']) - else: - msg = "ok: [%s]" % result._host.get_name() - - msg += " => (item=%s)" % (result._result['item']) - - self.logger.append(msg) - - def v2_playbook_item_on_failed(self, result): - delegated_vars = result._result.get('_ansible_delegated_vars', None) - if 'exception' in result._result: - # Extract the error message and log it - error = result._result['exception'].strip().split('\n')[-1] - self.logger.append(error) - - # Remove the exception from the result so it's not shown every time - del result._result['exception'] - - if delegated_vars: - self.logger.append("failed: [%s -> %s] => (item=%s) => %s" % (result._host.get_name( - ), delegated_vars['ansible_host'], result._result['item'], self._dump_results(result._result))) - else: - self.logger.append("failed: [%s] => (item=%s) => %s" % (result._host.get_name( - ), result._result['item'], self._dump_results(result._result))) - - def v2_playbook_item_on_skipped(self, result): - msg = "skipping: [%s] => (item=%s) " % ( - result._host.get_name(), result._result['item']) - self.logger.append(msg) - - def v2_playbook_on_stats(self, stats): - run_time = datetime.now() - self.start_time - # returns an int, unlike run_time.total_seconds() - self.logger.runtime = run_time.seconds - - 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']), - ) - - self.logger.append(msg) - - def record_logs(self, user_id, success=False): - """ - Special callback added to this callback plugin - Called by Runner objet - :param user_id: - :return: - """ - - log_storage = Logs() - return log_storage.save_log(user_id, self.logger.log, self.logger.runtime, success) diff --git a/scripts/common/ansible/run_playbook.py b/scripts/common/ansible/run_playbook.py deleted file mode 100644 index f8905b6..0000000 --- a/scripts/common/ansible/run_playbook.py +++ /dev/null @@ -1,23 +0,0 @@ -from .task import Runner -# You may want this to run as user root instead -# or make this an environmental variable, or -# a CLI prompt. Whatever you want! -become_user_password = 'foo-whatever' -run_data = { - "user_id": 12345, - 'foo': 'bar', - 'baz': 'cux-or-whatever-this-one-is' -} - - -runner = Runner(hostnames='192.168.10.233' - playbook='run.yaml', - private_key='/home/user/.ssh/id_whatever', - run_data=run_data, - become_pass=become_user_password, - verbosity=0) - - -stats = runner.run() - -# Maybe do something with stats here? If you want! diff --git a/scripts/common/ansible/task.py b/scripts/common/ansible/task.py deleted file mode 100644 index 06d358e..0000000 --- a/scripts/common/ansible/task.py +++ /dev/null @@ -1,159 +0,0 @@ -import os -from tempfile import NamedTemporaryFile -from ansible.inventory import Inventory -from ansible.vars import VariableManager -from ansible.parsing.dataloader import DataLoader -from ansible.executor import playbook_executor -from ansible.utils.display import Display - - -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(object): - - def __init__(self, hostnames, playbook, private_key_file, run_data, become_pass, verbosity=0): - - self.run_data = run_data - - self.options = Options() - self.options.private_key_file = private_key_file - self.options.verbosity = verbosity - 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' - - # Set global verbosity - self.display = Display() - self.display.verbosity = self.options.verbosity - # Executor appears to have it's own - # verbosity object/setting as well - playbook_executor.verbosity = self.options.verbosity - - # Become Pass Needed if not logging in as user root - passwords = {'become_pass': become_pass} - - # Gets data from YAML/JSON files - self.loader = DataLoader() - self.loader.set_vault_password(os.environ['VAULT_PASS']) - - # All the variables from all the various places - self.variable_manager = VariableManager() - self.variable_manager.extra_vars = self.run_data - - # Parse hosts, I haven't found a good way to - # pass hosts in without using a parsed template :( - # (Maybe you know how?) - self.hosts = NamedTemporaryFile(delete=False) - self.hosts.write("""[run_hosts] -%s -""" % hostnames) - self.hosts.close() - - # This was my attempt to pass in hosts directly. - # - # Also Note: In py2.7, "isinstance(foo, str)" is valid for - # latin chars only. Luckily, hostnames are - # ascii-only, which overlaps latin charset - ## if isinstance(hostnames, str): - ## hostnames = {"customers": {"hosts": [hostnames]}} - - # Set inventory, using most of above objects - self.inventory = Inventory( - loader=self.loader, variable_manager=self.variable_manager, host_list=self.hosts.name) - self.variable_manager.set_inventory(self.inventory) - - # Playbook to run. Assumes it is - # local to this python file - pb_dir = os.path.dirname(__file__) - playbook = "%s/%s" % (pb_dir, playbook) - - # Setup playbook executor, but don't run until run() called - self.pbex = playbook_executor.PlaybookExecutor( - playbooks=[playbook], - inventory=self.inventory, - variable_manager=self.variable_manager, - loader=self.loader, - options=self.options, - passwords=passwords) - - def run(self): - # Results of PlaybookExecutor - self.pbex.run() - stats = self.pbex._tqm._stats - - # Test if success for record_logs - run_success = True - hosts = sorted(stats.processed.keys()) - for h in hosts: - t = stats.summarize(h) - if t['unreachable'] > 0 or t['failures'] > 0: - run_success = False - - # Dirty hack to send callback to save logs with data we want - # Note that function "record_logs" is one I created and put into - # the playbook callback file - self.pbex._tqm.send_callback( - 'record_logs', - user_id=self.run_data['user_id'], - success=run_success - ) - - # Remove created temporary files - os.remove(self.hosts.name) - - return stats