From ffe5f715c134b453fce37b60f5e45b908e97e816 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Thu, 15 Jun 2017 21:11:58 +0400 Subject: [PATCH] =?UTF-8?q?d=C3=A9tacher=20la=20base=20de=20donn=C3=A9es?= =?UTF-8?q?=20du=20parser?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/ulib/support/deploydb.py | 275 +++++++++++++++++++++-------------- 1 file changed, 167 insertions(+), 108 deletions(-) diff --git a/lib/ulib/support/deploydb.py b/lib/ulib/support/deploydb.py index 080bdd4..ae48fac 100755 --- a/lib/ulib/support/deploydb.py +++ b/lib/ulib/support/deploydb.py @@ -9,6 +9,141 @@ from glob import glob USER_CONFDIR = '~/etc/deploy' SYSTEM_CONFDIR = '/var/local/deploy' +################################################################################ +# Base de données + +class HostObject(object): + @staticmethod + def genid(host): + host = re.sub(r'\..*', '', host) + host = re.sub(r'[^a-zA-Z0-9]', '_', host) + host = host.lower() + return host + @staticmethod + def genib(id): + if re.match(r'\d+$', id): return id + ib = re.sub(r'^(.*?)\d+$', r'\1', id) + return ib + + _id = None + _hosts = None + _attrs = None + + def __init__(self, id): + self._id = id + self._hosts = [] + self._attrs = {} + def get_id(self): return self._id + id = property(get_id) + + def get_hosts(self): return self._hosts + hosts = property(get_hosts) + def add_host(self, host): + if host not in self._hosts: self._hosts.append(host) + + def get_attrs(self): return self._attrs + attrs = property(get_attrs) + + def get_attr(self, name): return self._attrs.get(name, None) + def set_attr(self, name, value): + if name not in self._attrs: self._attrs[name] = [] + if value not in self._attrs[name]: self._attrs[name].append(value) + def reset_attr(self, name, value=None): + if name in self._attrs: del self._attrs[name] + if value is not None: self.set_attr(name, value) + def add_attr(self, name, value): + if name not in self._attrs: self._attrs[name] = [] + self._attrs[name].append(value) + def del_attr(self, name, value): + if name not in self._attrs: return + self._attrs[name].remove(value) + if not self._attrs[name]: del self._attrs[name] + def modify_attr(self, name, value, method='set'): + if method == 'set': self.set_attr(name, value) + elif method == 'reset': self.reset_attr(name, value) + elif method == 'add': self.add_attr(name, value) + elif method == 'del': self.del_attr(name, value) + def copy_attrs(self, other, method='set'): + for name, values in other.attrs.items(): + for value in values: + self.modify_attr(name, value, method) + + def dump(self, indent=''): + print "%s%s" % (indent, self.id) + print "%s hosts: %s" % (indent, ' '.join(self.hosts)) + if self.attrs: + print "%s attrs:" % indent + for name, values in self.attrs.items(): + if len(values) == 1: + print "%s %s=%s" % (indent, name, repr(values[0])) + else: + print "%s %s=(%s)" % (indent, name, ', '.join(map(repr, values))) + +class Database(object): + _known_profiles = None + _default_profile = None + _default_domain = None + + _objects = None + _objects_classes = None + + def __init__(self): + self._known_profiles = {} + self._objects = {} + self._objects_classes = {} + + def get_known_profiles(self): + return self.known_profiles.keys() + known_profiles = property(get_known_profiles) + + def has_default_profile(self): + return self._default_profile is not None + def get_default_profile(self): + return self._default_profile + def set_default_profile(self, profile): + if profile: self._known_profiles[profile] = True + self._default_profile = profile or None + default_profile = property(get_default_profile, set_default_profile) + + def has_default_domain(self): + return self._default_domain is not None + def get_default_domain(self): + return self._default_domain + def set_default_domain(self, domain): + if domain is not None: + #XXX si le domaine a été corrigé, l'indiquer en warning + if domain.startswith('.'): domain = domain[1:] + if domain.endswith('.'): domain = domain[:-1] + self._default_domain = domain or None + default_domain = property(get_default_domain, set_default_domain) + + def register_object(self, otype, oclass): + if not self._objects.has_key(otype): + self._objects[otype] = {} + self._objects_classes[otype] = oclass + def get_objects(self, otype): + objects = self._objects.get(otype, None) + if objects is None: return None + return [objects[id] for id in objects if id is not None] + objects = property(get_objects) + def has_object(self, otype, id): + objects = self._objects.get(otype, None) + if objects is None: return False + return objects.has_key(id) + def get_object(self, otype, id): + objects = self._objects.get(otype, None) + if objects is None: return None + object = objects.get(id, None) + if object is None: + object_class = self._objects_classes.get(otype, None) + if object_class is not None: + object = object_class(id) + self._objects[otype][id] = object + return object + +################################################################################ +# Analyse des fichiers de configuration + class EOL(object): __repr__ = __string__ = lambda self: 'EOL' EOL = EOL() @@ -154,47 +289,6 @@ class Lexer(object): predicate.append(lexem) return predicates -class HostObject(object): - id = None - dir = None - hosts = None - attrs = None - - def __init__(self, id): - self.id = id - self.hosts = [] - self.attrs = {} - def get_id(self): return self.id - def get_dir(self): return self.dir - def set_dir(self, dir): self.dir = dir - def get_hosts(self): return self.hosts - def add_host(self, host): - if host not in self.hosts: self.hosts.append(host) - def get_attrs(self): return self.attrs - def get_attr(self, name): return self.attrs.get(name, None) - def set_attr(self, name, value): - if name not in self.attrs: self.attrs[name] = [] - if value not in self.attrs[name]: self.attrs[name].append(value) - def reset_attr(self, name, value=None): - if name in self.attrs: del self.attrs[name] - if value is not None: self.set_attr(name, value) - def add_attr(self, name, value): - if name not in self.attrs: self.attrs[name] = [] - self.attrs[name].append(value) - def del_attr(self, name, value): - if name not in self.attrs: return - self.attrs[name].remove(value) - if not self.attrs[name]: del self.attrs[name] - def modify_attr(self, name, value, method='set'): - if method == 'set': self.set_attr(name, value) - elif method == 'reset': self.reset_attr(name, value) - elif method == 'add': self.add_attr(name, value) - elif method == 'del': self.del_attr(name, value) - def copy_attrs(self, other, method='set'): - for name, values in other.attrs.items(): - for value in values: - self.modify_attr(name, value, method) - def split_scalar(arg): if '=' in arg: name, value = arg.split('=', 1) @@ -224,27 +318,18 @@ def split_list(arg): return name, values class Parser(object): - lexer = None - predicates = None - - known_profiles = None - default_profile = None - default_domain = None - - objects = None + db = None groups = None attr_otype = None - def __init__(self, lexer, parse=True): - self.lexer = lexer - self.objects = {} + def __init__(self, db=None): + if db is None: db = Database() + self.db = db self.groups = {} self.__setup_hosts() - if parse: self.parse() - def parse(self): - self.predicates = self.lexer.get_predicates() - for p in self.predicates: + def parse(self, predicates): + for p in predicates: cmd = p[0] args = p[1:] if cmd == 'default_profile': self.handle_default_profile(args) @@ -252,10 +337,7 @@ class Parser(object): elif cmd == 'group': self.handle_group(args) elif cmd == 'attr': self.handle_attr(args) elif cmd == 'host': self.handle_host(args) - - def get_objects(self, otype): - objects = self.objects[otype] - return [objects[id] for id in objects if id is not None] + return self ############################################################################ def reset_group(self, otype): @@ -297,54 +379,33 @@ class Parser(object): method = 'set' value = '1' for id in self.groups[otype]['current']: - self.objects[otype][id].modify_attr(name, value, method) + self.db.get_object(otype, id).modify_attr(name, value, method) ############################################################################ def handle_default_profile(self, args): - if not args or not args[0]: - profile = None - else: - profile = args[0] - if self.known_profiles is None: self.known_profiles = {} - self.known_profiles[profile] = True - self.default_profile = profile + if not args or not args[0]: profile = None + else: profile = args[0] + self.db.default_profile = profile ############################################################################ def handle_default_domain(self, args): - if not args or not args[0]: - domain = None - else: - domain = args[0] - self.default_domain = domain + if not args or not args[0]: domain = None + else: domain = args[0] + self.db.default_domain = domain ############################################################################ def __setup_hosts(self): - self.objects['host'] = {} - self.__host_object(None) + self.db.register_object('host', HostObject) + self.db.get_object('host', None) self.groups['host'] = {} self.handle_group(['host', 'defaults']) self.attr_otype = 'host' def __fix_host(self, host): if host.endswith('.'): host = host[:-1] - elif '.' not in host and self.default_domain: - host = '%s.%s' % (host, self.default_domain) + elif '.' not in host and self.db.has_default_domain(): + host = '%s.%s' % (host, self.db.default_domain) return host - def __hostid(self, host): - host = re.sub(r'\..*', '', host) - host = re.sub(r'[^a-zA-Z0-9]', '_', host) - host = host.lower() - return host - def __hostib(self, id): - if re.match(r'\d+$', id): return id - ib = re.sub(r'^(.*?)\d+$', r'\1', id) - return ib - def __host_object(self, id): - ho = self.objects['host'].get(id, None) - if ho is None: - ho = HostObject(id) - self.objects['host'][id] = ho - return ho def handle_host(self, args): """host [id=]host,... @@ -370,7 +431,7 @@ class Parser(object): # préparer la mise à jour du groupe courant self.reset_group_maybe('host') self.attr_otype = 'host' - default_ho = self.__host_object(None) + default_ho = self.db.get_object('host', None) # traiter les hôtes for nvs in nvss: name, values = split_list(nvs) @@ -381,20 +442,21 @@ class Parser(object): dir, host = path.split(path.abspath(path.expanduser(host))) host = self.__fix_host(host) if name: - ho = self.__host_object(name) + ho = self.db.get_object('host', name) if host: ho.add_host(host) ho.copy_attrs(default_ho) if dir is not None: ho.reset_attr('dir', dir) self.add_group('host', name) else: - id = self.__hostid(host) - ho = self.__host_object(id) + id = HostObject.genid(host) + ho = self.db.get_object('host', id) ho.add_host(host) ho.copy_attrs(default_ho) if dir is not None: ho.reset_attr('dir', dir) self.add_group('host', id) - ib = self.__hostib(id) - ho = self.__host_object(ib) + + ib = HostObject.genib(id) + ho = self.db.get_object('host', ib) ho.add_host(host) ho.copy_attrs(default_ho) if dir is not None: ho.reset_attr('dir', dir) @@ -415,24 +477,21 @@ def run_qdd(o): if path.exists(user_conf): conf = user_conf elif path.exists(system_conf): conf = system_conf lexer = Lexer(conf) + db = Database() if o.action == 'nop': pass elif o.action == 'dump': #XXX - parser = Parser(lexer) + predicates = lexer.get_predicates() + parser = Parser(db).parse(predicates) print "=== predicates" - for p in parser.predicates: + for p in predicates: print ' '.join(map(repr, p)) print "=== hosts" - for ho in parser.get_objects('host'): - id, dir, hosts = ho.get_id(), ho.get_dir(), ho.get_hosts() - attrs = ho.get_attrs() - print id - if dir: print " dir=%s" % dir - print " hosts=%r" % hosts - if attrs: print " attrs=%r" % attrs + for ho in db.get_objects('host'): + ho.dump() elif o.action == 'query': - parser = Parser(lexer) + parser = Parser(db).parse(lexer.get_predicates()) if __name__ == '__main__': from argparse import ArgumentParser, HelpFormatter