Returns the grain functions

      .. code-block:: python

          import salt.config
          import salt.loader

          __opts__ = salt.config.minion_config('/etc/salt/minion')
          grainfuncs = salt.loader.grain_funcs(__opts__)
9414
def grain_funcs(opts, proxy=None):
    '''
    
    '''
    ret = LazyLoader(
        _module_dirs(
            opts,
            'grains',
            'grain',
            ext_type_dirs='grains_dirs',
        ),
        opts,
        tag='grains',
    )
    ret.pack['__utils__'] = utils(opts, proxy=proxy)
    return ret
914961
def get_async_pillar(opts, grains, minion_id, saltenv=None, ext=None, funcs=None,
                     pillar_override=None, pillarenv=None,
                     extra_minion_data=None):
    '''
    
    '''
    file_client = opts['file_client']
    if opts.get('master_type') == 'disable' and file_client == 'remote':
        file_client = 'local'
    ptype = {
        'remote': AsyncRemotePillar,
        'local': AsyncPillar,
    }.get(file_client, AsyncPillar)
    return ptype(opts, grains, minion_id, saltenv, ext, functions=funcs,
                 pillar_override=pillar_override, pillarenv=pillarenv,
                 extra_minion_data=extra_minion_data)
1101579
def get_minion_data(minion, opts):
    '''
    
    '''
    grains = None
    pillar = None
    if opts.get('minion_data_cache', False):
        cache = salt.cache.factory(opts)
        if minion is None:
            for id_ in cache.list('minions'):
                data = cache.fetch('minions/{0}'.format(id_), 'data')
                if data is None:
                    continue
        else:
            data = cache.fetch('minions/{0}'.format(minion), 'data')
        if data is not None:
            grains = data.get('grains', None)
            pillar = data.get('pillar', None)
    return minion if minion else None, grains, pillar
1062989
def get_docs(self, arg=None):
        '''
        
        '''
        if arg:
            if '*' in arg:
                target_mod = arg
                _use_fnmatch = True
            else:
                target_mod = arg + '.' if not arg.endswith('.') else arg
                _use_fnmatch = False
            if _use_fnmatch:
                docs = [(fun, self.functions[fun].__doc__)
                        for fun in fnmatch.filter(self.functions, target_mod)]
            else:
                docs = [(fun, self.functions[fun].__doc__)
                        for fun in sorted(self.functions)
                        if fun == arg or fun.startswith(target_mod)]
        else:
            docs = [(fun, self.functions[fun].__doc__)
                    for fun in sorted(self.functions)]
        docs = dict(docs)
        return salt.utils.doc.strip_rst(docs)
466071
def pillars(opts, functions, context=None):
    '''
    
    '''
    ret = LazyLoader(_module_dirs(opts, 'pillar'),
                     opts,
                     tag='pillar',
                     pack={'__salt__': functions,
                           '__context__': context,
                           '__utils__': utils(opts)})
    ret.pack['__ext_pillar__'] = ret
    return FilterDictWrapper(ret, '.ext_pillar')
627215
def load_modules(self, data=None, proxy=None):
        '''
        
        '''
        log.info('Loading fresh modules for state activity')
        # Load a modified client interface that looks like the interface used
        # from the minion, but uses remote execution
        #
        self.functions = salt.client.FunctionWrapper(
                self.opts,
                self.opts['id']
                )
        # Load the states, but they should not be used in this class apart
        # from inspection
        self.utils = salt.loader.utils(self.opts)
        self.serializers = salt.loader.serializers(self.opts)
        self.states = salt.loader.states(self.opts, self.functions, self.utils, self.serializers)
        self.rend = salt.loader.render(self.opts, self.functions, states=self.states, context=self.state_con)
252452
def ext_pillar(minion_id,  # pylint: disable=W0613
               pillar,  # pylint: disable=W0613
               conf):
    '''
    
    '''
    vs = varstack.Varstack(config_filename=conf)
    return vs.evaluate(__grains__)
