Example #1
0
 def _register_play_vars(host, result):
     # when 'register' is used, persist the result in the vars cache
     # rather than the setup cache - vars should be transient between
     # playbook executions
     if 'stdout' in result and 'stdout_lines' not in result:
         result['stdout_lines'] = result['stdout'].splitlines()
     utils.update_hash(self.VARS_CACHE, host, {task.register: result})
Example #2
0
 def _save_play_facts(host, facts):
     # saves play facts in SETUP_CACHE, unless the module executed was
     # set_fact, in which case we add them to the VARS_CACHE
     if task.module_name == 'set_fact':
         utils.update_hash(self.VARS_CACHE, host, facts)
     else:
         utils.update_hash(self.SETUP_CACHE, host, facts)
Example #3
0
 def _save_play_facts(host, facts):
     # saves play facts in SETUP_CACHE, unless the module executed was
     # set_fact, in which case we add them to the VARS_CACHE
     if task.module_name in ('set_fact', 'include_vars'):
         utils.update_hash(self.VARS_CACHE, host, facts)
     else:
         utils.update_hash(self.SETUP_CACHE, host, facts)
Example #4
0
 def _register_play_vars(host, result):
     # when 'register' is used, persist the result in the vars cache
     # rather than the setup cache - vars should be transient between
     # playbook executions
     if 'stdout' in result and 'stdout_lines' not in result:
         result['stdout_lines'] = result['stdout'].splitlines()
     utils.update_hash(self.VARS_CACHE, host, {task.register: result})
 def _update_hash(self, hash, key, new_value):
     # If two or more nodes delegate to the same node and attempt to update
     # the fact-cache for that node simultaneously we need to lock using
     # mutex around the update_hash action to stop a collision.
     # Because instances of this callback plugin live within multiple subprocesses
     # during execution, we can't rely on a threading.RLock; nor can we use a
     # POSIX multiprocess.Lock object since there's no way to ensure that the
     # object is correctly created in the parent process.
     # Instead, we'll use a traditional file-based lock for the key item.
     with open("%s/.lock_%s" % (C.CACHE_PLUGIN_CONNECTION, key), "w+") as f:
         fcntl.flock(f, fcntl.LOCK_EX)
         utils.update_hash(hash, key, new_value)
 def _update_hash(self, hash, key, new_value):
     # If two or more nodes delegate to the same node and attempt to update
     # the fact-cache for that node simultaneously we need to lock using
     # mutex around the update_hash action to stop a collision.
     # Because instances of this callback plugin live within multiple subprocesses
     # during execution, we can't rely on a threading.RLock; nor can we use a
     # POSIX multiprocess.Lock object since there's no way to ensure that the
     # object is correctly created in the parent process.
     # Instead, we'll use a traditional file-based lock for the key item.
     with open("%s/.lock_%s" % (C.CACHE_PLUGIN_CONNECTION, key), "w+") as f:
         fcntl.flock(f, fcntl.LOCK_EX)
         utils.update_hash(hash, key, new_value)
Example #7
0
    def _do_setup_step(self, play):
        ''' get facts from the remote system '''

        host_list = self._trim_unavailable_hosts(play._play_hosts)

        if play.gather_facts is None and C.DEFAULT_GATHERING == 'smart':
            host_list = [h for h in host_list if h not in self.SETUP_CACHE or 'module_setup' not in self.SETUP_CACHE[h]]
            if len(host_list) == 0:
                return {}
        elif play.gather_facts is False or (play.gather_facts is None and C.DEFAULT_GATHERING == 'explicit'):
            return {}

        self.callbacks.on_setup()
        self.inventory.restrict_to(host_list)

        ansible.callbacks.set_task(self.callbacks, None)
        ansible.callbacks.set_task(self.runner_callbacks, None)

        # push any variables down to the system
        setup_results = ansible.runner.Runner(
            basedir=self.basedir,
            pattern=play.hosts,
            module_name='setup',
            module_args={},
            inventory=self.inventory,
            forks=self.forks,
            module_path=self.module_path,
            timeout=self.timeout,
            remote_user=play.remote_user,
            remote_pass=self.remote_pass,
            remote_port=play.remote_port,
            private_key_file=self.private_key_file,
            setup_cache=self.SETUP_CACHE,
            vars_cache=self.VARS_CACHE,
            callbacks=self.runner_callbacks,
            sudo=play.sudo,
            sudo_user=play.sudo_user,
            sudo_pass=self.sudo_pass,
            su=play.su,
            su_user=play.su_user,
            su_pass=self.su_pass,
            vault_pass=self.vault_password,
            transport=play.transport,
            is_playbook=True,
            module_vars=play.vars,
            default_vars=play.default_vars,
            check=self.check,
            diff=self.diff,
            accelerate=play.accelerate,
            accelerate_port=play.accelerate_port,
        ).run()
        self.stats.compute(setup_results, setup=True)

        self.inventory.lift_restriction()

        # now for each result, load into the setup cache so we can
        # let runner template out future commands
        setup_ok = setup_results.get('contacted', {})
        for (host, result) in setup_ok.iteritems():
            utils.update_hash(self.SETUP_CACHE, host, {'module_setup': True})
            utils.update_hash(self.SETUP_CACHE, host, result.get('ansible_facts', {}))
        return setup_results
