def execute_playbook(play_book, host_list=[]):
    host_list = host_list
    # 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=None,
                                    forks=None,
                                    become=None,
                                    become_method=None,
                                    become_user=None,
                                    check=False,
                                    diff=False)

    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='******')

    # Instantiate our ResultsCollectorJSONCallback for handling results as they come in. Ansible expects this to be one of its main display outlets
    results_callback = ResultsCollectorJSONCallback()

    inventory = InventoryManager(loader=loader, sources=sources)

    variable_manager = VariableManager(loader=loader, inventory=inventory)

    tqm = TaskQueueManager(
        inventory=inventory,
        variable_manager=variable_manager,
        loader=loader,
        passwords=passwords,
        stdout_callback=
        results_callback,  # Use our custom callback instead of the ``default`` callback plugin, which prints to stdout
    )

    pbex = PlaybookExecutor(playbooks=[play_book],
                            inventory=inventory,
                            variable_manager=variable_manager,
                            loader=loader,
                            passwords=passwords)
    playbook = Playbook.load(pbex._playbooks[0],
                             variable_manager=variable_manager,
                             loader=loader)
    play = playbook.get_plays()[0]

    # Actually run it
    try:
        result = tqm.run(
            play
        )  # most interesting data for a play is actually sent to the callback's methods
    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)
Exemple #2
0
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=['/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()
    passwords = dict()

    # create inventory and pass to var manager
    inventory = InventoryManager(loader=loader, sources=sources)
    variable_manager = VariableManager(loader=loader, inventory=inventory)

    # create play with tasks
    play_source = dict(
        name="Ansible Play",
        hosts=host_list,
        gather_facts='no',
        tasks=[dict(action=dict(module='command', args=dict(cmd='/usr/bin/uptime')))]
    )
    play = Play().load(play_source, variable_manager=variable_manager, loader=loader)

    # actually run it
    tqm = None
    callback = ResultsCollector()
    try:
        tqm = TaskQueueManager(
            inventory=inventory,
            variable_manager=variable_manager,
            loader=loader,
            passwords=passwords,
            stdout_callback=callback,
        )
        result = tqm.run(play)
    finally:
        if tqm is not None:
            tqm.cleanup()
        if loader:
            loader.cleanup_all_tmp_files()

    print("UP ***********")
    for host, result in callback.host_ok.items():
        print('{0} >>> {1}'.format(host, result._result['msg']))

    print("FAILED *******")
    for host, result in callback.host_failed.items():
        print('{0} >>> {1}'.format(host, result._result['msg']))

    print("DOWN *********")
    for host, result in callback.host_unreachable.items():
        print('{0} >>> {1}'.format(host, result._result['msg']))
class PlaybookRunner():
    def __init__(
        self,
        playbook_files=['./site.yml'],
        inventory_sources=['hosts.sh'],
        vault_password=None,
    ):
        self.playbook_files = playbook_files
        self.inventory_sources = inventory_sources
        self.vault_password = vault_password
        self.loader = DataLoader()
        self.inventory = InventoryManager(loader=self.loader,
                                          sources=self.inventory_sources)
        self.results_callback = ResultsCallback()
        self.variable_manager = VariableManager(loader=self.loader,
                                                inventory=self.inventory)

    def run(self):
        try:
            pbex = PlaybookExecutor(
                inventory=self.inventory,
                loader=self.loader,
                passwords={'vault_password': self.vault_password},
                playbooks=self.playbook_files,
                variable_manager=self.variable_manager,
            )

            tqm = pbex._tqm
            tqm._stdout_callback = self.results_callback

            pbex.run()

            # if tqm and hasattr(tqm, 'send_callback'):
            #   tqm.send_callback('playbook_on_exception', exception=e)

        finally:

            # if hasattr(self.results_callback, 'results'):
            #   print(json.dumps({
            #     'results': self.results_callback.results
            #   }, indent=2))

            if tqm is not None:
                tqm.cleanup()

            if self.loader is not None:
                self.loader.cleanup_all_tmp_files()

            shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
Exemple #4
0
    def run_cmd(self):

        passwords = {
            'conn_pass': "******",
            'become_pass': "******"
        }

        loader = DataLoader()

        variable_manager = VariableManager()
        variable_manager.extra_vars = load_extra_vars(loader=loader,
                                                      options=self.pb_options)
        variable_manager.options_vars = load_options_vars(self.pb_options)

        inventory = Inventory(loader=loader,
                              variable_manager=variable_manager,
                              host_list=self.pb_options.inventory)
        variable_manager.set_inventory(inventory)

        play_ds = self._play_ds(self.pb_options.name, self.pb_options.pattern)
        play = Play().load(play_ds,
                           variable_manager=variable_manager,
                           loader=loader)

        self._tqm = None
        try:
            self._tqm = TaskQueueManager(
                inventory=inventory,
                variable_manager=variable_manager,
                loader=loader,
                options=self.pb_options,
                passwords=passwords,
                # stdout_callback=CallbackWrap(),
            )

            rc = self._tqm.run(play)
            detail = json.loads(self._tqm._stdout_callback._dump_results)
            print("json.loads.self._tqm._stdout_callback._dump_results")
            print(json.loads(self._tqm._stdout_callback._dump_results))
            print("self._tqm._stdout_callback dir")
            print(dir(self._tqm._stdout_callback))
        finally:
            if self._tqm:
                self._tqm.cleanup()
            if loader:
                loader.cleanup_all_tmp_files()

        return {'rc': rc, 'detail': detail}
Exemple #5
0
class AdHocRunner(object):
    """
    ADHoc接口
    """
    Options = namedtuple("Options", [
        'connection', 'module_path', 'private_key_file', "remote_user",
        'timeout', 'forks', 'become', 'become_method', 'become_user',
        'check', 'extra_vars',
        ]
    )

    results_callback_class = AdHocResultCallback

    def __init__(self,
                 hosts=C.DEFAULT_HOST_LIST,
                 forks=C.DEFAULT_FORKS,  # 5
                 timeout=C.DEFAULT_TIMEOUT,  # SSH timeout = 10s
                 remote_user=C.DEFAULT_REMOTE_USER,  # root
                 module_path=None,  # dirs of custome modules
                 connection_type="smart",
                 become=None,
                 become_method=None,
                 become_user=None,
                 check=False,
                 passwords=None,
                 extra_vars=None,
                 private_key_file=None,
                 gather_facts='no'):

        self.pattern = ''
        self.variable_manager = VariableManager()
        self.loader = DataLoader()
        self.gather_facts = gather_facts
        self.results_callback = AdHocRunner.results_callback_class()
        self.options = self.Options(
            connection=connection_type,
            timeout=timeout,
            module_path=module_path,
            forks=forks,
            become=become,
            become_method=become_method,
            become_user=become_user,
            check=check,
            remote_user=remote_user,
            extra_vars=extra_vars or [],
            private_key_file=private_key_file,
        )

        self.variable_manager.extra_vars = load_extra_vars(self.loader,
                                                           options=self.options)
        self.variable_manager.options_vars = load_options_vars(self.options)
        self.passwords = passwords or {}
        self.inventory = JMSInventory(hosts)
        self.variable_manager.set_inventory(self.inventory)
        self.tasks = []
        self.play_source = None
        self.play = None
        self.runner = None

    @staticmethod
    def check_module_args(module_name, module_args=''):
        if module_name in C.MODULE_REQUIRE_ARGS and not module_args:
            err = "No argument passed to '%s' module." % module_name
            print(err)
            return False
        return True

    def run(self, task_tuple, pattern='all', task_name='Ansible Ad-hoc'):
        """
        :param task_tuple:  (('shell', 'ls'), ('ping', ''))
        :param pattern:
        :param task_name:
        :return:
        """
        for module, args in task_tuple:
            if not self.check_module_args(module, args):
                return
            self.tasks.append(
                dict(action=dict(
                    module=module,
                    args=args,
                ))
            )

        self.play_source = dict(
            name=task_name,
            hosts=pattern,
            gather_facts=self.gather_facts,
            tasks=self.tasks
        )

        self.play = Play().load(
            self.play_source,
            variable_manager=self.variable_manager,
            loader=self.loader,
        )

        self.runner = TaskQueueManager(
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            passwords=self.passwords,
            stdout_callback=self.results_callback,
        )

        if not self.inventory.list_hosts("all"):
            raise AnsibleError("Inventory is empty.")

        if not self.inventory.list_hosts(self.pattern):
            raise AnsibleError(
                "pattern: %s  dose not match any hosts." % self.pattern)

        try:
            self.runner.run(self.play)
        except Exception as e:
            logger.warning(e)
        else:
            #logger.debug(self.results_callback.result_q)
            return self.results_callback.result_q
        finally:
            if self.runner:
                self.runner.cleanup()
            if self.loader:
                self.loader.cleanup_all_tmp_files()

    def clean_result(self):
        """
        :return: {
            "success": ['hostname',],
            "failed": [('hostname', 'msg'), {}],
        }
        """
        result = {'success': [], 'failed': []}
        for host in self.results_callback.result_q['contacted']:
            result['success'].append(host)

        for host, msgs in self.results_callback.result_q['dark'].items():
            msg = '\n'.join(['{} {}: {}'.format(
                msg.get('module_stdout', ''),
                msg.get('invocation', {}).get('module_name'),
                msg.get('msg', '')) for msg in msgs])
            result['failed'].append((host, msg))
        return result
Exemple #6
0
class AdHocRunner:
    """
    ADHoc Runner接口
    """
    results_callback_class = AdHocResultCallback
    loader_class = DataLoader
    variable_manager_class = VariableManager
    options = get_default_options()
    default_options = get_default_options()

    def __init__(self, inventory, options=None):
        if options:
            self.options = options
        self.inventory = inventory
        self.loader = DataLoader()
        self.variable_manager = VariableManager(loader=self.loader,
                                                inventory=self.inventory)

    @staticmethod
    def check_module_args(module_name, module_args=''):
        if module_name in C.MODULE_REQUIRE_ARGS and not module_args:
            err = "No argument passed to '%s' module." % module_name
            raise AnsibleError(err)

    def check_pattern(self, pattern):
        if not pattern:
            raise AnsibleError("Pattern `{}` is not valid!".format(pattern))
        if not self.inventory.list_hosts("all"):
            raise AnsibleError("Inventory is empty.")
        if not self.inventory.list_hosts(pattern):
            raise AnsibleError("pattern: %s  dose not match any hosts." %
                               pattern)

    def clean_tasks(self, tasks):
        cleaned_tasks = []
        for task in tasks:
            self.check_module_args(task['action']['module'],
                                   task['action'].get('args'))
            cleaned_tasks.append(task)
        return cleaned_tasks

    def set_option(self, k, v):
        kwargs = {k: v}
        self.options = self.options._replace(**kwargs)

    def run(
        self,
        tasks,
        pattern,
        play_name='Ansible Ad-hoc',
        gather_facts='no',
    ):
        """
        :param gather_facts:
        :param tasks: [{'action': {'module': 'shell', 'args': 'ls'}, ...}, ]
        :param pattern: all, *, or others
        :param play_name: The play name
        :return:
        """
        self.check_pattern(pattern)
        results_callback = self.results_callback_class()
        cleaned_tasks = self.clean_tasks(tasks)

        play_source = dict(name=play_name,
                           hosts=pattern,
                           gather_facts=gather_facts,
                           tasks=cleaned_tasks)

        play = Play().load(
            play_source,
            variable_manager=self.variable_manager,
            loader=self.loader,
        )

        tqm = TaskQueueManager(
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            stdout_callback=results_callback,
            passwords=self.options.passwords,
        )

        try:
            tqm.run(play)
            return results_callback
        except Exception as e:
            raise AnsibleError(e)
        finally:
            tqm.cleanup()
            self.loader.cleanup_all_tmp_files()
Exemple #7
0
class AdHocRunner(object):
    """
    ADHoc接口
    """
    Options = namedtuple("Options", [
        'connection',
        'module_path',
        'private_key_file',
        "remote_user",
        'timeout',
        'forks',
        'become',
        'become_method',
        'become_user',
        'check',
        'extra_vars',
    ])

    results_callback_class = AdHocResultCallback

    def __init__(
            self,
            hosts=C.DEFAULT_HOST_LIST,
            forks=C.DEFAULT_FORKS,  # 5
            timeout=C.DEFAULT_TIMEOUT,  # SSH timeout = 10s
            remote_user=C.DEFAULT_REMOTE_USER,  # root
            module_path=None,  # dirs of custome modules
            connection_type="smart",
            become=None,
            become_method=None,
            become_user=None,
            check=False,
            passwords=None,
            extra_vars=None,
            private_key_file=None,
            gather_facts='no'):

        self.pattern = ''
        self.variable_manager = VariableManager()
        self.loader = DataLoader()
        self.gather_facts = gather_facts
        self.results_callback = AdHocRunner.results_callback_class()
        self.options = self.Options(
            connection=connection_type,
            timeout=timeout,
            module_path=module_path,
            forks=forks,
            become=become,
            become_method=become_method,
            become_user=become_user,
            check=check,
            remote_user=remote_user,
            extra_vars=extra_vars or [],
            private_key_file=private_key_file,
        )

        self.variable_manager.extra_vars = load_extra_vars(
            self.loader, options=self.options)
        self.variable_manager.options_vars = load_options_vars(self.options)
        self.passwords = passwords or {}
        self.inventory = JMSInventory(hosts)
        self.variable_manager.set_inventory(self.inventory)
        self.tasks = []
        self.play_source = None
        self.play = None
        self.runner = None

    @staticmethod
    def check_module_args(module_name, module_args=''):
        if module_name in C.MODULE_REQUIRE_ARGS and not module_args:
            err = "No argument passed to '%s' module." % module_name
            print(err)
            return False
        return True

    def run(self, task_tuple, pattern='all', task_name='Ansible Ad-hoc'):
        """
        :param task_tuple:  (('shell', 'ls'), ('ping', ''))
        :param pattern:
        :param task_name:
        :return:
        """
        for module, args in task_tuple:
            if not self.check_module_args(module, args):
                return
            self.tasks.append(dict(action=dict(
                module=module,
                args=args,
            )))

        self.play_source = dict(name=task_name,
                                hosts=pattern,
                                gather_facts=self.gather_facts,
                                tasks=self.tasks)

        self.play = Play().load(
            self.play_source,
            variable_manager=self.variable_manager,
            loader=self.loader,
        )

        self.runner = TaskQueueManager(
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            passwords=self.passwords,
            stdout_callback=self.results_callback,
        )

        if not self.inventory.list_hosts("all"):
            raise AnsibleError("Inventory is empty.")

        if not self.inventory.list_hosts(self.pattern):
            raise AnsibleError("pattern: %s  dose not match any hosts." %
                               self.pattern)

        try:
            self.runner.run(self.play)
        except Exception as e:
            logger.warning(e)
        else:
            #logger.debug(self.results_callback.result_q)
            return self.results_callback.result_q
        finally:
            if self.runner:
                self.runner.cleanup()
            if self.loader:
                self.loader.cleanup_all_tmp_files()

    def clean_result(self):
        """
        :return: {
            "success": ['hostname',],
            "failed": [('hostname', 'msg'), {}],
        }
        """
        result = {'success': [], 'failed': []}
        for host in self.results_callback.result_q['contacted']:
            result['success'].append(host)

        for host, msgs in self.results_callback.result_q['dark'].items():
            msg = '\n'.join([
                '{} {}: {}'.format(
                    msg.get('module_stdout', ''),
                    msg.get('invocation', {}).get('module_name'),
                    msg.get('msg', '')) for msg in msgs
            ])
            result['failed'].append((host, msg))
        return result
Exemple #8
0
class AdHocRunner:
    """
    ADHoc Runner接口
    """
    results_callback_class = AdHocResultCallback
    results_callback = None
    loader_class = DataLoader
    variable_manager_class = VariableManager
    default_options = get_default_options()
    command_modules_choices = ('shell', 'raw', 'command', 'script', 'win_shell')

    def __init__(self, inventory, options=None):
        self.options = self.update_options(options)
        self.inventory = inventory
        self.loader = DataLoader()
        self.variable_manager = VariableManager(
            loader=self.loader, inventory=self.inventory
        )

    def get_result_callback(self, file_obj=None):
        return self.__class__.results_callback_class()

    @staticmethod
    def check_module_args(module_name, module_args=''):
        if module_name in C.MODULE_REQUIRE_ARGS and not module_args:
            err = "No argument passed to '%s' module." % module_name
            raise AnsibleError(err)

    def check_pattern(self, pattern):
        if not pattern:
            raise AnsibleError("Pattern `{}` is not valid!".format(pattern))
        if not self.inventory.list_hosts("all"):
            raise AnsibleError("Inventory is empty.")
        if not self.inventory.list_hosts(pattern):
            raise AnsibleError(
                "pattern: %s  dose not match any hosts." % pattern
            )

    def clean_args(self, module, args):
        if not args:
            return ''
        if module not in self.command_modules_choices:
            return args
        if isinstance(args, str):
            if args.startswith('executable='):
                _args = args.split(' ')
                executable, command = _args[0].split('=')[1], ' '.join(_args[1:])
                args = {'executable': executable, '_raw_params':  command}
            else:
                args = {'_raw_params':  args}
            return args
        else:
            return args

    def clean_tasks(self, tasks):
        cleaned_tasks = []
        for task in tasks:
            module = task['action']['module']
            args = task['action'].get('args')
            cleaned_args = self.clean_args(module, args)
            task['action']['args'] = cleaned_args
            self.check_module_args(module, cleaned_args)
            cleaned_tasks.append(task)
        return cleaned_tasks

    def update_options(self, options):
        if options and isinstance(options, dict):
            options = self.__class__.default_options._replace(**options)
        else:
            options = self.__class__.default_options
        return options

    def run(self, tasks, pattern, play_name='Ansible Ad-hoc', gather_facts='no'):
        """
        :param tasks: [{'action': {'module': 'shell', 'args': 'ls'}, ...}, ]
        :param pattern: all, *, or others
        :param play_name: The play name
        :param gather_facts:
        :return:
        """
        self.check_pattern(pattern)
        self.results_callback = self.get_result_callback()
        cleaned_tasks = self.clean_tasks(tasks)

        play_source = dict(
            name=play_name,
            hosts=pattern,
            gather_facts=gather_facts,
            tasks=cleaned_tasks
        )

        play = Play().load(
            play_source,
            variable_manager=self.variable_manager,
            loader=self.loader,
        )

        tqm = TaskQueueManager(
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            stdout_callback=self.results_callback,
            passwords=self.options.passwords,
        )
        try:
            tqm.run(play)
            return self.results_callback
        except Exception as e:
            raise AnsibleError(e)
        finally:
            tqm.cleanup()
            self.loader.cleanup_all_tmp_files()
Exemple #9
0
    def run(self):
        """Run the Application"""

        # 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=[get_path("./modules"), "/usr/share/ansible"],
            forks=10,
            become=None,
            become_method=None,
            become_user=None,
            check=False,
            diff=False,
            verbosity=3,
        )

        # Initialize needed objects
        loader = DataLoader(
        )  # Takes care of finding and reading yaml, json and
        # ini files
        passwords = dict(vault_pass="******")

        # Instantiate our ResultCallback for handling results as they come in
        if self.args.measurement:
            results_callback = MeasurementsResultCallback(
                plugins=self._plugins)
        else:
            results_callback = ResultCallback(plugins=self._plugins)

        # Create inventory, use path to host config file as source or hosts in a
        # comma separated string
        inventory = InventoryManager(loader=loader, sources=self._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,
            stdout_callback=
            results_callback,  # Use our custom callback instead of
            # the ``default`` callback plugin,
            # which prints to stdout
        )

        # 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="all",
            gather_facts="yes",
            tasks=self.playbook_tasks(),
        )

        # 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:
            tqm.load_callbacks()
            tqm.run(play)
            tqm.send_callback(
                "v2_playbook_on_stats",
                tqm._stats,  # pylint: disable=protected-access
            )
        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)  # pylint: disable=no-member

            if tqm is not None:
                tqm.cleanup()
