def process_config(self, file_hash, config, host): """Manages all translations related to a config file. Publish tables to PE. :param file_hash: Hash of the configuration file :param config: object representing the configuration :param host: Remote host name :return: True if config was processed """ try: LOG.debug("process_config hash=%s" % file_hash) template_hash = config['template'] template = self.known_templates.get(template_hash, None) if template is None: waiting = ( self.templates_awaited_by_config.get(template_hash, [])) waiting.append((file_hash, config)) self.templates_awaited_by_config[template_hash] = waiting LOG.debug('Template %s not yet registered' % template_hash) return False host_id = utils.compute_hash(host) namespaces = [self.known_namespaces.get(h, None).get('data', None) for h in template['namespaces']] conf = parsing.construct_conf_manager(namespaces) parsing.add_parsed_conf(conf, config['data']) for tablename in set(self.get_schema()) - set(self.state): self.state[tablename] = set() self.publish(tablename, self.state[tablename], use_snapshot=False) self.translate_conf(conf, file_hash) self.translate_host(host_id, host) self.translate_service( host_id, config['service'], config['version']) file_name = os.path.basename(config['path']) self.translate_file(file_hash, host_id, template_hash, file_name) ns_hashes = {h: self.known_namespaces[h]['name'] for h in template['namespaces']} self.translate_template_namespace(template_hash, template['name'], ns_hashes) for tablename in self.state: self.publish(tablename, self.state[tablename], use_snapshot=True) return True except KeyError: LOG.error('Config %s from %s NOT registered' % (file_hash, host)) return False
def parse(self, host): """Parses the config at the path given. Updates data and hash. host: the name of the host where the config is. Used for building a unique hash. """ namespaces_data = [ns.data for ns in self.template.namespaces] conf = parsing.parse_config_file(namespaces_data, self.path) Config.sanitize_config(conf) self.data = conf._namespace._normalized self.hash = utils.compute_hash(host, self.template.hash, json.dumps(self.data, sort_keys=True))
def process_config(self, file_hash, config, host): """Manages all translations related to a config file. Publish tables to PE. :param file_hash: Hash of the configuration file :param config: object representing the configuration :param host: Remote host name """ template_hash = config['template'] template = self.known_templates.get(template_hash, None) if template is None: waiting = self.templates_awaited_by_config.get(template_hash, []) waiting.append((file_hash, config)) self.templates_awaited_by_config[template_hash] = waiting LOG.info('Template %s not yet registered' % template_hash) return host_id = utils.compute_hash(host) namespaces = [ self.known_namespaces.get(h, None).get('data', None) for h in template['namespaces'] ] conf = parsing.construct_conf_manager(namespaces) parsing.add_parsed_conf(conf, config['data']) for tablename in set(self.get_schema()) - set(self.state): self.state[tablename] = set() self.publish(tablename, self.state[tablename], use_snapshot=False) self.translate_conf(conf, file_hash) self.translate_host(host_id, host) self.translate_service(host_id, config['service'], config['version']) file_name = os.path.basename(config['path']) self.translate_file(file_hash, host_id, template_hash, file_name) ns_hashes = { h: self.known_namespaces[h]['name'] for h in template['namespaces'] } self.translate_template_namespace(template_hash, template['name'], ns_hashes) for tablename in self.state: self.publish(tablename, self.state[tablename], use_snapshot=True)
def load(template_path): """Loads a template configuration file :param template_path: path to the template :return: a fully configured Template object. """ namespaces, output_file = Template._parse_template_conf(template_path) template = Template(template_path, output_file) for namespace in namespaces: template.namespaces.append(Namespace.load(namespace)) template.hash = utils.compute_hash( sorted([ns.hash for ns in template.namespaces])) return template
def construct_conf_manager(namespaces): """Construct a config manager from a list of namespaces data. Register options of given namespaces into a cfg.ConfigOpts object. A namespaces dict is typically cfg_validator.generator output. Options are provided an hash as an extra field. :param namespaces: A list of dict, containing options metadata. :return: A cfg.ConfigOpts. """ conf = cfg.ConfigOpts() for ns_dict in namespaces: ns_hash = utils.compute_hash(json.dumps(ns_dict, sort_keys=True)) add_namespace(conf, ns_dict, ns_hash) return conf
def load(name): """Loads a namespace from disk :param name: the name of namespace to load. :return: a fully configured namespace. """ namespace = Namespace(name) saved_conf = cfg.CONF cfg.CONF = cfg.ConfigOpts() try: json_data = validator_generator.generate_ns_data(name) finally: cfg.CONF = saved_conf namespace.hash = utils.compute_hash(json_data) namespace.data = json.loads(json_data) return namespace
def add_namespace(conf, ns_dict, ns_hash): """Add options from a kind to an already existing config""" for group_name, group in six.iteritems(ns_dict): try: title = group['object'].get('title', None) help_msg = group['object'].get('help', None) except AttributeError: title = help_msg = None cfggroup = make_group(group_name, title, help_msg) # Get back the instance already stored or register the group. if cfggroup is not None: # pylint: disable=protected-access cfggroup = conf._get_group(cfggroup, autocreate=True) for namespace in group['namespaces']: for option in namespace[1]: opt_hash = utils.compute_hash(ns_hash, group_name, option['name']) cfgopt = make_opt(option, opt_hash, ns_hash) conf.register_opt(cfgopt, cfggroup)
def test_hash(self): """Test shape of hash generated""" re_hash = ('^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-' '[0-9a-f]{4}-[0-9a-f]{8}') self.assertTrue(re.match(re_hash, utils.compute_hash('foo'))) self.assertTrue(re.match(re_hash, utils.compute_hash('foo', 'bar')))