Example #8
0
    def _do_setup_step(self, play):
        ''' get facts from the remote system '''

        host_list = self._trim_unavailable_hosts(play._play_hosts)

        if play.gather_facts is None and C.DEFAULT_GATHERING == 'smart':
            host_list = [
                h for h in host_list if h not in self.SETUP_CACHE
                or 'module_setup' not in self.SETUP_CACHE[h]
            ]
            if len(host_list) == 0:
                return {}
        elif play.gather_facts is False or (play.gather_facts is None and
                                            C.DEFAULT_GATHERING == 'explicit'):
            return {}

        self.callbacks.on_setup()
        self.inventory.restrict_to(host_list)

        ansible.callbacks.set_task(self.callbacks, None)
        ansible.callbacks.set_task(self.runner_callbacks, None)

        # push any variables down to the system
        setup_results = ansible.runner.Runner(
            basedir=self.basedir,
            pattern=play.hosts,
            module_name='setup',
            module_args={},
            inventory=self.inventory,
            forks=self.forks,
            module_path=self.module_path,
            timeout=self.timeout,
            remote_user=play.remote_user,
            remote_pass=self.remote_pass,
            remote_port=play.remote_port,
            private_key_file=self.private_key_file,
            setup_cache=self.SETUP_CACHE,
            vars_cache=self.VARS_CACHE,
            callbacks=self.runner_callbacks,
            become=play.become,
            become_method=play.become_method,
            become_user=play.become_user,
            become_pass=self.become_pass,
            vault_pass=self.vault_password,
            transport=play.transport,
            is_playbook=True,
            module_vars=play.vars,
            play_vars=play.vars,
            play_file_vars=play.vars_file_vars,
            role_vars=play.role_vars,
            default_vars=play.default_vars,
            check=self.check,
            diff=self.diff,
            accelerate=play.accelerate,
            accelerate_port=play.accelerate_port,
        ).run()
        self.stats.compute(setup_results, setup=True)

        self.inventory.lift_restriction()

        # now for each result, load into the setup cache so we can
        # let runner template out future commands
        setup_ok = setup_results.get('contacted', {})
        for (host, result) in setup_ok.iteritems():
            utils.update_hash(self.SETUP_CACHE, host, {'module_setup': True})
            utils.update_hash(self.SETUP_CACHE, host,
                              result.get('ansible_facts', {}))
        return setup_results