Exemple #10
0
class YoRunner(object):
    Options = namedtuple("Options", [
        'connection',
        'module_path',
        'private_key_file',
        "remote_user",
        'timeout',
        'forks',
        'become',
        'become_method',
        'become_user',
        'check',
        'extra_vars',
    ])

    def __init__(
            self,
            hosts=C.DEFAULT_HOST_LIST,
            forks=C.DEFAULT_FORKS,  # 5
            timeout=C.DEFAULT_TIMEOUT,  # SSH timeout = 10s
            remote_user=C.DEFAULT_REMOTE_USER,  # root
            module_path=None,  # dirs of custome modules
            connection_type="smart",
            become=None,
            become_method=None,
            become_user=None,
            check=False,
            passwords=None,
            extra_vars=None,
            private_key_file=None,
            gather_facts='no'):
        self.pattern = ''
        self.variable_manager = VariableManager()
        self.loader = DataLoader()
        self.gather_facts = gather_facts
        self.options = self.Options(
            connection=connection_type,
            timeout=timeout,
            module_path=module_path,
            forks=forks,
            become=become,
            become_method=become_method,
            become_user=become_user,
            check=check,
            remote_user=remote_user,
            extra_vars=extra_vars or [],
            private_key_file=private_key_file,
        )
        # self.variable_manager.extra_vars = load_extra_vars(self.loader,
        #                                                    options=self.options)
        self.variable_manager.extra_vars = extra_vars
        self.variable_manager.options_vars = load_options_vars(self.options)
        self.passwords = passwords or {}
        self.inventory = YoInventory(hosts)
        self.variable_manager.set_inventory(self.inventory)
        self.tasks = []
        self.play_source = None
        self.play = None
        self.runner = None
        self.timestamp = str(time.time())
        self.filename = FILENAME % (self.timestamp, '')
        self.have_script = 0

    def set_callback(self, callback):
        self.results_callback = callback

    @staticmethod
    def check_module_args(module_name, module_args=''):
        if module_name in C.MODULE_REQUIRE_ARGS and not module_args:
            err = "No argument passed to '%s' module." % module_name
            print(err)
            return False
        return True

    def task_add(self, task_tuple):
        for task in task_tuple:
            if not self.check_module_args(task.module, task.args):
                return
            if task.module == u'script':
                self.have_script = 1
                script = Script.objects.filter(id=task.args)
                if os.path.exists(self.filename):
                    os.remove(self.filename)
                script_name = FILENAME % (self.timestamp,
                                          '-' + str(script.get().id))
                output = open(script_name, 'w')
                output.writelines(script.get().formatScript())
                output.close()
            if self.have_script == 1:
                self.tasks.append(
                    dict(action=dict(
                        module=task.module,
                        args=script_name,
                    )))
            else:
                self.tasks.append(
                    dict(action=dict(
                        module=task.module,
                        args=task.args,
                    )))

    def run(
        self,
        task_tuple,
    ):  # pattern='all'):
        """
        :param task_tuple:  (('shell', 'ls'), ('ping', ''))
        :param pattern:
        :param timestamp:
        :return:
        """
        self.task_add(task_tuple)

        self.play_source = dict(name=self.timestamp,
                                hosts='all',
                                gather_facts=self.gather_facts,
                                tasks=self.tasks)

        self.play = Play().load(
            self.play_source,
            variable_manager=self.variable_manager,
            loader=self.loader,
        )

        self.runner = TaskQueueManager(
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            passwords=self.passwords,
            stdout_callback=self.results_callback,
        )

        # if not self.inventory.list_hosts("all"):
        #     raise AnsibleError("Inventory is empty.")
        #
        # if not self.inventory.list_hosts(self.pattern):
        #     raise AnsibleError(
        #         "pattern: %s  dose not match any hosts." % self.pattern)

        try:
            self.runner.run(self.play)
        finally:
            if self.runner:
                self.runner.cleanup()
            if self.loader:
                self.loader.cleanup_all_tmp_files()
            if self.have_script:
                self.cleanup_script()

    def cleanup_script(self):
        # if os.path.exists(self.filename):
        #     os.remove(self.filename)
        # return self.filename
        for name in glob.glob(self.filename + '*'):
            if os.path.exists(name):
                print(name)
                os.remove(name)
        inventory=inventory,
        variable_manager=variable_manager,
        loader=loader,
        passwords=passwords,
        stdout_callback=results_callback,  # Use our custom callback instead of the ``default`` callback plugin, which prints to stdout
    )


    # Actually run it
    try:
        result = tqm.run(play)  # most interesting data for a play is actually sent to the callback's methods
    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()

    # play_source = []
    # with open("./mysql.yml") as f:
    #     data = yaml.load(f, yaml.SafeLoader)
    #     if isinstance(data, list):
    #         play_source.extend(data)
    #     else:
    #         play_source.append(data)

    # for play_book in play_source:
    #     play = Play().load(play_book, variable_manager=variable_manager, loader=loader)
    #     results_callback = ResultCallback()
    #     tqm = None
    #     try:
    #         tqm = TaskQueueManager(