293209
def get_functions(self):
        
        instances = self._get_instances(ast.FunctionDef)
        instances = [
            PyFunction(instance, self.package)
            for instance in instances
        ]
        return instances
1137552
def _pillar(self, load):
        '''
        
        '''
        if any(key not in load for key in ('id', 'grains')):
            return False
#        pillar = salt.pillar.Pillar(
        log.debug('Master _pillar using ext: %s', load.get('ext'))
        pillar = salt.pillar.get_pillar(
                self.opts,
                load['grains'],
                load['id'],
                load.get('saltenv', load.get('env')),
                load.get('ext'),
                self.mminion.functions,
                pillar_override=load.get('pillar_override', {}))
        data = pillar.compile_pillar()
        if self.opts.get('minion_data_cache', False):
            self.cache.store('minions/{0}'.format(load['id']),
                             'data',
                             {'grains': load['grains'], 'pillar': data})
            if self.opts.get('minion_data_cache_events') is True:
                self.event.fire_event({'comment': 'Minion data cache refresh'}, salt.utils.event.tagify(load['id'], 'refresh', 'minion'))
        return data
768107
def _thread_return(cls, minion_instance, opts, data):
        '''
        
        '''
        fn_ = os.path.join(minion_instance.proc_dir, data['jid'])

        if opts['multiprocessing'] and not salt.utils.platform.is_windows():
            # Shutdown the multiprocessing before daemonizing
            salt.log.setup.shutdown_multiprocessing_logging()

            salt.utils.process.daemonize_if(opts)

            # Reconfigure multiprocessing logging after daemonizing
            salt.log.setup.setup_multiprocessing_logging()

        salt.utils.process.appendproctitle('{0}._thread_return {1}'.format(cls.__name__, data['jid']))

        sdata = {'pid': os.getpid()}
        sdata.update(data)
        log.info('Starting a new job %s with PID %s', data['jid'], sdata['pid'])
        with salt.utils.files.fopen(fn_, 'w+b') as fp_:
            fp_.write(minion_instance.serial.dumps(sdata))
        ret = {'success': False}
        function_name = data['fun']
        executors = data.get('module_executors') or \
                    getattr(minion_instance, 'module_executors', []) or \
                    opts.get('module_executors', ['direct_call'])
        allow_missing_funcs = any([
            minion_instance.executors['{0}.allow_missing_func'.format(executor)](function_name)
            for executor in executors
            if '{0}.allow_missing_func' in minion_instance.executors
        ])
        if function_name in minion_instance.functions or allow_missing_funcs is True:
            try:
                minion_blackout_violation = False
                if minion_instance.connected and minion_instance.opts['pillar'].get('minion_blackout', False):
                    whitelist = minion_instance.opts['pillar'].get('minion_blackout_whitelist', [])
                    # this minion is blacked out. Only allow saltutil.refresh_pillar and the whitelist
                    if function_name != 'saltutil.refresh_pillar' and function_name not in whitelist:
                        minion_blackout_violation = True
                # use minion_blackout_whitelist from grains if it exists
                if minion_instance.opts['grains'].get('minion_blackout', False):
                    whitelist = minion_instance.opts['grains'].get('minion_blackout_whitelist', [])
                    if function_name != 'saltutil.refresh_pillar' and function_name not in whitelist:
                        minion_blackout_violation = True
                if minion_blackout_violation:
                    raise SaltInvocationError('Minion in blackout mode. Set \'minion_blackout\' '
                                             'to False in pillar or grains to resume operations. Only '
                                             'saltutil.refresh_pillar allowed in blackout mode.')

                if function_name in minion_instance.functions:
                    func = minion_instance.functions[function_name]
                    args, kwargs = load_args_and_kwargs(
                        func,
                        data['arg'],
                        data)
                else:
                    # only run if function_name is not in minion_instance.functions and allow_missing_funcs is True
                    func = function_name
                    args, kwargs = data['arg'], data
                minion_instance.functions.pack['__context__']['retcode'] = 0
                if isinstance(executors, six.string_types):
                    executors = [executors]
                elif not isinstance(executors, list) or not executors:
                    raise SaltInvocationError("Wrong executors specification: {0}. String or non-empty list expected".
                        format(executors))
                if opts.get('sudo_user', '') and executors[-1] != 'sudo':
                    executors[-1] = 'sudo'  # replace the last one with sudo
                log.trace('Executors list %s', executors)  # pylint: disable=no-member

                for name in executors:
                    fname = '{0}.execute'.format(name)
                    if fname not in minion_instance.executors:
                        raise SaltInvocationError("Executor '{0}' is not available".format(name))
                    return_data = minion_instance.executors[fname](opts, data, func, args, kwargs)
                    if return_data is not None:
                        break

                if isinstance(return_data, types.GeneratorType):
                    ind = 0
                    iret = {}
                    for single in return_data:
                        if isinstance(single, dict) and isinstance(iret, dict):
                            iret.update(single)
                        else:
                            if not iret:
                                iret = []
                            iret.append(single)
                        tag = tagify([data['jid'], 'prog', opts['id'], six.text_type(ind)], 'job')
                        event_data = {'return': single}
                        minion_instance._fire_master(event_data, tag)
                        ind += 1
                    ret['return'] = iret
                else:
                    ret['return'] = return_data

                retcode = minion_instance.functions.pack['__context__'].get(
                    'retcode',
                    salt.defaults.exitcodes.EX_OK
                )
                if retcode == salt.defaults.exitcodes.EX_OK:
                    # No nonzero retcode in __context__ dunder. Check if return
                    # is a dictionary with a "result" or "success" key.
                    try:
                        func_result = all(return_data.get(x, True)
                                          for x in ('result', 'success'))
                    except Exception:
                        # return data is not a dict
                        func_result = True
                    if not func_result:
                        retcode = salt.defaults.exitcodes.EX_GENERIC

                ret['retcode'] = retcode
                ret['success'] = retcode == salt.defaults.exitcodes.EX_OK
            except CommandNotFoundError as exc:
                msg = 'Command required for \'{0}\' not found'.format(
                    function_name
                )
                log.debug(msg, exc_info=True)
                ret['return'] = '{0}: {1}'.format(msg, exc)
                ret['out'] = 'nested'
                ret['retcode'] = salt.defaults.exitcodes.EX_GENERIC
            except CommandExecutionError as exc:
                log.error(
                    'A command in \'%s\' had a problem: %s',
                    function_name, exc,
                    exc_info_on_loglevel=logging.DEBUG
                )
                ret['return'] = 'ERROR: {0}'.format(exc)
                ret['out'] = 'nested'
                ret['retcode'] = salt.defaults.exitcodes.EX_GENERIC
            except SaltInvocationError as exc:
                log.error(
                    'Problem executing \'%s\': %s',
                    function_name, exc,
                    exc_info_on_loglevel=logging.DEBUG
                )
                ret['return'] = 'ERROR executing \'{0}\': {1}'.format(
                    function_name, exc
                )
                ret['out'] = 'nested'
                ret['retcode'] = salt.defaults.exitcodes.EX_GENERIC
            except TypeError as exc:
                msg = 'Passed invalid arguments to {0}: {1}\n{2}'.format(
                    function_name, exc, func.__doc__ or ''
                )
                log.warning(msg, exc_info_on_loglevel=logging.DEBUG)
                ret['return'] = msg
                ret['out'] = 'nested'
                ret['retcode'] = salt.defaults.exitcodes.EX_GENERIC
            except Exception:
                msg = 'The minion function caused an exception'
                log.warning(msg, exc_info_on_loglevel=True)
                salt.utils.error.fire_exception(salt.exceptions.MinionError(msg), opts, job=data)
                ret['return'] = '{0}: {1}'.format(msg, traceback.format_exc())
                ret['out'] = 'nested'
                ret['retcode'] = salt.defaults.exitcodes.EX_GENERIC
        else:
            docs = minion_instance.functions['sys.doc']('{0}*'.format(function_name))
            if docs:
                docs[function_name] = minion_instance.functions.missing_fun_string(function_name)
                ret['return'] = docs
            else:
                ret['return'] = minion_instance.functions.missing_fun_string(function_name)
                mod_name = function_name.split('.')[0]
                if mod_name in minion_instance.function_errors:
                    ret['return'] += ' Possible reasons: \'{0}\''.format(
                        minion_instance.function_errors[mod_name]
                    )
            ret['success'] = False
            ret['retcode'] = salt.defaults.exitcodes.EX_GENERIC
            ret['out'] = 'nested'

        ret['jid'] = data['jid']
        ret['fun'] = data['fun']
        ret['fun_args'] = data['arg']
        if 'master_id' in data:
            ret['master_id'] = data['master_id']
        if 'metadata' in data:
            if isinstance(data['metadata'], dict):
                ret['metadata'] = data['metadata']
            else:
                log.warning('The metadata parameter must be a dictionary. Ignoring.')
        if minion_instance.connected:
            minion_instance._return_pub(
                ret,
                timeout=minion_instance._return_retry_timer()
            )

        # Add default returners from minion config
        # Should have been coverted to comma-delimited string already
        if isinstance(opts.get('return'), six.string_types):
            if data['ret']:
                data['ret'] = ','.join((data['ret'], opts['return']))
            else:
                data['ret'] = opts['return']

        log.debug('minion return: %s', ret)
        # TODO: make a list? Seems odd to split it this late :/
        if data['ret'] and isinstance(data['ret'], six.string_types):
            if 'ret_config' in data:
                ret['ret_config'] = data['ret_config']
            if 'ret_kwargs' in data:
                ret['ret_kwargs'] = data['ret_kwargs']
            ret['id'] = opts['id']
            for returner in set(data['ret'].split(',')):
                try:
                    returner_str = '{0}.returner'.format(returner)
                    if returner_str in minion_instance.returners:
                        minion_instance.returners[returner_str](ret)
                    else:
                        returner_err = minion_instance.returners.missing_fun_string(returner_str)
                        log.error(
                            'Returner %s could not be loaded: %s',
                            returner_str, returner_err
                        )
                except Exception as exc:
                    log.exception(
                        'The return failed for job %s: %s', data['jid'], exc
                    )
