Process the configured beacons

        The config must be a list and looks like this in yaml

        .. code_block:: yaml
            beacons:
              inotify:
                - files:
                    - /etc/fstab: {}
                    - /var/cache/foo: {}

def process(self, config, grains):
        '''
        Process the configured beacons

        The config must be a list and looks like this in yaml

        .. code_block:: yaml
            beacons:
              inotify:
                - files:
                    - /etc/fstab: {}
                    - /var/cache/foo: {}
        '''
        ret = []
        b_config = copy.deepcopy(config)
        if 'enabled' in b_config and not b_config['enabled']:
            return
        for mod in config:
            if mod == 'enabled':
                continue

            # Convert beacons that are lists to a dict to make processing easier
            current_beacon_config = None
            if isinstance(config[mod], list):
                current_beacon_config = {}
                list(map(current_beacon_config.update, config[mod]))
            elif isinstance(config[mod], dict):
                current_beacon_config = config[mod]

            if 'enabled' in current_beacon_config:
                if not current_beacon_config['enabled']:
                    log.trace('Beacon %s disabled', mod)
                    continue
                else:
                    # remove 'enabled' item before processing the beacon
                    if isinstance(config[mod], dict):
                        del config[mod]['enabled']
                    else:
                        self._remove_list_item(config[mod], 'enabled')

            log.trace('Beacon processing: %s', mod)
            beacon_name = None
            if self._determine_beacon_config(current_beacon_config, 'beacon_module'):
                beacon_name = current_beacon_config['beacon_module']
            else:
                beacon_name = mod
            fun_str = '{0}.beacon'.format(beacon_name)
            validate_str = '{0}.validate'.format(beacon_name)
            if fun_str in self.beacons:
                runonce = self._determine_beacon_config(current_beacon_config, 'run_once')
                interval = self._determine_beacon_config(current_beacon_config, 'interval')
                if interval:
                    b_config = self._trim_config(b_config, mod, 'interval')
                    if not self._process_interval(mod, interval):
                        log.trace('Skipping beacon %s. Interval not reached.', mod)
                        continue
                if self._determine_beacon_config(current_beacon_config, 'disable_during_state_run'):
                    log.trace('Evaluting if beacon %s should be skipped due to a state run.', mod)
                    b_config = self._trim_config(b_config, mod, 'disable_during_state_run')
                    is_running = False
                    running_jobs = salt.utils.minion.running(self.opts)
                    for job in running_jobs:
                        if re.match('state.*', job['fun']):
                            is_running = True
                    if is_running:
                        close_str = '{0}.close'.format(beacon_name)
                        if close_str in self.beacons:
                            log.info('Closing beacon %s. State run in progress.', mod)
                            self.beacons[close_str](b_config[mod])
                        else:
                            log.info('Skipping beacon %s. State run in progress.', mod)
                        continue
                # Update __grains__ on the beacon
                self.beacons[fun_str].__globals__['__grains__'] = grains

                # Run the validate function if it's available,
                # otherwise there is a warning about it being missing
                if validate_str in self.beacons:
                    valid, vcomment = self.beacons[validate_str](b_config[mod])

                    if not valid:
                        log.info('Beacon %s configuration invalid, '
                                 'not running.\n%s', mod, vcomment)
                        continue

                # Fire the beacon!
                raw = self.beacons[fun_str](b_config[mod])
                for data in raw:
                    tag = 'salt/beacon/{0}/{1}/'.format(self.opts['id'], mod)
                    if 'tag' in data:
                        tag += data.pop('tag')
                    if 'id' not in data:
                        data['id'] = self.opts['id']
                    ret.append({'tag': tag,
                                'data': data,
                                'beacon_name': beacon_name})
                if runonce:
                    self.disable_beacon(mod)
            else:
                log.warning('Unable to process beacon %s', mod)
        return ret