class AnsibleTask:
    def __init__(self, hosts=None, extra_vars=None):
        self.hosts = hosts
        self.__validate()
        self.hosts_file = None
        self.__generate_hosts_file()
        Options = namedtuple('Options', [
            'connection', 'module_path',
            'forks', 'become',
            'become_method', 'become_user',
            'check', 'diff',
            'host_key_checking', 'listhosts',
            'listtasks', 'listtags', 'syntax'
        ])
        self.options = Options(
            connection='ssh',
            module_path=None,
            forks=10,
            become=None,
            become_method=None,
            become_user=None,
            check=False,
            diff=False,
            host_key_checking=False,
            listhosts=None,
            listtasks=None,
            listtags=None,
            syntax=None
        )
        self.loader = DataLoader()
        self.passwords = dict(vault_pass='******')
        self.inventory = InventoryManager(loader=self.loader, sources=[self.hosts_file])
        self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory)
        self.results_callback = AnsibleTaskResultCallback()
        # 结果对象
        self.results_raw = {'success': {}, 'failed': {}, 'unreachable': {}}

        if extra_vars:
            self.variable_manager.extra_vars = extra_vars

    # 用于读取host 文件的,一般用不到
    def __generate_hosts_file(self):
        self.hosts_file = tempfile.mktemp()
        with open(self.hosts_file, 'w+', encoding='utf-8') as file:
            hosts = []
            for host in self.hosts:
                hosts.append(f'{host.host} {str(host)}')
            file.write('\n'.join(hosts))

    def __validate(self):
        assert self.hosts, 'hosts不能为空'
        assert isinstance(self.hosts, list), 'hosts 应为 list'
        for host in self.hosts:
            assert isinstance(host, AnsibleHost), 'host 类型必须为 AnsibleHost'

    def exec_run(self, module_name, module_args=None):
        play_source = dict(
            name="Ops Ansible Play",
            hosts='all',
            gather_facts='no',
            tasks=[dict(action=dict(module=module_name, args=module_args))] if module_args
            else [dict(action=dict(module=module_name))]
        )

        play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader)
        self.results_callback = AnsibleTaskResultCallback()
        tqm = None
        try:
            tqm = TaskQueueManager(
                inventory=self.inventory,
                variable_manager=self.variable_manager,
                loader=self.loader,
                options=self.options,
                passwords=self.passwords,
                stdout_callback=self.results_callback
            )
            tqm.run(play)
        except Exception as e:
            raise e
        finally:
            tqm.cleanup()
            self.loader.cleanup_all_tmp_files()

    def exec_playbook(self, playbooks):

        playbook = PlaybookExecutor(
            playbooks=playbooks,
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            passwords=self.passwords
        )
        setattr(getattr(playbook, '_tqm'), '_stdout_callback', self.results_callback)
        playbook.run()
        playbook._tqm.cleanup()

    @property
    def get_result(self):
        for host, result in self.results_callback.host_ok.items():
            self.results_raw['success'][host] = (
                result._result,
                {'code': 0}
            )

        for host, result in self.results_callback.host_failed.items():
            self.results_raw['failed'][host] = (
                result._result,
                {'code': 1}
            )

        for host, result in self.results_callback.host_unreachable.items():
            self.results_raw['unreachable'][host] = (
                result._result,
                {'code': 1}
            )

        return self.results_raw

    # __del__ 被称为析构方法,在程序执行完后,python垃圾回收器,会自动执行
    def __del__(self):
        if self.hosts_file:
            os.remove(self.hosts_file)
Exemple #13
0
class CopyAdHocRunner:
    """
    ADHoc Runner接口
    """
    results_callback_class = AdHocResultCallback
    loader_class = DataLoader
    variable_manager_class = VariableManager
    options = get_default_options()
    default_options = get_default_options()

    def __init__(self, inventory, options=None):
        if options:
            self.options = options
        self.inventory = inventory
        self.loader = DataLoader()
        self.variable_manager = VariableManager(loader=self.loader,
                                                inventory=self.inventory)

    def set_option(self, k, v):
        kwargs = {k: v}
        self.options = self.options._replace(**kwargs)

    def run(self,
            tasks,
            pattern,
            play_name='Ansible Ad-hoc',
            gather_facts='no'):
        """
        :param tasks: [{'action': {'module': 'shell', 'args': 'ls'}, ...}, ]
        :param pattern: all, *, or others
        :param play_name: The play name
        :return:
        """
        results_callback = self.results_callback_class()

        play_source = dict(name=play_name,
                           hosts=pattern,
                           gather_facts=gather_facts,
                           tasks=tasks)

        play = Play().load(
            play_source,
            variable_manager=self.variable_manager,
            loader=self.loader,
        )

        tqm = TaskQueueManager(
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            stdout_callback=results_callback,
            passwords=self.options.passwords,
        )
        logger.debug("Get inventory matched hosts: {}".format(
            self.inventory.get_matched_hosts(pattern)))

        try:
            tqm.run(play)
            return results_callback
        except Exception as e:
            raise AnsibleError(e)
        finally:
            tqm.cleanup()
            self.loader.cleanup_all_tmp_files()
Exemple #14
0
class AdHocRunner:
    results_callback_class = ResultCallback

    # results_callback = None
    # loader_class = DataLoader
    # variable_manager_class = VariableManager
    # default_options = get_default_options()

    def __init__(self, inventory):
        self.options = get_default_options()
        self.loader = DataLoader()
        self.inventory = InventoryManager(loader=self.loader,
                                          sources=['/etc/ansible/hosts'])
        self.variable_manager = VariableManager(loader=self.loader,
                                                inventory=self.inventory)

    def get_result_callback(self, file_obj=None):
        return self.__class__.results_callback_class(file_obj=file_obj)

    def run(self,
            tasks,
            pattern,
            play_name='Ansible Ad-hoc',
            gather_facts='no',
            file_obj=None):
        self.results_callback = self.get_result_callback(file_obj)
        play_source = dict(name=play_name,
                           hosts=pattern,
                           gather_facts=gather_facts,
                           tasks=tasks)

        play = Play().load(
            play_source,
            variable_manager=self.variable_manager,
            loader=self.loader,
        )

        tqm = TaskQueueManager(
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            stdout_callback=self.results_callback,
            passwords=self.options.passwords,
        )

        try:
            result = tqm.run(play)
            # return self.results_callback
        except Exception as e:
            raise AnsibleError(e)
        finally:
            tqm.cleanup()
            self.loader.cleanup_all_tmp_files()

        results_raw = {}
        results_raw['success'] = {}
        results_raw['failed'] = {}
        results_raw['unreachable'] = {}

        for host, result in self.results_callback.host_ok.items():
            results_raw['success'][host] = json.dumps(result._result)

        for host, result in self.results_callback.host_failed.items():
            results_raw['failed'][host] = result._result['msg']

        for host, result in self.results_callback.host_unreachable.items():
            results_raw['unreachable'][host] = result._result['msg']

        print(results_raw)
Exemple #15
0
class AnsibleRunner(object):
    def __init__(self,
                 hosts=C.DEFAULT_HOST_LIST,
                 module_name=C.DEFAULT_MODULE_NAME,
                 module_args=C.DEFAULT_MODULE_ARGS,
                 forks=C.DEFAULT_FORKS,
                 timeout=C.DEFAULT_TIMEOUT,
                 pattern="all",
                 remote_user=C.DEFAULT_REMOTE_USER,
                 module_path=None,
                 connection_type="smart",
                 become=None,
                 become_method=None,
                 become_user=None,
                 check=False,
                 passwords=None,
                 extra_vars=None,
                 private_key_file=None,
                 listtags=False,
                 listtasks=False,
                 listhosts=False,
                 ssh_common_args=None,
                 ssh_extra_args=None,
                 sftp_extra_args=None,
                 scp_extra_args=None,
                 verbosity=None,
                 syntax=False,
                 redisKey=None,
                 logId=None):
        self.Options = namedtuple("Options", [
            'listtags', 'listtasks', 'listhosts', 'syntax', 'connection',
            'module_path', 'forks', 'remote_user', 'private_key_file',
            'timeout', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args',
            'scp_extra_args', 'become', 'become_method', 'become_user',
            'verbosity', 'check', 'extra_vars', 'diff'
        ])
        self.results_raw = {}
        self.pattern = pattern
        self.module_name = module_name
        self.module_args = module_args
        self.gather_facts = 'no'
        self.options = self.Options(listtags=listtags,
                                    listtasks=listtasks,
                                    listhosts=listhosts,
                                    syntax=syntax,
                                    timeout=timeout,
                                    connection=connection_type,
                                    module_path=module_path,
                                    forks=forks,
                                    remote_user=remote_user,
                                    private_key_file=private_key_file,
                                    ssh_common_args=ssh_common_args or "",
                                    ssh_extra_args=ssh_extra_args or "",
                                    sftp_extra_args=sftp_extra_args,
                                    scp_extra_args=scp_extra_args,
                                    become=become,
                                    become_method=become_method,
                                    become_user=become_user,
                                    verbosity=verbosity,
                                    extra_vars=extra_vars or [],
                                    check=check,
                                    diff=False)
        self.redisKey = redisKey
        self.logId = logId
        self.loader = DataLoader()
        self.inventory = CustomInventory(resource=hosts)
        self.variable_manager = VariableManager(self.loader, self.inventory)
        self.variable_manager.extra_vars = load_extra_vars(
            loader=self.loader, options=self.options)
        self.variable_manager.options_vars = load_options_vars(
            self.options, "")
        self.passwords = passwords or {}

    def run_module(self, host_list, module_name, module_args):
        """
        :param host_list: ßß
        :param module_name: ansible 模块名称 (-m)
        :param module_args: ansible 模块参数 (-a)
        :return:
        """
        self.callback = ModuleResultsCollector()
        play_source = dict(
            name="Ansible Ad-hoc",
            hosts=host_list,
            gather_facts=self.gather_facts,
            tasks=[dict(action=dict(module=module_name, args=module_args))])
        play = Play().load(play_source,
                           loader=self.loader,
                           variable_manager=self.variable_manager)
        tqm = None
        try:
            tqm = TaskQueueManager(inventory=self.inventory,
                                   variable_manager=self.variable_manager,
                                   loader=self.loader,
                                   options=self.options,
                                   passwords=self.passwords,
                                   stdout_callback=self.callback)
            tqm._stdout_callback = self.callback
            C.HOST_KEY_CHECKING = False  # 关闭第一次使用ansible连接客户端是输入命令
            tqm.run(play)
        except Exception as err:
            print err
        finally:
            if tqm is not None:
                tqm.cleanup()
            if self.loader:
                self.loader.cleanup_all_tmp_files()

    def run_playbook(self, host_list, playbook_path, extra_vars=dict()):
        """
        run ansible palybook
        :param host_list: --limit 参数
        :param playbook_path:  playbook的路径
        :param extra_vars:
        :return:
        """
        try:
            self.callback = PlayBookResultsCollector()
            self.variable_manager.extra_vars = extra_vars

            self.inventory.subset(host_list)
            executor = PlaybookExecutor(
                playbooks=[playbook_path],
                inventory=self.inventory,
                variable_manager=self.variable_manager,
                loader=self.loader,
                options=self.options,
                passwords=self.passwords,
            )
            executor._tqm._stdout_callback = self.callback
            C.HOST_KEY_CHECKING = False  # 关闭第一次使用ansible连接客户端时输入命令
            C.DEPRECATION_WARNINGS = False
            C.RETRY_FILES_ENABLED = False
            executor.run()
        except Exception as err:
            print err
            return False

    def get_module_result(self):
        """
        获取module执行结果
        :return:
        """
        self.results_raw = {'success': {}, 'failed': {}, 'unreachable': {}}
        for host, result in self.callback.host_ok.items():
            self.results_raw['success'][host] = result._result['stdout']

        for host, result in self.callback.host_failed.items():
            self.results_raw['failed'][host] = result._result['stderr']

        for host, result in self.callback.host_unreachable.items():
            self.results_raw['unreachable'][host] = result._result['msg']

        return json.dumps(self.results_raw)

    def get_playbook_result(self):
        """
        获取playbook的执行结果
        :return:
        """
        self.results_raw = {
            'skipped': {},
            'failed': {},
            'ok': {},
            "status": {},
            'unreachable': {},
            "changed": {},
        }

        for host, results in self.callback.task_ok.items():
            for result in results:
                if not self.results_raw['ok'].get(host):
                    self.results_raw['ok'][host] = dict()
                task_name = result.task_name
                _result = result._result
                if not self.results_raw['ok'][host].get(task_name):
                    self.results_raw['ok'][host][task_name] = list()
                if task_name != 'Gathering Facts':
                    self.results_raw['ok'][host][task_name] = (
                        _result['stdout'])

        for host, results in self.callback.task_failed.items():
            for result in results:
                if not self.results_raw['failed'].get(host):
                    self.results_raw['failed'][host] = dict()
                task_name = result.task_name
                _result = result._result
                if not self.results_raw['failed'][host].get(task_name):
                    self.results_raw['failed'][host][task_name] = list()
                if task_name != 'Gathering Facts':
                    self.results_raw['failed'][host][task_name] = (
                        _result['stderr'])

        for host, results in self.callback.task_unreachable.items():
            for result in results:
                if not self.results_raw['unreachable'].get(host):
                    self.results_raw['unreachable'][host] = dict()
                task_name = result.task_name
                _result = result._result
                if not self.results_raw['unreachable'][host].get(task_name):
                    self.results_raw['unreachable'][host][task_name] = list()
                self.results_raw['unreachable'][host][task_name] = (
                    _result['msg'])

        for host, results in self.callback.task_changed.items():
            for result in results:
                if not self.results_raw['changed'].get(host):
                    self.results_raw['changed'][host] = dict()
                task_name = result.task_name
                _result = result._result
                if not self.results_raw['changed'][host].get(task_name):
                    self.results_raw['changed'][host][task_name] = list()
                self.results_raw['changed'][host][task_name] = (
                    _result['task_name'])

        for host, results in self.callback.task_skipped.items():
            for result in results:
                if not self.results_raw['skipped'].get(host):
                    self.results_raw['skipped'][host] = dict()
                task_name = result.task_name
                _result = result._result
                if not self.results_raw['skipped'][host].get(task_name):
                    self.results_raw['skipped'][host][task_name] = list()
                self.results_raw['skipped'][host][task_name] = (
                    _result['task_name'])

        for host, result in self.callback.task_status.items():
            self.results_raw['status'][host] = result

        self.results_raw['status_no_hosts'] = self.callback.status_no_hosts
        return json.dumps(self.results_raw)
