Deploy salt minion during create()
486729
def _deploy_salt_minion(name, session, vm_):
    '''
    
    '''
    # Get bootstrap values
    vm_['ssh_host'] = get_vm_ip(name, session)
    vm_['user'] = vm_.get('user', 'root')
    vm_['password'] = vm_.get('password', 'p@ssw0rd!')
    vm_['provider'] = vm_.get('provider', 'xen')
    log.debug('%s has IP of %s', name, vm_['ssh_host'])
    # Bootstrap Salt minion!
    if vm_['ssh_host'] is not None:
        log.info('Installing Salt minion on %s', name)
        boot_ret = __utils__['cloud.bootstrap'](vm_, __opts__)
        log.debug('boot return: %s', boot_ret)
416880
def salt_support():
    '''
    
    '''

    import salt.cli.support.collector
    if '' in sys.path:
        sys.path.remove('')
    client = salt.cli.support.collector.SaltSupport()
    _install_signal_handlers(client)
    client.run()
72889
def run(self):
        '''
        
        '''
        import salt.client
        self.parse_args()

        if self.config['log_level'] not in ('quiet', ):
            # Setup file logging!
            self.setup_logfile_logger()
            verify_log(self.config)

        try:
            # We don't need to bail on config file permission errors
            # if the CLI process is run with the -a flag
            skip_perm_errors = self.options.eauth != ''

            self.local_client = salt.client.get_local_client(
                self.get_config_file_path(),
                skip_perm_errors=skip_perm_errors,
                auto_reconnect=True)
        except SaltClientError as exc:
            self.exit(2, '{0}\n'.format(exc))
            return

        if self.options.batch or self.options.static:
            # _run_batch() will handle all output and
            # exit with the appropriate error condition
            # Execution will not continue past this point
            # in batch mode.
            self._run_batch()
            return

        if self.options.preview_target:
            minion_list = self._preview_target()
            self._output_ret(minion_list, self.config.get('output', 'nested'))
            return

        if self.options.timeout <= 0:
            self.options.timeout = self.local_client.opts['timeout']

        kwargs = {
            'tgt': self.config['tgt'],
            'fun': self.config['fun'],
            'arg': self.config['arg'],
            'timeout': self.options.timeout,
            'show_timeout': self.options.show_timeout,
            'show_jid': self.options.show_jid}

        if 'token' in self.config:
            import salt.utils.files
            try:
                with salt.utils.files.fopen(os.path.join(self.config['cachedir'], '.root_key'), 'r') as fp_:
                    kwargs['key'] = fp_.readline()
            except IOError:
                kwargs['token'] = self.config['token']

        kwargs['delimiter'] = self.options.delimiter

        if self.selected_target_option:
            kwargs['tgt_type'] = self.selected_target_option
        else:
            kwargs['tgt_type'] = 'glob'

        # If batch_safe_limit is set, check minions matching target and
        # potentially switch to batch execution
        if self.options.batch_safe_limit > 1:
            if len(self._preview_target()) >= self.options.batch_safe_limit:
                salt.utils.stringutils.print_cli('\nNOTICE: Too many minions targeted, switching to batch execution.')
                self.options.batch = self.options.batch_safe_size
                self._run_batch()
                return

        if getattr(self.options, 'return'):
            kwargs['ret'] = getattr(self.options, 'return')

        if getattr(self.options, 'return_config'):
            kwargs['ret_config'] = getattr(self.options, 'return_config')

        if getattr(self.options, 'return_kwargs'):
            kwargs['ret_kwargs'] = yamlify_arg(
                    getattr(self.options, 'return_kwargs'))

        if getattr(self.options, 'module_executors'):
            kwargs['module_executors'] = yamlify_arg(getattr(self.options, 'module_executors'))

        if getattr(self.options, 'executor_opts'):
            kwargs['executor_opts'] = yamlify_arg(getattr(self.options, 'executor_opts'))

        if getattr(self.options, 'metadata'):
            kwargs['metadata'] = yamlify_arg(
                    getattr(self.options, 'metadata'))

        # If using eauth and a token hasn't already been loaded into
        # kwargs, prompt the user to enter auth credentials
        if 'token' not in kwargs and 'key' not in kwargs and self.options.eauth:
            # This is expensive. Don't do it unless we need to.
            import salt.auth
            resolver = salt.auth.Resolver(self.config)
            res = resolver.cli(self.options.eauth)
            if self.options.mktoken and res:
                tok = resolver.token_cli(
                        self.options.eauth,
                        res
                        )
                if tok:
                    kwargs['token'] = tok.get('token', '')
            if not res:
                sys.stderr.write('ERROR: Authentication failed\n')
                sys.exit(2)
            kwargs.update(res)
            kwargs['eauth'] = self.options.eauth

        if self.config['async']:
            jid = self.local_client.cmd_async(**kwargs)
            salt.utils.stringutils.print_cli('Executed command with job ID: {0}'.format(jid))
            return

        # local will be None when there was an error
        if not self.local_client:
            return

        retcodes = []
        errors = []

        try:
            if self.options.subset:
                cmd_func = self.local_client.cmd_subset
                kwargs['sub'] = self.options.subset
                kwargs['cli'] = True
            else:
                cmd_func = self.local_client.cmd_cli

            if self.options.progress:
                kwargs['progress'] = True
                self.config['progress'] = True
                ret = {}
                for progress in cmd_func(**kwargs):
                    out = 'progress'
                    try:
                        self._progress_ret(progress, out)
                    except LoaderError as exc:
                        raise SaltSystemExit(exc)
                    if 'return_count' not in progress:
                        ret.update(progress)
                self._progress_end(out)
                self._print_returns_summary(ret)
            elif self.config['fun'] == 'sys.doc':
                ret = {}
                out = ''
                for full_ret in self.local_client.cmd_cli(**kwargs):
                    ret_, out, retcode = self._format_ret(full_ret)
                    ret.update(ret_)
                self._output_ret(ret, out, retcode=retcode)
            else:
                if self.options.verbose:
                    kwargs['verbose'] = True
                ret = {}
                for full_ret in cmd_func(**kwargs):
                    try:
                        ret_, out, retcode = self._format_ret(full_ret)
                        retcodes.append(retcode)
                        self._output_ret(ret_, out, retcode=retcode)
                        ret.update(full_ret)
                    except KeyError:
                        errors.append(full_ret)

            # Returns summary
            if self.config['cli_summary'] is True:
                if self.config['fun'] != 'sys.doc':
                    if self.options.output is None:
                        self._print_returns_summary(ret)
                        self._print_errors_summary(errors)

            # NOTE: Return code is set here based on if all minions
            # returned 'ok' with a retcode of 0.
            # This is the final point before the 'salt' cmd returns,
            # which is why we set the retcode here.
            if not all(exit_code == salt.defaults.exitcodes.EX_OK for exit_code in retcodes):
                sys.stderr.write('ERROR: Minions returned with non-zero exit code\n')
                sys.exit(salt.defaults.exitcodes.EX_GENERIC)

        except (AuthenticationError,
                AuthorizationError,
                SaltInvocationError,
                EauthAuthenticationError,
                SaltClientError) as exc:
            ret = six.text_type(exc)
            self._output_ret(ret, '', retcode=1)