283796
def match(tgt, functions=None, opts=None):
    '''
    
    '''
    if not opts:
        opts = __opts__
    if functions is None:
        utils = salt.loader.utils(opts)
        functions = salt.loader.minion_mods(opts, utils=utils)
    comps = tgt.split(':')
    if len(comps) < 2:
        return False
    val = functions['data.getval'](comps[0])
    if val is None:
        # The value is not defined
        return False
    if isinstance(val, list):
        # We are matching a single component to a single list member
        for member in val:
            if fnmatch.fnmatch(six.text_type(member).lower(), comps[1].lower()):
                return True
        return False
    if isinstance(val, dict):
        if comps[1] in val:
            return True
        return False
    return bool(fnmatch.fnmatch(
        val,
        comps[1],
    ))
932489
def __gen_opts(self, opts_in, grains, saltenv=None, ext=None, pillarenv=None):
        '''
        
        '''
        opts = copy.deepcopy(opts_in)
        opts['file_client'] = 'local'
        if not grains:
            opts['grains'] = {}
        else:
            opts['grains'] = grains
        # Allow minion/CLI saltenv/pillarenv to take precedence over master
        opts['saltenv'] = saltenv \
            if saltenv is not None \
            else opts.get('saltenv')
        opts['pillarenv'] = pillarenv \
            if pillarenv is not None \
            else opts.get('pillarenv')
        opts['id'] = self.minion_id
        if opts['state_top'].startswith('salt://'):
            opts['state_top'] = opts['state_top']
        elif opts['state_top'].startswith('/'):
            opts['state_top'] = salt.utils.url.create(opts['state_top'][1:])
        else:
            opts['state_top'] = salt.utils.url.create(opts['state_top'])
        if self.ext and self.__valid_on_demand_ext_pillar(opts):
            if 'ext_pillar' in opts:
                opts['ext_pillar'].append(self.ext)
            else:
                opts['ext_pillar'] = [self.ext]
        if '__env__' in opts['pillar_roots']:
            env = opts.get('pillarenv') or opts.get('saltenv') or 'base'
            if env not in opts['pillar_roots']:
                log.debug("pillar environment '%s' maps to __env__ pillar_roots directory", env)
                opts['pillar_roots'][env] = opts['pillar_roots'].pop('__env__')
            else:
                log.debug("pillar_roots __env__ ignored (environment '%s' found in pillar_roots)",
                          env)
                opts['pillar_roots'].pop('__env__')
        return opts