Exemple #16
0
def main():
    host_list = ['172.17.0.10']
    # since the API is constructed for CLI it expects certain options to always be set in the context object
    context.CLIARGS = ImmutableDict(connection='smart',
                                    private_key_file="~/.ssh/id_rsa",
                                    forks=10,
                                    become=None,
                                    become_method=None,
                                    become_user=None,
                                    check=False,
                                    diff=False,
                                    verbosity=0)
    # 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='')

    # 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,
        stdout_callback=
        results_callback,  # Use our custom callback instead of the ``default`` callback plugin, which prints to stdout
    )

    play_sources = []
    with open('./mysql.yml') as f:
        data = yaml.load(f, yaml.SafeLoader)
        if isinstance(data, list):
            play_sources.extend(data)
        else:
            play_source.append(data)

    for play_book in play_sources:
        play_book['hosts'] = host_list
        play = Play().load(play_book,
                           variable_manager=variable_manager,
                           loader=loader)
        # Actually run it
        try:
            result = tqm.run(
                play
            )  # most interesting data for a play is actually sent to the callback's methods
        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()

    # 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

    # 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']))
Exemple #17
0
class MyApi(object):
    def __init__(self, resource=None, sources=None, *args, **kwargs):
        self.resource = resource
        self.sources = sources
        self.inventory = None
        self.variable_manager = None
        self.loader = None
        self.options = None
        self.passwords = None
        self.callback = None

        self.timeout = kwargs.get('timeout', '') if kwargs.get('timeout',
                                                               '') else 10
        self.forks = kwargs.get('forks', '') if kwargs.get('forks', '') else 10
        self.connection = kwargs.get('connection', '') if kwargs.get(
            'connection', '') else 'smart'
        self.become_user = kwargs.get('become_user', '') if kwargs.get(
            'become_user', '') else 'root'

        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', 'diff', 'syntax'
        ])

        # 定义选项 become=u'yes', 开启beome,默认关闭
        self.options = Options(connection=self.connection,
                               module_path=None,
                               forks=self.forks,
                               timeout=self.timeout,
                               remote_user='******',
                               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='sudo',
                               become_user=self.become_user,
                               ask_value_pass=False,
                               verbosity=None,
                               check=False,
                               listhosts=False,
                               listtasks=False,
                               listtags=False,
                               diff=False,
                               syntax=False)

        # 用来加载解析yaml文件或JSON内容, 并且支持vault的解密
        self.loader = DataLoader()

        # 默认密码, 主机未定义密码的时候才生效
        #self.passwords = dict(sshpass=None, becomepass=None)
        self.passwords = dict(vault_pass='******')

        # 加载 host 列表
        self.inventory = MyInventory(self.resource, self.loader,
                                     self.sources).inventory

        # 初始化变量, 包括主机、组、扩展等变量
        self.variable_manager = VariableManager(loader=self.loader,
                                                inventory=self.inventory)

    def run(self, host_list, module_name, module_args=None):
        """
        从 andible ad-hoc 运行模块.
        module_name: ansible 模块名称 (-m)
        module_args: ansible 模块参数 (-a)
        """

        # 创建任务
        play_source = dict(
            name="JK 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)

        # 实际运行
        # TaskQueueManager 是创建进程池, 负责输出结果和多进程间数据结构或者队列的共享协作
        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,
                stdout_callback=self.callback,
            )
            tqm.run(play)

        finally:
            if tqm is not None:
                tqm.cleanup()
            if self.loader:
                self.loader.cleanup_all_tmp_files()
            shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)

    def run_playbook(self, host_list, playbook_path):
        """
        执行 ansible palybook
        """

        try:
            self.callback = ResultsCollector()
            # playbook的路径
            pbfiles = playbook_path.split()
            for pbfile in pbfiles:
                if not os.path.exists(pbfile):
                    print('[INFO] The [%s] playbook does not exist' % pbfile)
                    sys.exit()

            # 额外的参数 sudoers.yml以及模板中的参数,它对应ansible-playbook test.yml --extra-vars "host='aa' name='cc'"
            extra_vars = {}
            extra_vars['host_list'] = host_list
            self.variable_manager.extra_vars = extra_vars
            # actually run it
            executor = PlaybookExecutor(
                playbooks=pbfiles,
                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:
            jklog.error(e)

    def get_result(self):
        # 获取结束回调
        self.result_all = {'success': {}, 'failed': {}, 'unreachable': {}}

        for host, results in self.callback.status_ok.items():
            for result in results:
                if not self.result_all['success'].get(host):
                    self.result_all['success'][host] = dict()
                task_name = result.task_name
                _result = result._result
                # jklog.debug(_result)
                if not self.result_all['success'][host].get(task_name):
                    self.result_all['success'][host][task_name] = list()
                if task_name == 'copy':
                    self.result_all['success'][host][task_name] = (
                        _result['invocation'])
                else:
                    self.result_all['success'][host][task_name] = (
                        _result['stdout'])

        for host, results in self.callback.status_fail.items():
            for result in results:
                if not self.result_all['failed'].get(host):
                    self.result_all['failed'][host] = dict()
                task_name = result.task_name
                _result = result._result
                # jklog.debug(_result)
                if not self.result_all['failed'][host].get(task_name):
                    self.result_all['failed'][host][task_name] = list()
                if task_name == 'copy':
                    self.result_all['failed'][host][task_name] = (
                        _result['msg'])
                else:
                    self.result_all['failed'][host][task_name] = (
                        _result['stdout'])

        for host, results in self.callback.status_unreachable.items():
            for result in results:
                if not self.result_all['unreachable'].get(host):
                    self.result_all['unreachable'][host] = dict()
                task_name = result.task_name
                _result = result._result
                # jklog.debug(_result)
                if not self.result_all['unreachable'][host].get(task_name):
                    self.result_all['unreachable'][host][task_name] = list()
                self.result_all['unreachable'][host][task_name].append(
                    _result['msg'])

        return self.result_all

    def get_json(self):
        d = self.get_result()
        data = json.dumps(d)
        return data
Exemple #18
0
class AdHocRunner:
    """
    ADHoc Runner接口
    """
    results_callback_class = AdHocResultCallback
    results_callback = None
    loader_class = DataLoader
    variable_manager_class = VariableManager
    default_options = get_default_options()
    options = None
    command_modules_choices = ('shell', 'raw', 'command', 'script')

    def __init__(self, inventory, options=None, stdout=None):
        self.options = self.get_options(options)
        self.inventory = inventory
        self.stdout = stdout
        self.loader = DataLoader()
        self.variable_manager = VariableManager(loader=self.loader,
                                                inventory=self.inventory)
        self.set_result_callback()

    def get_result_callback(self):
        display = None
        if self.stdout:
            display = LogFileDisplay(self.stdout)
        return self.results_callback_class(display=display)

    def set_result_callback(self):
        self.results_callback = self.get_result_callback()

    @staticmethod
    def check_module_args(module_name, module_args=''):
        if module_name in C.MODULE_REQUIRE_ARGS and not module_args:
            err = "No argument passed to '%s' module." % module_name
            raise AnsibleError(err)

    def is_command_task(self, tasks):
        if len(tasks) != 1:
            return False
        if tasks[0].get("action",
                        {}).get("module") in self.command_modules_choices:
            return True
        return False

    def check_pattern(self, pattern):
        if not pattern:
            raise AnsibleError("Pattern `{}` is not valid!".format(pattern))
        if not self.inventory.list_hosts("all"):
            raise AnsibleError("Inventory is empty.")
        if not self.inventory.list_hosts(pattern):
            raise AnsibleError("pattern: %s  dose not match any hosts." %
                               pattern)

    def clean_tasks(self, tasks):
        cleaned_tasks = []
        for task in tasks:
            module = task['action']['module']
            args = task['action'].get('args')
            self.check_module_args(module, args)
            cleaned_tasks.append(task)
        return cleaned_tasks

    def get_options(self, options):
        _options = self.default_options
        if options and isinstance(options, dict):
            _options = _options._replace(**options)
        return _options

    def update_options(self, options):
        if options and isinstance(options, dict):
            self.options = self.options._replace(**options)

    def run(self,
            tasks,
            pattern,
            play_name='Ansible Ad-hoc',
            gather_facts='no'):
        """
        :param tasks: [{'action': {'module': 'shell', 'args': 'ls'}, ...}, ]
        :param pattern: all, *, or others
        :param play_name: The play name
        :param gather_facts:
        :return:
        """
        self.check_pattern(pattern)
        cleaned_tasks = self.clean_tasks(tasks)

        play_source = dict(name=play_name,
                           hosts=pattern,
                           gather_facts=gather_facts,
                           tasks=cleaned_tasks)

        play = Play().load(
            play_source,
            variable_manager=self.variable_manager,
            loader=self.loader,
        )

        tqm = TaskQueueManager(
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            stdout_callback=self.results_callback,
            passwords=self.options.passwords,
        )
        msg = ("Get matched hosts: {}".format(
            self.inventory.get_matched_hosts(pattern)))
        try:
            tqm.send_callback('on_playbook_start', play.name)
            self.results_callback.display(msg)
            tqm.run(play)
            return self.results_callback.results
        except Exception as e:
            raise AnsibleError(e)
        finally:
            tqm.send_callback('v2_playbook_on_stats', tqm._stats)
            tqm.send_callback('on_playbook_end', play.name)
            tqm.cleanup()
            self.loader.cleanup_all_tmp_files()
class PlaybookRunner(object):
    """
  The plabybook API.
  """
    def __init__(
            self,
            hosts=C.DEFAULT_HOST_LIST,  # a list or dynamic-hosts,
            # default is /etc/ansible/hosts
        playbook_path=None,  # * a playbook file
            forks=C.DEFAULT_FORKS,
            listtags=False,
            listtasks=False,
            listhosts=False,
            syntax=False,
            module_path=None,
            remote_user='******',
            timeout=C.DEFAULT_TIMEOUT,
            ssh_common_args=None,
            ssh_extra_args=None,
            sftp_extra_args=None,
            scp_extra_args=None,
            become=True,
            become_method=None,
            become_user="******",
            verbosity=None,
            extra_vars=None,
            connection_type="ssh",
            passwords=None,
            private_key_file=C.DEFAULT_PRIVATE_KEY_FILE,
            remote_pass=C.DEFAULT_REMOTE_PASS,
            remote_port=None,
            check=False):

        C.RETRY_FILES_ENABLED = False
        self.callbackmodule = CallbackModule()
        if playbook_path is None or not os.path.exists(playbook_path):
            raise AnsibleError("Not Found the playbook file: %s." %
                               playbook_path)
        self.playbook_path = playbook_path
        self.loader = DataLoader()
        self.variable_manager = VariableManager()
        self.passwords = passwords or {}
        # save host to file
        if not os.path.exists(os.path.join(base_dir, "tmp_inventory")):
            os.mkdir(os.path.join(base_dir, "tmp_inventory"))
        self.file_name = os.path.join(base_dir, "tmp_inventory",
                                      "tmp_host_{0}".format(time.time()))
        with open(self.file_name, 'w') as f:
            f.write("\n".join(hosts))
        self.passwords = passwords or {}
        self.inventory = InventoryManager(loader=self.loader,
                                          sources=self.file_name)
        self.variable_manager = VariableManager(loader=self.loader,
                                                inventory=self.inventory)

        self.options = Options(listtags=listtags,
                               listtasks=listtasks,
                               listhosts=listhosts,
                               syntax=syntax,
                               timeout=timeout,
                               connection=connection_type,
                               module_path=module_path,
                               forks=forks,
                               remote_user=remote_user,
                               remote_pass=remote_pass,
                               remote_port=remote_port,
                               private_key_file=private_key_file,
                               ssh_common_args=ssh_common_args or "",
                               ssh_extra_args=ssh_extra_args or "",
                               sftp_extra_args=sftp_extra_args,
                               scp_extra_args=scp_extra_args,
                               become=become,
                               become_method=become_method,
                               become_user=become_user,
                               verbosity=verbosity,
                               extra_vars=extra_vars or [],
                               check=check,
                               diff=False)

        self.runner = PlaybookExecutor(playbooks=[self.playbook_path],
                                       inventory=self.inventory,
                                       variable_manager=self.variable_manager,
                                       loader=self.loader,
                                       options=self.options,
                                       passwords=self.passwords)
        if self.runner._tqm:
            self.runner._tqm._stdout_callback = self.callbackmodule

    def run(self):
        if not self.inventory.list_hosts("all"):
            raise AnsibleError("Inventory is empty.")

        try:
            self.runner.run()
            return self.callbackmodule.output
        except Exception as e:
            raise Exception(e)
        finally:
            if self.loader:
                self.loader.cleanup_all_tmp_files()
            if os.path.exists(self.file_name):
                os.remove(self.file_name)
Exemple #20
0
class AdHocRunner:
    """
    ADHoc Runner接口
    """
    results_callback_class = AdHocResultCallback
    results_callback = None
    loader_class = DataLoader
    variable_manager_class = VariableManager
    default_options = get_default_options()

    def __init__(self, inventory, options=None):
        self.options = self.update_options(options)
        self.inventory = inventory
        self.loader = DataLoader()
        self.variable_manager = VariableManager(
            loader=self.loader, inventory=self.inventory
        )

    def get_result_callback(self, file_obj=None):
        return self.__class__.results_callback_class(file_obj=file_obj)

    @staticmethod
    def check_module_args(module_name, module_args=''):
        if module_name in C.MODULE_REQUIRE_ARGS and not module_args:
            err = "No argument passed to '%s' module." % module_name
            raise AnsibleError(err)

    def check_pattern(self, pattern):
        if not pattern:
            raise AnsibleError("Pattern `{}` is not valid!".format(pattern))
        if not self.inventory.list_hosts("all"):
            raise AnsibleError("Inventory is empty.")
        if not self.inventory.list_hosts(pattern):
            raise AnsibleError(
                "pattern: %s  dose not match any hosts." % pattern
            )

    def clean_tasks(self, tasks):
        cleaned_tasks = []
        for task in tasks:
            self.check_module_args(task['action']['module'], task['action'].get('args'))
            cleaned_tasks.append(task)
        return cleaned_tasks

    def update_options(self, options):
        if options and isinstance(options, dict):
            options = self.__class__.default_options._replace(**options)
        else:
            options = self.__class__.default_options
        return options

    def run(self, tasks, pattern, play_name='Ansible Ad-hoc', gather_facts='no', file_obj=None):
        """
        :param tasks: [{'action': {'module': 'shell', 'args': 'ls'}, ...}, ]
        :param pattern: all, *, or others
        :param play_name: The play name
        :param gather_facts:
        :param file_obj: logging to file_obj
        :return:
        """
        self.check_pattern(pattern)
        self.results_callback = self.get_result_callback(file_obj)
        cleaned_tasks = self.clean_tasks(tasks)

        play_source = dict(
            name=play_name,
            hosts=pattern,
            gather_facts=gather_facts,
            tasks=cleaned_tasks
        )

        play = Play().load(
            play_source,
            variable_manager=self.variable_manager,
            loader=self.loader,
        )

        tqm = TaskQueueManager(
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            stdout_callback=self.results_callback,
            passwords=self.options.passwords,
        )
        print("Get matched hosts: {}".format(
            self.inventory.get_matched_hosts(pattern)
        ))

        try:
            tqm.run(play)
            return self.results_callback
        except Exception as e:
            raise AnsibleError(e)
        finally:
            tqm.cleanup()
            self.loader.cleanup_all_tmp_files()
Exemple #21
0
class YoRunner(object):
    Options = namedtuple("Options", [
        'connection', 'module_path', 'private_key_file', "remote_user",
        'timeout', 'forks', 'become', 'become_method', 'become_user',
        'check', 'extra_vars',
        ]
    )

    def __init__(self,
                 hosts=C.DEFAULT_HOST_LIST,
                 forks=C.DEFAULT_FORKS,  # 5
                 timeout=C.DEFAULT_TIMEOUT,  # SSH timeout = 10s
                 remote_user=C.DEFAULT_REMOTE_USER,  # root
                 module_path=None,  # dirs of custome modules
                 connection_type="smart",
                 become=None,
                 become_method=None,
                 become_user=None,
                 check=False,
                 passwords=None,
                 extra_vars=None,
                 private_key_file=None,
                 gather_facts='no'):
        self.pattern = ''
        self.variable_manager = VariableManager()
        self.loader = DataLoader()
        self.gather_facts = gather_facts
        self.options = self.Options(
            connection=connection_type,
            timeout=timeout,
            module_path=module_path,
            forks=forks,
            become=become,
            become_method=become_method,
            become_user=become_user,
            check=check,
            remote_user=remote_user,
            extra_vars=extra_vars or [],
            private_key_file=private_key_file,
        )
        # self.variable_manager.extra_vars = load_extra_vars(self.loader,
        #                                                    options=self.options)
        self.variable_manager.extra_vars = extra_vars
        self.variable_manager.options_vars = load_options_vars(self.options)
        self.passwords = passwords or {}
        self.inventory = YoInventory(hosts)
        self.variable_manager.set_inventory(self.inventory)
        self.tasks = []
        self.play_source = None
        self.play = None
        self.runner = None
        self.timestamp = str(time.time())
        self.filename = FILENAME%(self.timestamp,'')
        self.have_script = 0

    def set_callback(self,callback):
        self.results_callback=callback

    @staticmethod
    def check_module_args(module_name, module_args=''):
        if module_name in C.MODULE_REQUIRE_ARGS and not module_args:
            err = "No argument passed to '%s' module." % module_name
            print(err)
            return False
        return True

    def task_add(self,task_tuple):
        for task in task_tuple:
            if not self.check_module_args(task.module,task.args):
                return
            if task.module == u'script':
                self.have_script = 1
                script = Script.objects.filter(id=task.args)
                if os.path.exists(self.filename):
                    os.remove(self.filename)
                script_name = FILENAME % (self.timestamp, '-' + str(script.get().id))
                output = open(script_name, 'w')
                output.writelines(script.get().formatScript())
                output.close()
            if self.have_script == 1:
                self.tasks.append(
                    dict(action=dict(
                        module=task.module,
                        args=script_name,
                    ))
                )
            else:
                self.tasks.append(
                    dict(action=dict(
                        module=task.module,
                        args=task.args,
                    ))
                )


    def run(self, task_tuple,):# pattern='all'):
        """
        :param task_tuple:  (('shell', 'ls'), ('ping', ''))
        :param pattern:
        :param timestamp:
        :return:
        """
        self.task_add(task_tuple)

        self.play_source = dict(
            name=self.timestamp,
            hosts='all',
            gather_facts=self.gather_facts,
            tasks=self.tasks
        )

        self.play = Play().load(
            self.play_source,
            variable_manager=self.variable_manager,
            loader=self.loader,
        )

        self.runner = TaskQueueManager(
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            passwords=self.passwords,
            stdout_callback=self.results_callback,
        )

        # if not self.inventory.list_hosts("all"):
        #     raise AnsibleError("Inventory is empty.")
        #
        # if not self.inventory.list_hosts(self.pattern):
        #     raise AnsibleError(
        #         "pattern: %s  dose not match any hosts." % self.pattern)

        try:
            self.runner.run(self.play)
        finally:
            if self.runner:
                self.runner.cleanup()
            if self.loader:
                self.loader.cleanup_all_tmp_files()
            if self.have_script:
                self.cleanup_script()

    def cleanup_script(self):
        # if os.path.exists(self.filename):
        #     os.remove(self.filename)
        # return self.filename
        for name in glob.glob(self.filename+'*'):
            if os.path.exists(name):
                print(name)
                os.remove(name)
    # def clean_result(self):
    #     """
    #     :return: {
    #         "success": ['hostname',],
    #         "failed": [('hostname', 'msg'), {}],
    #     }
    #     """
    #     result = {'success': [], 'failed': []}
    #     for host in self.results_callback.result_q['contacted']:
    #         result['success'].append(host)
    #
    #     for host, msgs in self.results_callback.result_q['dark'].items():
    #         msg = '\n'.join(['{} {}: {}'.format(
    #             msg.get('module_stdout', ''),
    #             msg.get('invocation', {}).get('module_name'),
    #             msg.get('msg', '')) for msg in msgs])
    #         result['failed'].append((host, msg))
    #     return 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='******')

    # 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,
        stdout_callback=
        results_callback,  # Use our custom callback instead of the ``default`` callback plugin, which prints to stdout
    )

    # 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:
        result = tqm.run(
            play
        )  # most interesting data for a play is actually sent to the callback's methods
    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']))