1082121
def save_minions(jid, minions, syndic_id=None):
    '''
    
    '''
    # Ensure we have a list for Python 3 compatability
    minions = list(minions)

    log.debug(
        'Adding minions for job %s%s: %s',
        jid,
        ' from syndic master \'{0}\''.format(syndic_id) if syndic_id else '',
        minions
    )
    serial = salt.payload.Serial(__opts__)

    jid_dir = salt.utils.jid.jid_dir(jid, _job_dir(), __opts__['hash_type'])

    try:
        if not os.path.exists(jid_dir):
            os.makedirs(jid_dir)
    except OSError as exc:
        if exc.errno == errno.EEXIST:
            # rarely, the directory can be already concurrently created between
            # the os.path.exists and the os.makedirs lines above
            pass
        else:
            raise

    if syndic_id is not None:
        minions_path = os.path.join(
            jid_dir,
            SYNDIC_MINIONS_P.format(syndic_id)
        )
    else:
        minions_path = os.path.join(jid_dir, MINIONS_P)

    try:
        if not os.path.exists(jid_dir):
            try:
                os.makedirs(jid_dir)
            except OSError:
                pass
        with salt.utils.files.fopen(minions_path, 'w+b') as wfh:
            serial.dump(minions, wfh)
    except IOError as exc:
        log.error(
            'Failed to write minion list %s to job cache file %s: %s',
            minions, minions_path, exc
        )