Example #9
0
    def _run_task(self, play, task, is_handler):
        ''' run a single task in the playbook and recursively run any subtasks.  '''

        ansible.callbacks.set_task(self.callbacks, task)
        ansible.callbacks.set_task(self.runner_callbacks, task)

        if task.role_name:
            name = '%s | %s' % (task.role_name, task.name)
        else:
            name = task.name

        self.callbacks.on_task_start(
            template(play.basedir,
                     name,
                     task.module_vars,
                     lookup_fatal=False,
                     filter_fatal=False), is_handler)
        if hasattr(self.callbacks, 'skip_task') and self.callbacks.skip_task:
            ansible.callbacks.set_task(self.callbacks, None)
            ansible.callbacks.set_task(self.runner_callbacks, None)
            return True

        # template ignore_errors
        cond = template(play.basedir,
                        task.ignore_errors,
                        task.module_vars,
                        expand_lists=False)
        task.ignore_errors = utils.check_conditional(
            cond,
            play.basedir,
            task.module_vars,
            fail_on_undefined=C.DEFAULT_UNDEFINED_VAR_BEHAVIOR)

        # load up an appropriate ansible runner to run the task in parallel
        results = self._run_task_internal(task)

        # if no hosts are matched, carry on
        hosts_remaining = True
        if results is None:
            hosts_remaining = False
            results = {}

        contacted = results.get('contacted', {})
        self.stats.compute(results, ignore_errors=task.ignore_errors)

        def _register_play_vars(host, result):
            # when 'register' is used, persist the result in the vars cache
            # rather than the setup cache - vars should be transient between playbook executions
            if 'stdout' in result and 'stdout_lines' not in result:
                result['stdout_lines'] = result['stdout'].splitlines()
            utils.update_hash(self.VARS_CACHE, host, {task.register: result})

        # add facts to the global setup cache
        for host, result in contacted.iteritems():
            if 'results' in result:
                # task ran with_ lookup plugin, so facts are encapsulated in
                # multiple list items in the results key
                for res in result['results']:
                    if type(res) == dict:
                        facts = res.get('ansible_facts', {})
                        utils.update_hash(self.SETUP_CACHE, host, facts)
            else:
                # when facts are returned, persist them in the setup cache
                facts = result.get('ansible_facts', {})
                utils.update_hash(self.SETUP_CACHE, host, facts)
            if task.register:
                _register_play_vars(host, result)

        # also have to register some failed, but ignored, tasks
        if task.ignore_errors and task.register:
            failed = results.get('failed', {})
            for host, result in failed.iteritems():
                _register_play_vars(host, result)

        # flag which notify handlers need to be run
        if len(task.notify) > 0:
            for host, results in results.get('contacted', {}).iteritems():
                if results.get('changed', False):
                    for handler_name in task.notify:
                        self._flag_handler(
                            play,
                            template(play.basedir, handler_name,
                                     task.module_vars), host)

        ansible.callbacks.set_task(self.callbacks, None)
        ansible.callbacks.set_task(self.runner_callbacks, None)
        return hosts_remaining
Example #10
0
    def _run_task(self, play, task, is_handler):
        ''' run a single task in the playbook and recursively run any subtasks.  '''

        ansible.callbacks.set_task(self.callbacks, task)
        ansible.callbacks.set_task(self.runner_callbacks, task)

        if task.role_name:
            name = '%s | %s' % (task.role_name, task.name)
        else:
            name = task.name

        self.callbacks.on_task_start(template(play.basedir, name, task.module_vars, lookup_fatal=False, filter_fatal=False), is_handler)
        if hasattr(self.callbacks, 'skip_task') and self.callbacks.skip_task:
            ansible.callbacks.set_task(self.callbacks, None)
            ansible.callbacks.set_task(self.runner_callbacks, None)
            return True

        # template ignore_errors
        cond = template(play.basedir, task.ignore_errors, task.module_vars, expand_lists=False)
        task.ignore_errors =  utils.check_conditional(cond, play.basedir, task.module_vars, fail_on_undefined=C.DEFAULT_UNDEFINED_VAR_BEHAVIOR)

        # load up an appropriate ansible runner to run the task in parallel
        results = self._run_task_internal(task)

        # if no hosts are matched, carry on
        hosts_remaining = True
        if results is None:
            hosts_remaining = False
            results = {}

        contacted = results.get('contacted', {})
        self.stats.compute(results, ignore_errors=task.ignore_errors)

        def _register_play_vars(host, result):
            # when 'register' is used, persist the result in the vars cache
            # rather than the setup cache - vars should be transient between playbook executions
            if 'stdout' in result and 'stdout_lines' not in result:
                result['stdout_lines'] = result['stdout'].splitlines()
            utils.update_hash(self.VARS_CACHE, host, {task.register: result})

        # add facts to the global setup cache
        for host, result in contacted.iteritems():
            if 'results' in result:
                # task ran with_ lookup plugin, so facts are encapsulated in
                # multiple list items in the results key
                for res in result['results']:
                    if type(res) == dict:
                        facts = res.get('ansible_facts', {})
                        utils.update_hash(self.SETUP_CACHE, host, facts)
            else:
                # when facts are returned, persist them in the setup cache
                facts = result.get('ansible_facts', {})
                utils.update_hash(self.SETUP_CACHE, host, facts)
            if task.register:
                _register_play_vars(host, result)

        # also have to register some failed, but ignored, tasks
        if task.ignore_errors and task.register:
            failed = results.get('failed', {})
            for host, result in failed.iteritems():
                _register_play_vars(host, result)

        # flag which notify handlers need to be run
        if len(task.notify) > 0:
            for host, results in results.get('contacted',{}).iteritems():
                if results.get('changed', False):
                    for handler_name in task.notify:
                        self._flag_handler(play, template(play.basedir, handler_name, task.module_vars), host)

        ansible.callbacks.set_task(self.callbacks, None)
        ansible.callbacks.set_task(self.runner_callbacks, None)
        return hosts_remaining