Exemple #23
0
class Runner(object):
    """
    仿照ansible1.9 的python API,制作的ansible2.0 API的简化版本。
    参数说明:
        inventory:: 仓库对象,可以是列表,逗号间隔的ip字符串,可执行文件. 默认/etc/ansible/hosts
        module_name:: 指定要使用的模块
        module_args:: 模块参数
        forks:: 并发数量, 默认5
        timeout:: 连接等待超时时间,默认10秒
        pattern:: 模式匹配,指定要连接的主机名, 默认all
        remote_user:: 指定连接用户, 默认root
        private_key_files:: 指定私钥文件
    """
    def __init__(
        self,
        hosts=C.DEFAULT_HOST_LIST,
        module_name=C.DEFAULT_MODULE_NAME,    # * command
        module_args=C.DEFAULT_MODULE_ARGS,    # * 'cmd args'
        forks=C.DEFAULT_FORKS,                # 5
        timeout=C.DEFAULT_TIMEOUT,            # SSH timeout = 10s
        pattern="all",                        # all
        remote_user=C.DEFAULT_REMOTE_USER,    # root
        module_path=None,                     # dirs of custome modules
        connection_type="smart",
        become=None,
        become_method=None,
        become_user=None,
        check=False,
        passwords=None,
        extra_vars = None,
        private_key_file=None
    ):

        # storage & defaults
        self.pattern = pattern
        self.loader = DataLoader()
        self.module_name = module_name
        self.module_args = module_args
        self.check_module_args()
        self.gather_facts = 'no'
        self.resultcallback = ResultCallback()
        self.options = Options(
            connection=connection_type,
            timeout=timeout,
            module_path=module_path,
            forks=forks,
            become=become,
            become_method=become_method,
            become_user=become_user,
            check=check,
            remote_user=remote_user,
            extra_vars=extra_vars or [],
            private_key_file=private_key_file,
            diff=False
        )

        self.inventory = MyInventory(host_list=hosts)
        self.variable_manager = VariableManager(self.loader, self.inventory)
        self.variable_manager.extra_vars = load_extra_vars(loader=self.loader, options=self.options)
        self.variable_manager.options_vars = load_options_vars(self.options, "")
        self.passwords = passwords or {}

        self.play_source = dict(
            name="Ansible Ad-hoc",
            hosts=self.pattern,
            gather_facts=self.gather_facts,
            tasks=[dict(action=dict(
                module=self.module_name, args=self.module_args))]
        )

        self.play = Play().load(
            self.play_source, variable_manager=self.variable_manager,
            loader=self.loader)

        self.runner = TaskQueueManager(
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            passwords=self.passwords,
            stdout_callback=self.resultcallback
        )

        # ** end __init__() **

    def run(self):
        if not self.inventory.list_hosts("all"):
            raise AnsibleError("Inventory is empty.")

        if not self.inventory.list_hosts(self.pattern):
            raise AnsibleError(
                "pattern: %s  dose not match any hosts." % self.pattern)

        try:
            self.runner.run(self.play)
        finally:
            if self.runner:
                self.runner.cleanup()
            if self.loader:
                self.loader.cleanup_all_tmp_files()

        return self.resultcallback.result_q


    def check_module_args(self):
        if self.module_name in C.MODULE_REQUIRE_ARGS and not self.module_args:
            err = "No argument passed to '%s' module." % self.module_name
            raise AnsibleError(err)