171770
def ssh_wrapper(opts, functions=None, context=None):
    '''
    
    '''
    return LazyLoader(
        _module_dirs(
            opts,
            'wrapper',
            base_path=os.path.join(SALT_BASE_PATH, os.path.join('client', 'ssh')),
        ),
        opts,
        tag='wrapper',
        pack={
            '__salt__': functions,
            '__grains__': opts.get('grains', {}),
            '__pillar__': opts.get('pillar', {}),
            '__context__': context,
            },
    )
751162
def _load_cached_grains(opts, cfn):
    '''
    
    '''
    if not os.path.isfile(cfn):
        log.debug('Grains cache file does not exist.')
        return None

    grains_cache_age = int(time.time() - os.path.getmtime(cfn))
    if grains_cache_age > opts.get('grains_cache_expiration', 300):
        log.debug(
            'Grains cache last modified %s seconds ago and cache '
            'expiration is set to %s. Grains cache expired. '
            'Refreshing.',
            grains_cache_age, opts.get('grains_cache_expiration', 300)
        )
        return None

    if opts.get('refresh_grains_cache', False):
        log.debug('refresh_grains_cache requested, Refreshing.')
        return None

    log.debug('Retrieving grains from cache')
    try:
        serial = salt.payload.Serial(opts)
        with salt.utils.files.fopen(cfn, 'rb') as fp_:
            cached_grains = salt.utils.data.decode(serial.load(fp_), preserve_tuples=True)
        if not cached_grains:
            log.debug('Cached grains are empty, cache might be corrupted. Refreshing.')
            return None

        return cached_grains
    except (IOError, OSError):
        return None