556288
def create(vm_, call=None):
    '''
    '''
    prov = get_configured_provider(vm_)
    if not prov:
        return
    # we cant use profile as a configuration key as it conflicts
    # with salt cloud internals
    profile = vm_.get(
        'lxc_profile',
        vm_.get('container_profile', None))

    event_data = vm_.copy()
    event_data['profile'] = profile

    __utils__['cloud.fire_event'](
        'event',
        'starting create',
        'salt/cloud/{0}/creating'.format(vm_['name']),
        args=__utils__['cloud.filter_event']('creating', event_data, ['name', 'profile', 'provider', 'driver']),
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    ret = {'name': vm_['name'], 'changes': {}, 'result': True, 'comment': ''}
    if 'pub_key' not in vm_ and 'priv_key' not in vm_:
        log.debug('Generating minion keys for %s', vm_['name'])
        vm_['priv_key'], vm_['pub_key'] = salt.utils.cloud.gen_keys(
            salt.config.get_cloud_config_value(
                'keysize', vm_, __opts__))
    # get the minion key pair to distribute back to the container
    kwarg = copy.deepcopy(vm_)
    kwarg['host'] = prov['target']
    kwarg['profile'] = profile

    __utils__['cloud.fire_event'](
        'event',
        'requesting instance',
        'salt/cloud/{0}/requesting'.format(vm_['name']),
        args=__utils__['cloud.filter_event']('requesting', vm_, ['name', 'profile', 'provider', 'driver']),
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    cret = _runner().cmd('lxc.cloud_init', [vm_['name']], kwarg=kwarg)
    ret['runner_return'] = cret
    ret['result'] = cret['result']
    if not ret['result']:
        ret['Error'] = 'Error while creating {0},'.format(vm_['name'])
    else:
        ret['changes']['created'] = 'created'

    # When using cloud states to manage LXC containers
    # __opts__['profile'] is not implicitly reset between operations
    # on different containers. However list_nodes will hide container
    # if profile is set in opts assuming that it have to be created.
    # But in cloud state we do want to check at first if it really
    # exists hence the need to remove profile from global opts once
    # current container is created.
    if 'profile' in __opts__:
        __opts__['internal_lxc_profile'] = __opts__['profile']
        del __opts__['profile']

    __utils__['cloud.fire_event'](
        'event',
        'created instance',
        'salt/cloud/{0}/created'.format(vm_['name']),
        args=__utils__['cloud.filter_event']('created', vm_, ['name', 'profile', 'provider', 'driver']),
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    return ret
958142
def save_load(jid, load, minions=None):
    '''
    
    '''
    serv = _get_serv(ret=None)
    serv.set(jid, salt.utils.json.dumps(load))
    _append_list(serv, 'jids', jid)
774006
def tune_in_no_block(self):
        '''
        
        '''
        # Instantiate the local client
        self.local = salt.client.get_local_client(
                self.opts['_minion_conf_file'], io_loop=self.io_loop)

        # add handler to subscriber
        self.pub_channel.on_recv(self._process_cmd_socket)
146653
def proxy_minion_process(queue):
    '''
    
    '''
    import salt.cli.daemons
    import salt.utils.platform
    # salt_minion spawns this function in a new process

    lock = threading.RLock()

    def suicide_when_without_parent(parent_pid):
        '''
        Have the minion suicide if the parent process is gone

        NOTE: there is a small race issue where the parent PID could be replace
        with another process with the same PID!
        '''
        while lock.acquire(blocking=False):
            lock.release()
            time.sleep(5)
            try:
                # check pid alive (Unix only trick!)
                os.kill(parent_pid, 0)
            except OSError:
                # forcibly exit, regular sys.exit raises an exception-- which
                # isn't sufficient in a thread
                os._exit(999)

    try:
        if not salt.utils.platform.is_windows():
            thread = threading.Thread(target=suicide_when_without_parent, args=(os.getppid(),))
            thread.start()

        restart = False
        proxyminion = None
        status = salt.defaults.exitcodes.EX_OK
        proxyminion = salt.cli.daemons.ProxyMinion()
        proxyminion.start()
    except (Exception, SaltClientError, SaltReqTimeoutError, SaltSystemExit) as exc:
        log.error('Proxy Minion failed to start: ', exc_info=True)
        restart = True
        # status is superfluous since the process will be restarted
        status = salt.defaults.exitcodes.SALT_KEEPALIVE
    except SystemExit as exc:
        restart = False
        status = exc.code
    finally:
        lock.acquire(blocking=True)

    if restart is True:
        log.warning('** Restarting proxy minion **')
        delay = 60
        if proxyminion is not None:
            if hasattr(proxyminion, 'config'):
                delay = proxyminion.config.get('random_reauth_delay', 60)
        random_delay = randint(1, delay)
        log.info('Sleeping random_reauth_delay of %s seconds', random_delay)
        # preform delay after minion resources have been cleaned
        queue.put(random_delay)
    else:
        queue.put(0)
    sys.exit(status)
95361
def _handle_minion_event(self, load):
        '''
        
        '''
        id_ = load['id']
        if load.get('tag', '') == '_salt_error':
            log.error(
                'Received minion error from [%s]: %s',
                id_, load['data']['message']
            )

        for event in load.get('events', []):
            event_data = event.get('data', {})
            if 'minions' in event_data:
                jid = event_data.get('jid')
                if not jid:
                    continue
                minions = event_data['minions']
                try:
                    salt.utils.job.store_minions(
                        self.opts,
                        jid,
                        minions,
                        mminion=self.mminion,
                        syndic_id=id_)
                except (KeyError, salt.exceptions.SaltCacheError) as exc:
                    log.error(
                        'Could not add minion(s) %s for job %s: %s',
                        minions, jid, exc
                    )
1116207
def pillar_refresh(self, force_refresh=False, notify=False):
        '''
        
        '''
        if self.connected:
            log.debug('Refreshing pillar. Notify: %s', notify)
            async_pillar = salt.pillar.get_async_pillar(
                self.opts,
                self.opts['grains'],
                self.opts['id'],
                self.opts['saltenv'],
                pillarenv=self.opts.get('pillarenv'),
            )
            try:
                self.opts['pillar'] = yield async_pillar.compile_pillar()
                if notify:
                    evt = salt.utils.event.get_event('minion', opts=self.opts, listen=False)
                    evt.fire_event({'complete': True}, tag=salt.defaults.events.MINION_PILLAR_COMPLETE)
            except SaltClientError:
                # Do not exit if a pillar refresh fails.
                log.error('Pillar data could not be refreshed. '
                          'One or more masters may be down!')
            finally:
                async_pillar.destroy()
        self.module_refresh(force_refresh, notify)
        self.matchers_refresh()
        self.beacons_refresh()
955622
def process_presence_events(self, salt_data, token, opts):
        '''
        
        '''
        log.debug('In presence')
        changed = False

        # check if any connections were dropped
        if set(salt_data['data'].get('lost', [])):
            dropped_minions = set(salt_data['data'].get('lost', []))
        else:
            dropped_minions = set(self.minions) - set(salt_data['data'].get('present', []))

        for minion in dropped_minions:
            changed = True
            log.debug('Popping %s', minion)
            self.minions.pop(minion, None)

        # check if any new connections were made
        if set(salt_data['data'].get('new', [])):
            log.debug('got new minions')
            new_minions = set(salt_data['data'].get('new', []))
            changed = True
        elif set(salt_data['data'].get('present', [])) - set(self.minions):
            log.debug('detected new minions')
            new_minions = set(salt_data['data'].get('present', [])) - set(self.minions)
            changed = True
        else:
            new_minions = []

        tgt = ','.join(new_minions)
        for mid in new_minions:
            log.debug('Adding minion')
            self.minions[mid] = {}

        if tgt:
            changed = True
            client = salt.netapi.NetapiClient(opts)
            client.run(
                {
                    'fun': 'grains.items',
                    'tgt': tgt,
                    'expr_type': 'list',
                    'mode': 'client',
                    'client': 'local',
                    'asynchronous': 'local_async',
                    'token': token,
                })

        if changed:
            self.publish_minions()
508058
def apply_minion_config(overrides=None,
                        defaults=None,
                        cache_minion_id=False,
                        minion_id=None):
    '''
    
    '''
    if defaults is None:
        defaults = DEFAULT_MINION_OPTS.copy()
    if overrides is None:
        overrides = {}

    opts = defaults.copy()
    opts['__role'] = 'minion'
    _adjust_log_file_override(overrides, defaults['log_file'])
    if overrides:
        opts.update(overrides)

    if 'environment' in opts:
        if opts['saltenv'] is not None:
            log.warning(
                'The \'saltenv\' and \'environment\' minion config options '
                'cannot both be used. Ignoring \'environment\' in favor of '
                '\'saltenv\'.',
            )
            # Set environment to saltenv in case someone's custom module is
            # refrencing __opts__['environment']
            opts['environment'] = opts['saltenv']
        else:
            log.warning(
                'The \'environment\' minion config option has been renamed '
                'to \'saltenv\'. Using %s as the \'saltenv\' config value.',
                opts['environment']
            )
            opts['saltenv'] = opts['environment']

    for idx, val in enumerate(opts['fileserver_backend']):
        if val in ('git', 'hg', 'svn', 'minion'):
            new_val = val + 'fs'
            log.debug(
                'Changed %s to %s in minion opts\' fileserver_backend list',
                val, new_val
            )
            opts['fileserver_backend'][idx] = new_val

    opts['__cli'] = salt.utils.stringutils.to_unicode(
        os.path.basename(sys.argv[0])
    )

    # No ID provided. Will getfqdn save us?
    using_ip_for_id = False
    if not opts.get('id'):
        if minion_id:
            opts['id'] = minion_id
        else:
            opts['id'], using_ip_for_id = get_id(
                    opts,
                    cache_minion_id=cache_minion_id)

    # it does not make sense to append a domain to an IP based id
    if not using_ip_for_id and 'append_domain' in opts:
        opts['id'] = _append_domain(opts)

    for directory in opts.get('append_minionid_config_dirs', []):
        if directory in ('pki_dir', 'cachedir', 'extension_modules'):
            newdirectory = os.path.join(opts[directory], opts['id'])
            opts[directory] = newdirectory
        elif directory == 'default_include' and directory in opts:
            include_dir = os.path.dirname(opts[directory])
            new_include_dir = os.path.join(include_dir,
                                           opts['id'],
                                           os.path.basename(opts[directory]))
            opts[directory] = new_include_dir

    # pidfile can be in the list of append_minionid_config_dirs, but pidfile
    # is the actual path with the filename, not a directory.
    if 'pidfile' in opts.get('append_minionid_config_dirs', []):
        newpath_list = os.path.split(opts['pidfile'])
        opts['pidfile'] = os.path.join(newpath_list[0], 'salt', opts['id'], newpath_list[1])

    if len(opts['sock_dir']) > len(opts['cachedir']) + 10:
        opts['sock_dir'] = os.path.join(opts['cachedir'], '.salt-unix')

    # Enabling open mode requires that the value be set to True, and
    # nothing else!
    opts['open_mode'] = opts['open_mode'] is True
    opts['file_roots'] = _validate_file_roots(opts['file_roots'])
    opts['pillar_roots'] = _validate_pillar_roots(opts['pillar_roots'])
    # Make sure ext_mods gets set if it is an untrue value
    # (here to catch older bad configs)
    opts['extension_modules'] = (
        opts.get('extension_modules') or
        os.path.join(opts['cachedir'], 'extmods')
    )
    # Set up the utils_dirs location from the extension_modules location
    opts['utils_dirs'] = (
        opts.get('utils_dirs') or
        [os.path.join(opts['extension_modules'], 'utils')]
    )

    # Insert all 'utils_dirs' directories to the system path
    insert_system_path(opts, opts['utils_dirs'])

    # Prepend root_dir to other paths
    prepend_root_dirs = [
        'pki_dir', 'cachedir', 'sock_dir', 'extension_modules', 'pidfile',
    ]

    # These can be set to syslog, so, not actual paths on the system
    for config_key in ('log_file', 'key_logfile'):
        if urlparse(opts.get(config_key, '')).scheme == '':
            prepend_root_dirs.append(config_key)

    prepend_root_dir(opts, prepend_root_dirs)

    # if there is no beacons option yet, add an empty beacons dict
    if 'beacons' not in opts:
        opts['beacons'] = {}

    if overrides.get('ipc_write_buffer', '') == 'dynamic':
        opts['ipc_write_buffer'] = _DFLT_IPC_WBUFFER

    # Make sure hash_type is lowercase
    opts['hash_type'] = opts['hash_type'].lower()

    # Check and update TLS/SSL configuration
    _update_ssl_config(opts)
    _update_discovery_config(opts)

    return opts
300750
def execution():
    '''
    
    '''
    client = salt.client.get_local_client(__opts__['conf_file'])

    docs = {}
    try:
        for ret in client.cmd_iter('*', 'sys.doc', timeout=__opts__['timeout']):
            for v in six.itervalues(ret):
                docs.update(v)
    except SaltClientError as exc:
        print(exc)
        return []

    i = itertools.chain.from_iterable([six.iteritems(docs['ret'])])
    ret = dict(list(i))

    return ret
766118
def process(self, salt_data, token, opts):
        '''
        
        '''
        log.debug('In process %s', threading.current_thread())
        log.debug(salt_data['tag'])
        log.debug(salt_data)

        parts = salt_data['tag'].split('/')
        if len(parts) < 2:
            return

        # TBD: Simplify these conditional expressions
        if parts[1] == 'job':
            log.debug('In job part 1')
            if parts[3] == 'new':
                log.debug('In new job')
                self.process_new_job_event(salt_data)
                # if salt_data['data']['fun'] == 'grains.items':
                #     self.minions = {}
            elif parts[3] == 'ret':
                log.debug('In ret')
                self.process_ret_job_event(salt_data)
                if salt_data['data']['fun'] == 'grains.items':
                    self.process_minion_update(salt_data)
        elif parts[1] == 'key':
            log.debug('In key')
            self.process_key_event(salt_data)
        elif parts[1] == 'presence':
            self.process_presence_events(salt_data, token, opts)
170963
async function create(name, options, api, env) {
  // Grab the cwd and npmClient off of the environment. We can use these to
  // create the folder for the project and for determining what client to use
  // for npm-related commands
  const { CLI_ENV, cwd, npmClient } = env;
  // We support a couple of options for our `create` command, some only exist
  // during development (like link and linkCli).
  const { link, linkCli, plugins = [], presets = [], skip } = options;
  const root = path.join(cwd, name);

  logger.trace('Creating project:', name, 'at:', root);

  if (await fs.exists(root)) {
    throw new Error(`A folder already exists at \`${root}\``);
  }

  // Create the root directory for the new project
  await fs.ensureDir(root);

  const {
    writePackageJson,
    installDependencies,
    linkDependencies,
  } = await createClient(npmClient, root);
  const packageJson = {
    name,
    private: true,
    license: 'MIT',
    scripts: {},
    dependencies: {},
    devDependencies: {},
    toolkit: {},
  };

  // Write the packageJson to the newly created `root` folder
  await writePackageJson(packageJson);

  const installer = linkCli ? linkDependencies : installDependencies;
  await installer(['@carbon/toolkit']);

  if (CLI_ENV === 'production') {
    clearConsole();
  }

  if (skip) {
    displaySuccess(root, name, npmClient);
    return;
  }

  const toolkit = await which('toolkit', { cwd: root });

  if (presets.length > 0) {
    const args = ['add', ...presets, link && '--link'].filter(Boolean);
    await spawn(toolkit, args, {
      cwd: root,
      stdio: 'inherit',
    });
  }

  if (plugins.length > 0) {
    const args = ['add', ...plugins, link && '--link'].filter(Boolean);
    await spawn(toolkit, args, {
      cwd: root,
      stdio: 'inherit',
    });
  }

  displaySuccess(root, name, npmClient);
}
918503
def _deploy(self):
        """"""
        timeout = int(os.environ.get('AMULET_SETUP_TIMEOUT', 900))
        try:
            self.d.setup(timeout=timeout)
            self.d.sentry.wait(timeout=timeout)
        except amulet.helpers.TimeoutError:
            amulet.raise_status(
                amulet.FAIL,
                msg="Deployment timed out ({}s)".format(timeout)
            )
        except Exception:
            raise
32207
def _pillar(self, load):
        '''
        
        '''
        if any(key not in load for key in ('id', 'grains')):
            return False
        if not salt.utils.verify.valid_id(self.opts, load['id']):
            return False
        load['grains']['id'] = load['id']

        pillar = salt.pillar.get_pillar(
            self.opts,
            load['grains'],
            load['id'],
            load.get('saltenv', load.get('env')),
            ext=load.get('ext'),
            pillar_override=load.get('pillar_override', {}),
            pillarenv=load.get('pillarenv'),
            extra_minion_data=load.get('extra_minion_data'))
        data = pillar.compile_pillar()
        self.fs_.update_opts()
        if self.opts.get('minion_data_cache', False):
            self.masterapi.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({'Minion data cache refresh': load['id']}, tagify(load['id'], 'refresh', 'minion'))
        return data