Exemple #24
0
class Runner(object):
    """
  仿照ansible1.9 的python API,制作的ansible2.0 API的简化版本。
  参数说明:
      inventory:: 仓库对象,可以是列表,逗号间隔的ip字符串,可执行文件. 默认/etc/ansible/hosts
      module_name:: 指定要使用的模块
      module_args:: 模块参数
      forks:: 并发数量, 默认5
      timeout:: 连接等待超时时间,默认10秒
      pattern:: 模式匹配,指定要连接的主机名, 默认all
      remote_user:: 指定连接用户, 默认root
      private_key_files:: 指定私钥文件
  """
    def __init__(
            self,
            hosts=C.DEFAULT_HOST_LIST,
            module_name=C.DEFAULT_MODULE_NAME,  # * command
            module_args=C.DEFAULT_MODULE_ARGS,  # * 'cmd args'
            forks=C.DEFAULT_FORKS,  # 5
            timeout=C.DEFAULT_TIMEOUT,  # SSH timeout = 10s
            pattern="all",  # all
            remote_user=C.DEFAULT_REMOTE_USER,  # root
            module_path=None,  # dirs of custome modules
            connection_type="smart",
            become=None,
            become_method=None,
            become_user=None,
            check=False,
            passwords=None,
            extra_vars=None,
            private_key_file=C.DEFAULT_PRIVATE_KEY_FILE,
            remote_pass=C.DEFAULT_REMOTE_PASS,
            remote_port=None):

        # storage & defaults
        self.pattern = pattern
        self.loader = DataLoader()
        self.module_name = module_name
        self.module_args = module_args
        self.check_module_args()
        self.gather_facts = 'no'
        self.resultcallback = ResultCallback()
        self.options = Options(connection=connection_type,
                               ssh_common_args=None,
                               ssh_extra_args=None,
                               sftp_extra_args=None,
                               scp_extra_args=None,
                               module_path=module_path,
                               forks=forks,
                               become=become,
                               become_method=become_method,
                               become_user=become_user,
                               check=check,
                               remote_user=remote_user,
                               private_key_file=private_key_file,
                               remote_port=remote_port,
                               verbosity=None,
                               diff=False)
        # save host to file
        if not os.path.exists(os.path.join(base_dir, "tmp_inventory")):
            os.mkdir(os.path.join(base_dir, "tmp_inventory"))
        self.file_name = os.path.join(base_dir, "tmp_inventory",
                                      "tmp_host_{0}".format(time.time()))
        with open(self.file_name, 'w') as f:
            f.write("[all]\n")
            f.write("\n".join(hosts))
            f.write("\n")
            if remote_pass:
                f.write("""[all:vars]
ansible_connection=ssh 
ansible_user={0} 
ansible_pass={1}""".format(remote_user, remote_pass))
        self.passwords = passwords or {}
        self.inventory = InventoryManager(loader=self.loader,
                                          sources=self.file_name)
        self.variable_manager = VariableManager(loader=self.loader,
                                                inventory=self.inventory)
        if self.module_name.strip() == "shell":
            self.module_args = "source ~/.bash_profile;" + self.module_args
        self.play_source = dict(name="Ansible Ad-hoc",
                                hosts=self.pattern,
                                gather_facts=self.gather_facts,
                                tasks=[
                                    dict(action=dict(module=self.module_name,
                                                     args=self.module_args),
                                         register='shell_out')
                                ])

        self.play = Play().load(self.play_source,
                                variable_manager=self.variable_manager,
                                loader=self.loader)

        self.runner = TaskQueueManager(inventory=self.inventory,
                                       variable_manager=self.variable_manager,
                                       loader=self.loader,
                                       options=self.options,
                                       passwords=self.passwords,
                                       stdout_callback=self.resultcallback)
        # ** end __init__() **

    def run(self):
        if not self.inventory.list_hosts("all"):
            raise AnsibleError("Inventory is empty.")

        if not self.inventory.list_hosts(self.pattern):
            raise AnsibleError("pattern: %s  dose not match any hosts." %
                               self.pattern)
        try:
            self.runner.run(self.play)
            return self.resultcallback.result_q
        except Exception as e:
            raise Exception(e)
        finally:
            if self.runner:
                self.runner.cleanup()
            if self.loader:
                self.loader.cleanup_all_tmp_files()
            if os.path.exists(self.file_name):
                os.remove(self.file_name)

    def check_module_args(self):
        if self.module_name in C.MODULE_REQUIRE_ARGS and not self.module_args:
            err = "No argument passed to '%s' module." % self.module_name
            raise AnsibleError(err)
Exemple #25
0
def ansible_install_api(task_id, play_book_path, schema):
    context.CLIARGS = ImmutableDict(
        connection='smart',
        private_key_file=settings.ANSIBLE_PRIVATE_KEY,
        forks=10,
        become_method='sudo',
        become_user='******',
        check=False,
        diff=False,
        verbosity=0)

    host_list = [schema.host_ip]
    sources = ','.join(host_list)
    if len(host_list) == 1:
        sources += ','

    loader = DataLoader()
    passwords = dict(vault_pass='')

    results_callback = ResultsCollectorJSONCallback(task_id=task_id)

    inventory = InventoryManager(loader=loader, sources=sources)

    variable_manager = VariableManager(loader=loader, inventory=inventory)
    tqm = TaskQueueManager(
        inventory=inventory,
        variable_manager=variable_manager,
        loader=loader,
        passwords=passwords,
        stdout_callback=
        results_callback,  # Use our custom callback instead of the ``default`` callback plugin, which prints to stdout
    )

    play_sources = []

    import os
    os.chdir(os.path.dirname(play_book_path))
    with open(play_book_path) as f:
        data = yaml.load(f, yaml.SafeLoader)
        if isinstance(data, list):
            play_sources.extend(data)
        else:
            play_sources.append(data)

    logger.info("there are %d tasks to run", len(play_sources))
    for play_book in play_sources:
        play_book['hosts'] = host_list
        play_book['remote_user'] = '******'
        play_book['vars']['mysql_port'] = schema.port
        play_book['vars']['mysql_schema'] = schema.schema
        print("playbook", play_book)
        play = Play().load(play_book,
                           variable_manager=variable_manager,
                           loader=loader)
        # Actually run it
        try:
            result = tqm.run(
                play
            )  # most interesting data for a play is actually sent to the callback's methods
        finally:
            # we always need to cleanup child procs and the structures we use to communicate with them
            logger.info("tqm has finished")
            tqm.cleanup()
            if loader:
                loader.cleanup_all_tmp_files()

    # 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

    # Remove ansible tmpdir
    shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
    return not results_callback.is_failed
Exemple #26
0
class PlayRun:
    Options = namedtuple('Options', [
        'connection', 'module_path', 'forks', 'become', 'become_method',
        'become_user', 'check'
    ])

    def __init__(self,
                 connection_type="ssh",
                 forks=100,
                 host_list="/etc/ansible/hosts",
                 passwords=None,
                 callback=None):
        self.connection_type = connection_type
        self.forks = forks
        self.host_list = host_list
        self.passwords = passwords or None

        self.variable_manager = VariableManager()
        self.loader = DataLoader()
        self.options = self.Options(connection=self.connection_type,
                                    module_path=None,
                                    forks=forks,
                                    become=None,
                                    become_method=None,
                                    become_user=None,
                                    check=False)

        self.results_callback = callback()
        self.inventory = Inventory(loader=self.loader,
                                   variable_manager=self.variable_manager,
                                   host_list="/etc/ansible/hosts")

        self.variable_manager.set_inventory(self.inventory)
        self.play_source = None
        self.play = None
        self.runner = None

    def run(self, action_tuple, hosts="all", task_name="Ansible Ad-hoc"):
        """
        :param action_tuple: [('shell', 'ls'), ('ping', '')]
        """
        tasks = []
        for item in action_tuple:
            assert len(item) == 2
            module, args = item
            tasks.append(dict(action=dict(module=module, args=args)))

        self.play_source = dict(name=task_name,
                                hosts=hosts,
                                gather_facts='no',
                                tasks=tasks)
        self.play = Play().load(self.play_source,
                                variable_manager=self.variable_manager,
                                loader=self.loader)
        self.runner = TaskQueueManager(
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            passwords=self.passwords,
            stdout_callback=self.results_callback,
        )

        try:
            self.runner.run(self.play)
        finally:
            if self.runner:
                self.runner.cleanup()
            if self.loader:
                self.loader.cleanup_all_tmp_files()
            return self.results_callback.result_q  # run()最终将call_back的结果返回
def execute_playbook(play_book, host_list=[]):
    host_list = host_list
    # since the API is constructed for CLI it expects certain options to always be set in the context object
    context.CLIARGS = ImmutableDict(
        connection='paramiko',
        module_path=[
            '/home/koshik/Documents/projects/devops/scripts/aenv/lib/python3.6/site-packages/ansible'
        ],
        forks=10,
        become=None,
        become_method=None,
        become_user=None,
        check=False,
        diff=False)

    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='******')

    # Instantiate our ResultsCollectorJSONCallback for handling results as they come in. Ansible expects this to be one of its main display outlets
    results_callback = ResultsCollectorJSONCallback()

    inventory = InventoryManager(loader=loader, sources=sources)

    variable_manager = VariableManager(loader=loader, inventory=inventory)

    tqm = TaskQueueManager(
        inventory=inventory,
        variable_manager=variable_manager,
        loader=loader,
        passwords=passwords,
        stdout_callback=
        results_callback,  # Use our custom callback instead of the ``default`` callback plugin, which prints to stdout
    )

    pbex = PlaybookExecutor(playbooks=[play_book],
                            inventory=inventory,
                            variable_manager=variable_manager,
                            loader=loader,
                            passwords=passwords)
    playbook = Playbook.load(pbex._playbooks[0],
                             variable_manager=variable_manager,
                             loader=loader)
    play = playbook.get_plays()[0]

    # Actually run it
    try:
        result = tqm.run(
            play
        )  # most interesting data for a play is actually sent to the callback's methods
    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)

    if (results_callback.host_ok.items()):
        print("********* SUCCESS ***********")
        return results_callback.host_ok.items()

    if (results_callback.host_failed.items()):
        print("********* FAILED *******")
        for host, result in results_callback.host_failed.items():
            print('{0} >>> {1}'.format(host, result._result['msg']))

    if (results_callback.host_unreachable.items()):
        print("********* HOST DOWN *********")
        for host, result in results_callback.host_unreachable.items():
            print('{0} >>> {1}'.format(host, result._result['msg']))