479901
def _zfs_pool_data():
    '''
    
    '''
    grains = {}

    # collect zpool data
    zpool_list_cmd = __utils__['zfs.zpool_command'](
        'list',
        flags=['-H'],
        opts={'-o': 'name,size'},
    )
    for zpool in __salt__['cmd.run'](zpool_list_cmd, ignore_retcode=True).splitlines():
        if 'zpool' not in grains:
            grains['zpool'] = {}
        zpool = zpool.split()
        grains['zpool'][zpool[0]] = __utils__['zfs.to_size'](zpool[1], False)

    # return grain data
    return grains
1099983
def _get_policies(minion_id, config):
    '''
    
    '''
    _, grains, _ = salt.utils.minions.get_minion_data(minion_id, __opts__)
    policy_patterns = config.get(
                                 'policies',
                                 ['saltstack/minion/{minion}', 'saltstack/minions']
                                )
    mappings = {'minion': minion_id, 'grains': grains or {}}

    policies = []
    for pattern in policy_patterns:
        try:
            for expanded_pattern in _expand_pattern_lists(pattern, **mappings):
                policies.append(
                                expanded_pattern.format(**mappings)
                                                .lower()  # Vault requirement
                               )
        except KeyError:
            log.warning('Could not resolve policy pattern %s', pattern)

    log.debug('%s policies: %s', minion_id, policies)
    return policies
154873
def get_minions(returner):
    '''
    
    '''
    returners = salt.loader.returners(__opts__, __salt__)
    return returners['{0}.get_minions'.format(returner)]()