def chaosansible_run(
    host_list: list = ("localhost"),
    configuration: Configuration = None,
    facts: bool = False,
    become: bool = False,
    run_once: bool = False,
    ansible: dict = {},
    num_target: str = "all",
    secrets: Secrets = None,
):

    """
    Run a task through ansible and eventually gather facts from host
    """

    # Check for correct inputs
    if ansible:
        if ansible.get("module") is None:
            raise InvalidActivity("No ansible module defined")

        if ansible.get("args") is None:
            raise InvalidActivity("No ansible module args defined")

    configuration = configuration or {}

    # Ansible configuration elements
    module_path = configuration.get("ansible_module_path")
    become_user = configuration.get("ansible_become_user")
    ssh_key_path = configuration.get("ansible_ssh_private_key")
    ansible_user = configuration.get("ansible_user")
    become_ask_pass = configuration.get("become_ask_pass")
    ssh_extra_args = configuration.get("ansible_ssh_extra_args")

    context.CLIARGS = ImmutableDict(
        connection="smart",
        verbosity=0,
        module_path=module_path,
        forks=10,
        become=become,
        become_method="sudo",
        become_user=become_user,
        check=False,
        diff=False,
        private_key_file=ssh_key_path,
        remote_user=ansible_user,
        ssh_extra_args=ssh_extra_args,
    )

    # Update host_list regarding the number of desired target.
    # Need to generate a new host-list because after being update
    # and will be used later
    if num_target != "all":
        new_host_list = random_host(host_list, int(num_target))
    else:
        new_host_list = host_list[:]

    # Create an inventory
    sources = ",".join(new_host_list)
    if len(new_host_list) == 1:
        sources += ","

    loader = DataLoader()
    inventory = InventoryManager(loader=loader, sources=sources)

    # Instantiate callback for storing results
    results_callback = ResultsCollectorJSONCallback()

    variable_manager = VariableManager(loader=loader, inventory=inventory)
    if become_ask_pass:
        passwords = dict(become_pass=become_ask_pass)
    else:
        passwords = None

    # Ansible taskmanager
    tqm = TaskQueueManager(
        inventory=inventory,
        variable_manager=variable_manager,
        loader=loader,
        passwords=passwords,
        stdout_callback=results_callback,
        run_additional_callbacks=False,
    )

    # Ansible playbook
    play_source = dict(
        name="Ansible Play",
        hosts=new_host_list,
        gather_facts=facts,
        tasks=[
            dict(
                name="facts",
                action=dict(module="debug", args=dict(var="ansible_facts")),
            ),
        ],
    )

    # In cas we only want to gather facts
    if ansible:
        module = ansible.get("module")
        args = ansible.get("args")
        play_source["tasks"].append(
            dict(
                name="task",
                run_once=run_once,
                action=dict(module=module, args=args),
                register="shell_out",
            )
        )

    # Create an ansible playbook
    play = Play().load(play_source,
                       variable_manager=variable_manager,
                       loader=loader)

    # Run it
    try:
        result = tqm.run(play)
    finally:
        tqm.cleanup()
        if loader:
            loader.cleanup_all_tmp_files()

    # Remove ansible tmpdir
    shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)

    if len(results_callback.host_failed) > 0:
        print("Ansible error(s): ")
        for error in results_callback.host_failed:
            print(results_callback.host_failed[error].__dict__)

        raise FailedActivity("Failed to run ansible task")

    elif len(results_callback.host_unreachable) > 0:
        print("Unreachable host(s): ")
        for error in results_callback.host_unreachable:
            print(error)

        raise FailedActivity("At least one target is down")

    else:
        results = {}

        for host, result in results_callback.host_ok.items():
            results[host] = result

        return json.dumps(results)
class MyApi(object):
    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 = {}
        if not os.path.exists(self.resource):
            print('[INFO] The [%s] inventory does not exist' % resource)
            sys.exit()
    def __initializeData(self):
        # 定义选项
        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',
                'diff',
                'syntax'
            ]
        )
        # 初始化需要的对象(参数)
        self.variable_manager = VariableManager()
        # 用来加载解析yaml文件或JSON内容, 并且支持vault的解密
        self.loader = DataLoader()
        # 定义选项
        self.options = Options(
            connection='smart',
            module_path='/usr/share/ansible',
            forks=100,
            timeout=10,
            remote_user='******',
            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='******',
            ask_value_pass=False,
            verbosity=None,
            check=False,
            listhosts=False,
            listtasks=False,
            listtags=False,
            diff=False,
            syntax=False
        )

        # 默认密码, 主机未定义密码的时候才生效
        self.passwords = dict(sshpass=None, becomepass=None)
        # 加载 host 列表
        self.inventory = InventoryManager(
            loader=self.loader, sources=[self.resource])
        # 初始化变量, 包括主机、组、扩展等变量
        self.variable_manager = VariableManager(
            loader=self.loader, inventory=self.inventory)

    def run(self, host_list, module_name, module_args=None):
        # 创建任务
        play_source = dict(
            name="Ansible Play",
            hosts=host_list,
            gather_facts='no',
            tasks=[
                dict(
                    action=dict(
                        module=module_name,
                        args=module_args
                    )
                ),
                # dict(action=dict(module='shell', args="id"), register='shell_out'),
                # dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}')), async=0, poll=15)
            ]
        )
        play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader)
        # 实际运行
        # TaskQueueManager 是创建进程池, 负责输出结果和多进程间数据结构或者队列的共享协作
        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,
                stdout_callback=self.callback,
            )
            tqm.run(play)
        finally:
            if tqm is not None:
                tqm.cleanup()
            if self.loader:
                self.loader.cleanup_all_tmp_files()
            shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)

    def run_playbook(self, host_list, playbook_path):
        """
        执行 ansible palybook
        """

        try:
            self.callback = ResultsCollector()
            # playbook的路径
            pbfiles = playbook_path.split()
            for pbfile in pbfiles:
                if not os.path.exists(pbfile):
                    print('[INFO] The [%s] playbook does not exist' % pbfile)
                    sys.exit()
            # 额外的参数 sudoers.yml以及模板中的参数,它对应ansible-playbook test.yml --extra-vars "host='aa' name='cc'"
            extra_vars = {}
            extra_vars['host_list'] = host_list
            self.variable_manager.extra_vars = extra_vars
            # actually run it
            executor = PlaybookExecutor(
                playbooks=pbfiles,
                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("error:", e.message)

    def get_result(self):
        # 获取结束回调
        self.result_all = {'success': {}, 'fail': {}, 'unreachable': {}}
        # print result_all
        # print dir(self.callback)
        for host, results in self.callback.host_ok.items():
            for result in results:
                if not self.result_all['success'].get(host):
                    self.result_all['success'][host] = dict()
                task_name = result.task_name
                _result = result._result
                if not self.result_all['success'][host].get(task_name):
                    self.result_all['success'][host][task_name] = list()
                self.result_all['success'][host][task_name].append(_result)

        for host, result in self.callback.host_failed.items():
            for result in results:
                if not self.result_all['failed'].get(host):
                    self.result_all['failed'][host] = dict()
                task_name = result.task_name
                _result = result._result
                if not self.result_all['failed'][host].get(task_name):
                    self.result_all['failed'][host][task_name] = list()
                self.result_all['failed'][host][task_name].append(_result['msg'])
            # self.result_all['failed'][host] = _result['msg']

        for host, result in self.callback.host_unreachable.items():
            for result in results:
                if not self.result_all['unreachable'].get(host):
                    self.result_all['unreachable'][host] = dict()
                task_name = result.task_name
                _result = result._result
                if not self.result_all['unreachable'][host].get(task_name):
                    self.result_all['unreachable'][host][task_name] = list()
                self.result_all['unreachable'][host][task_name].append(_result['msg'])

        for i in self.result_all['success'].keys():
            return self.result_all

    def get_json(self):
        d = self.get_result()
        data = json.dumps(d, ensure_ascii=False, indent=4, encoding='utf-8')
        print(data)
Exemple #30
0
class AnsiBleApi:
    def __init__(
        self,
        connection="smart",
        module_path=None,
        remote_user="******",
        forks=10,
        become=None,
        become_method=None,
        become_user=None,
        check=False,
        diff=False,
        hosts_list=None,
        verbosity=0,
        syntax=None,
        start_at_task=None,
        results_call_back=None,
        *args,
        **kwargs,
    ):

        context.CLIARGS = ImmutableDict(connection=connection,
                                        module_path=module_path,
                                        remote_user=remote_user,
                                        forks=forks,
                                        become=become,
                                        become_method=become_method,
                                        become_user=become_user,
                                        check=check,
                                        diff=diff,
                                        syntax=syntax,
                                        start_at_task=start_at_task,
                                        verbosity=verbosity,
                                        *args,
                                        **kwargs)
        self.forks = forks
        self.sources = hosts_list
        self.results_callback = results_call_back
        self.loader = DataLoader()

        def _(host):
            if isinstance(host, str):
                pass
            elif isinstance(host, list):
                s = ','.join(host)  #
                if len(host) == 1:
                    s += ','
                host = s
            return host

        self._host_format = _

        self.inventory = InventoryManager(loader=self.loader,
                                          sources=self._host_format(
                                              self.sources))
        self.variable_manager = VariableManager(loader=self.loader,
                                                inventory=self.inventory)
        self._play_source_template = {
            "name": "",
            "hosts": "",
            "gather_facts": "",
            "tasks": [],
        }

    def _play(self, play_source):
        var = play_source.pop("vars")
        return Play().load(play_source,
                           variable_manager=self.variable_manager,
                           loader=self.loader,
                           vars=var)

    def _tqm(self):
        return TaskQueueManager(
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            forks=self.forks,
            passwords=None,
            stdout_callback=self.results_callback,
        )

    def set_task(self, module="shell", args=None, **kwargs):
        task = {"action": {"module": module, "args": args}}
        task.update(kwargs)

        self._play_source_template["tasks"].append(task)

    def set_callback(self, callback=None):
        self.results_callback = callback

    def ansible(self, hosts, name="task name", gather_facts="no", var=None):
        if isinstance(hosts, list):
            hosts = self._host_format(hosts)

        self._play_source_template["name"] = name
        self._play_source_template["hosts"] = hosts
        self._play_source_template["vars"] = var
        self._play_source_template["gather_facts"] = gather_facts

        print("AD-HOC DEBUG", self._play_source_template)

        play = self._play(self._play_source_template)
        tqm = self._tqm()
        try:
            tqm.run(play)
        finally:
            if tqm is not None:
                tqm.cleanup()
            if self.loader:
                self.loader.cleanup_all_tmp_files()
            shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)

    def ansible_playbook(self, playbooks):
        pb = playbooks if isinstance(playbooks, list) else [playbooks]
        playbook = PlaybookExecutor(
            playbooks=pb,  # 注意这里是一个列表
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            passwords=dict(vault_pass=None))
        playbook._tqm = self._tqm()
        print("Playbook DEBUG", pb)
        playbook.run()

    def result(self, to_json=False):
        result_raw = None
        if self.results_callback is None:
            return result_raw
        else:
            result_raw = self.results_callback.result()

        if to_json:
            return json.dumps(result_raw, indent=4)
        else:
            return result_raw
class ANSRunner(object):
    def __init__(self,
                 hosts=constants.DEFAULT_HOST_LIST,
                 module_name=constants.DEFAULT_MODULE_NAME,
                 module_args=constants.DEFAULT_MODULE_ARGS,
                 forks=constants.DEFAULT_FORKS,
                 timeout=constants.DEFAULT_TIMEOUT,
                 pattern="all",
                 remote_user=constants.DEFAULT_REMOTE_USER,
                 module_path=None,
                 connection_type="smart",
                 become=None,
                 become_method=None,
                 become_user=None,
                 check=False,
                 passwords=None,
                 extra_vars=None,
                 private_key_file=None,
                 listtags=False,
                 listtasks=False,
                 listhosts=False,
                 ssh_common_args=None,
                 ssh_extra_args=None,
                 sftp_extra_args=None,
                 scp_extra_args=None,
                 verbosity=None,
                 syntax=False,
                 redisKey=None,
                 logId=None):
        self.Options = namedtuple("Options", [
            'listtags', 'listtasks', 'listhosts', 'syntax', 'connection',
            'module_path', 'forks', 'remote_user', 'private_key_file',
            'timeout', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args',
            'scp_extra_args', 'become', 'become_method', 'become_user',
            'verbosity', 'check', 'extra_vars', 'diff'
        ])
        self.results_raw = {}
        self.pattern = pattern
        self.module_name = module_name
        self.module_args = module_args
        self.gather_facts = 'no'
        self.options = self.Options(listtags=listtags,
                                    listtasks=listtasks,
                                    listhosts=listhosts,
                                    syntax=syntax,
                                    timeout=timeout,
                                    connection=connection_type,
                                    module_path=module_path,
                                    forks=forks,
                                    remote_user=remote_user,
                                    private_key_file=private_key_file,
                                    ssh_common_args=ssh_common_args or "",
                                    ssh_extra_args=ssh_extra_args or "",
                                    sftp_extra_args=sftp_extra_args,
                                    scp_extra_args=scp_extra_args,
                                    become=become,
                                    become_method=become_method,
                                    become_user=become_user,
                                    verbosity=verbosity,
                                    extra_vars=extra_vars or [],
                                    check=check,
                                    diff=False)
        self.redisKey = redisKey
        self.logId = logId
        self.loader = DataLoader()
        self.inventory = MyInventory(resource=hosts)
        self.variable_manager = VariableManager(self.loader, self.inventory)
        self.variable_manager.extra_vars = load_extra_vars(
            loader=self.loader, options=self.options)
        self.variable_manager.options_vars = load_options_vars(
            self.options, "")
        self.passwords = passwords or {}

    def run_model(self, host_list, module_name, module_args):
        if self.redisKey or self.logId:
            self.callback = ModelResultsCollectorToSave(
                self.redisKey, self.logId)
        else:
            self.callback = ModelResultsCollector()

        play_source = dict(
            name="Ansible Ad-hoc",
            hosts=host_list,
            gather_facts=self.gather_facts,
            tasks=[dict(action=dict(module=module_name, args=module_args))])
        play = Play().load(play_source,
                           loader=self.loader,
                           variable_manager=self.variable_manager)
        tqm = None
        try:
            tqm = TaskQueueManager(inventory=self.inventory,
                                   variable_manager=self.variable_manager,
                                   loader=self.loader,
                                   options=self.options,
                                   passwords=self.passwords,
                                   stdout_callback=self.callback)
            tqm._stdout_callback = self.callback
            constants.HOST_KEY_CHECKING = False  # 关闭第一次使用ansible连接客户端是输入命令
            tqm.run(play)
        except Exception as err:
            logger.error(msg=err)
        finally:
            if tqm is not None:
                tqm.cleanup()
            if self.loader:
                self.loader.cleanup_all_tmp_files()

    def run_playbook(self, host_list, playbook_path, extra_vars=dict()):
        """
        run ansible palybook
        """
        try:
            if self.redisKey or self.logId:
                self.callback = PlayBookResultsCollectorToSave(
                    self.redisKey, self.logId)
            else:
                self.callback = PlayBookResultsCollector()
            if isinstance(host_list, list):
                extra_vars['host'] = ','.join(host_list)
            else:
                extra_vars['host'] = host_list
            self.variable_manager.extra_vars = extra_vars
            executor = PlaybookExecutor(
                playbooks=[playbook_path],
                inventory=self.inventory,
                variable_manager=self.variable_manager,
                loader=self.loader,
                options=self.options,
                passwords=self.passwords,
            )
            executor._tqm._stdout_callback = self.callback
            constants.HOST_KEY_CHECKING = False  # 关闭第一次使用ansible连接客户端是输入命令
            constants.DEPRECATION_WARNINGS = False
            constants.RETRY_FILES_ENABLED = False
            executor.run()
        except Exception as err:
            logger.error(msg=err)
            return False

    def get_model_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

        for host, result in self.callback.host_unreachable.items():
            self.results_raw['unreachable'][host] = result._result

        return json.dumps(self.results_raw)

    def get_playbook_result(self):
        self.results_raw = {
            'skipped': {},
            'failed': {},
            'ok': {},
            "status": {},
            'unreachable': {},
            "changed": {}
        }

        for host, result in self.callback.task_ok.items():
            self.results_raw['ok'][host] = result

        for host, result in self.callback.task_failed.items():
            self.results_raw['failed'][host] = result

        for host, result in self.callback.task_status.items():
            self.results_raw['status'][host] = result

        for host, result in self.callback.task_changed.items():
            self.results_raw['changed'][host] = result

        for host, result in self.callback.task_skipped.items():
            self.results_raw['skipped'][host] = result

        for host, result in self.callback.task_unreachable.items():
            self.results_raw['unreachable'][host] = result
        return self.results_raw

    def handle_cmdb_data(self, data):
        '''处理setup返回结果方法'''
        data_list = []
        for k, v in json.loads(data).items():
            if k == "success":
                for x, y in v.items():
                    cmdb_data = {}
                    data = y.get('ansible_facts')
                    disk_size = 0
                    cpu = data['ansible_processor'][-1]
                    for k, v in data['ansible_devices'].items():
                        if k[0:2] in ['sd', 'hd', 'ss', 'vd']:
                            disk = int(
                                (int(v.get('sectors')) *
                                 int(v.get('sectorsize'))) / 1024 / 1024)
                            disk_size = disk_size + disk
                    cmdb_data['serial'] = data['ansible_product_serial'].split(
                    )[0]
                    cmdb_data['ip'] = x
                    cmdb_data['cpu'] = cpu.replace('@', '')
                    cmdb_data['ram_total'] = int(data['ansible_memtotal_mb'])
                    cmdb_data['disk_total'] = int(disk_size)
                    cmdb_data[
                        'system'] = data['ansible_distribution'] + ' ' + data[
                            'ansible_distribution_version'] + ' ' + data[
                                'ansible_userspace_bits']
                    cmdb_data['model'] = data['ansible_product_name'].split(
                        ':')[0]
                    cmdb_data['cpu_number'] = data['ansible_processor_count']
                    cmdb_data['vcpu_number'] = data['ansible_processor_vcpus']
                    cmdb_data['cpu_core'] = data['ansible_processor_cores']
                    cmdb_data['hostname'] = data['ansible_hostname']
                    cmdb_data['kernel'] = str(data['ansible_kernel'])
                    cmdb_data['manufacturer'] = data['ansible_system_vendor']
                    if data['ansible_selinux']:
                        cmdb_data['selinux'] = data['ansible_selinux'].get(
                            'status')
                    else:
                        cmdb_data['selinux'] = 'disabled'
                    cmdb_data['swap'] = int(data['ansible_swaptotal_mb'])
                    # 获取网卡资源
                    nks = []
                    for nk in data.keys():
                        if re.match(r"^ansible_(eth|bind|eno|ens|em)\d+?", nk):
                            device = data.get(nk).get('device')
                            try:
                                address = data.get(nk).get('ipv4').get(
                                    'address')
                            except:
                                address = 'unkown'
                            macaddress = data.get(nk).get('macaddress')
                            module = data.get(nk).get('module')
                            mtu = data.get(nk).get('mtu')
                            if data.get(nk).get('active'):
                                active = 1
                            else:
                                active = 0
                            nks.append({
                                "device": device,
                                "address": address,
                                "macaddress": macaddress,
                                "module": module,
                                "mtu": mtu,
                                "active": active
                            })
                    cmdb_data['status'] = 0
                    cmdb_data['nks'] = nks
                    data_list.append(cmdb_data)
            elif k == "unreachable":
                for x, y in v.items():
                    cmdb_data = {}
                    cmdb_data['status'] = 1
                    cmdb_data['ip'] = x
                    data_list.append(cmdb_data)
        if data_list:
            return data_list
        else:
            return False

    def handle_cmdb_crawHw_data(self, data):
        data_list = []
        for k, v in json.loads(data).items():
            if k == "success":
                for x, y in v.items():
                    cmdb_data = {}
                    cmdb_data['ip'] = x
                    data = y.get('ansible_facts')
                    cmdb_data['mem_info'] = data.get(
                        'ansible_mem_detailed_info')
                    cmdb_data['disk_info'] = data.get(
                        'ansible_disk_detailed_info')
                    data_list.append(cmdb_data)
        if data_list:
            return data_list
        else:
            return False

    def handle_model_data(self, data, module_name, module_args=None):
        '''处理ANSIBLE 模块输出内容'''
        module_data = json.loads(data)
        failed = module_data.get('failed')
        success = module_data.get('success')
        unreachable = module_data.get('unreachable')
        data_list = []
        if module_name == "raw":
            if failed:
                for x, y in failed.items():
                    data = {}
                    data['ip'] = x
                    try:
                        data['msg'] = y.get('stdout').replace(
                            '\t\t',
                            '<br>').replace('\r\n',
                                            '<br>').replace('\t', '<br>')
                    except:
                        data['msg'] = None
                    if y.get('rc') == 0:
                        data['status'] = 'succeed'
                    else:
                        data['status'] = 'failed'
                    data_list.append(data)
            elif success:
                for x, y in success.items():
                    data = {}
                    data['ip'] = x
                    try:
                        data['msg'] = y.get('stdout').replace(
                            '\t\t',
                            '<br>').replace('\r\n',
                                            '<br>').replace('\t', '<br>')
                    except:
                        data['msg'] = None
                    if y.get('rc') == 0:
                        data['status'] = 'succeed'
                    else:
                        data['status'] = 'failed'
                    data_list.append(data)

        elif module_name == "ping":
            if success:
                for x, y in success.items():
                    data = {}
                    data['ip'] = x
                    if y.get('ping'):
                        data['msg'] = y.get('ping')
                        data['status'] = 'succeed'
                    data_list.append(data)
        else:
            if success:
                for x, y in success.items():
                    data = {}
                    data['ip'] = x
                    if y.get('invocation'):
                        data['msg'] = "Ansible %s with %s execute success." % (
                            module_name, module_args)
                        data['status'] = 'succeed'
                    data_list.append(data)

            elif failed:
                for x, y in failed.items():
                    data = {}
                    data['ip'] = x
                    data['msg'] = y.get('msg')
                    data['status'] = 'failed'
                    data_list.append(data)

        if unreachable:
            for x, y in unreachable.items():
                data = {}
                data['ip'] = x
                data['msg'] = y.get('msg')
                data['status'] = 'failed'
                data_list.append(data)
        if data_list:
            return data_list
        else:
            return False
Exemple #32
0
class AnsExecuter():
    def __init__(self,inventory):
        self._loader = DataLoader()
        self._passwords = None
        context.CLIARGS = ImmutableDict(connection='smart', module_path=None, forks=1, become=None,  verbosity=5,
                                        sudo=None,sudo_user=None,ask_sudo_pass=None,
                                        become_method=None, become_user=None, check=False, diff=False,syntax=None,start_at_task=None)
        self._inventory = InventoryManager(loader=self._loader, sources=inventory)

        self._variable_manager = VariableManager(loader=self._loader, inventory=self._inventory)
        self.result_callback=ResultsCollectorJSONCallback()

    def run(self,hosts='localhost',module='ping',args='',timeout=0):
        tqm = TaskQueueManager(
            inventory=self._inventory,
            variable_manager=self._variable_manager,
            loader=self._loader,
            passwords=self._passwords,
            stdout_callback=self.result_callback,
        )
        play_source = dict(
            name='Ad-hoc',
            hosts=hosts,
            gather_facts='no',
            tasks=[
                dict(action=dict(module=module, args=args), register='shell_out'),
                #{'action':{'module':module,'args':args},'async':timeout,'poll':0},
                # dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}'))),
                # dict(action=dict(module='command', args=dict(cmd='/usr/bin/uptime'))),
            ]
        )
        play = Play().load(play_source, variable_manager=self._variable_manager, loader=self._loader)
        try:
            result = tqm.run(play)
        finally:
            tqm.cleanup()
            if self._loader:
                self._loader.cleanup_all_tmp_files()
        # Remove ansible tmpdir
        shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)

    def playbook(self,playbooks):
        """
        :param playbooks: list类型
        :return:
        """
        playbook=PlaybookExecutor(playbooks=playbooks,inventory=self._inventory,variable_manager=self._variable_manager,
                                  loader=self._loader,passwords=self._passwords)
        playbook._tqm._stdout_callback=self.result_callback
        result=playbook.run()

    def get_result(self):
        # print("UP ***********")
        # for host, result in self.result_callback.host_ok.items():
        #     print('{0} >>> {1}'.format(host, result._result['stdout']))
        #
        # print("FAILED *******")
        # for host, result in self.result_callback.host_failed.items():
        #     print('{0} >>> {1}'.format(host, result._result['msg']))
        #
        # print("DOWN *********")
        # for host, result in self.result_callback.host_unreachable.items():
        #     print('{0} >>> {1}'.format(host, result._result['msg']))

        result_raw = {"ok": {}, "failed": {}, "unreachable": {}, "skipped": {}, "status": {}}
        print("UP", "***********"*8)
        self.result_callback.host_ok.pop(0)
        for result in self.result_callback.host_ok:
            print(result)
        print("FAILED", "***********" * 8)
        for result in self.result_callback.host_failed:
            print(result)
        print("DOWN", "***********" * 8)
        for result in self.result_callback.host_unreachable:
            print(result)