détacher la base de données du parser
This commit is contained in:
parent
5a3504e141
commit
ffe5f715c1
|
@ -9,6 +9,141 @@ from glob import glob
|
||||||
USER_CONFDIR = '~/etc/deploy'
|
USER_CONFDIR = '~/etc/deploy'
|
||||||
SYSTEM_CONFDIR = '/var/local/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):
|
class EOL(object):
|
||||||
__repr__ = __string__ = lambda self: 'EOL'
|
__repr__ = __string__ = lambda self: 'EOL'
|
||||||
EOL = EOL()
|
EOL = EOL()
|
||||||
|
@ -154,47 +289,6 @@ class Lexer(object):
|
||||||
predicate.append(lexem)
|
predicate.append(lexem)
|
||||||
return predicates
|
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):
|
def split_scalar(arg):
|
||||||
if '=' in arg:
|
if '=' in arg:
|
||||||
name, value = arg.split('=', 1)
|
name, value = arg.split('=', 1)
|
||||||
|
@ -224,27 +318,18 @@ def split_list(arg):
|
||||||
return name, values
|
return name, values
|
||||||
|
|
||||||
class Parser(object):
|
class Parser(object):
|
||||||
lexer = None
|
db = None
|
||||||
predicates = None
|
|
||||||
|
|
||||||
known_profiles = None
|
|
||||||
default_profile = None
|
|
||||||
default_domain = None
|
|
||||||
|
|
||||||
objects = None
|
|
||||||
groups = None
|
groups = None
|
||||||
attr_otype = None
|
attr_otype = None
|
||||||
|
|
||||||
def __init__(self, lexer, parse=True):
|
def __init__(self, db=None):
|
||||||
self.lexer = lexer
|
if db is None: db = Database()
|
||||||
self.objects = {}
|
self.db = db
|
||||||
self.groups = {}
|
self.groups = {}
|
||||||
self.__setup_hosts()
|
self.__setup_hosts()
|
||||||
if parse: self.parse()
|
|
||||||
|
|
||||||
def parse(self):
|
def parse(self, predicates):
|
||||||
self.predicates = self.lexer.get_predicates()
|
for p in predicates:
|
||||||
for p in self.predicates:
|
|
||||||
cmd = p[0]
|
cmd = p[0]
|
||||||
args = p[1:]
|
args = p[1:]
|
||||||
if cmd == 'default_profile': self.handle_default_profile(args)
|
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 == 'group': self.handle_group(args)
|
||||||
elif cmd == 'attr': self.handle_attr(args)
|
elif cmd == 'attr': self.handle_attr(args)
|
||||||
elif cmd == 'host': self.handle_host(args)
|
elif cmd == 'host': self.handle_host(args)
|
||||||
|
return self
|
||||||
def get_objects(self, otype):
|
|
||||||
objects = self.objects[otype]
|
|
||||||
return [objects[id] for id in objects if id is not None]
|
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
def reset_group(self, otype):
|
def reset_group(self, otype):
|
||||||
|
@ -297,54 +379,33 @@ class Parser(object):
|
||||||
method = 'set'
|
method = 'set'
|
||||||
value = '1'
|
value = '1'
|
||||||
for id in self.groups[otype]['current']:
|
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):
|
def handle_default_profile(self, args):
|
||||||
if not args or not args[0]:
|
if not args or not args[0]: profile = None
|
||||||
profile = None
|
else: profile = args[0]
|
||||||
else:
|
self.db.default_profile = profile
|
||||||
profile = args[0]
|
|
||||||
if self.known_profiles is None: self.known_profiles = {}
|
|
||||||
self.known_profiles[profile] = True
|
|
||||||
self.default_profile = profile
|
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
def handle_default_domain(self, args):
|
def handle_default_domain(self, args):
|
||||||
if not args or not args[0]:
|
if not args or not args[0]: domain = None
|
||||||
domain = None
|
else: domain = args[0]
|
||||||
else:
|
self.db.default_domain = domain
|
||||||
domain = args[0]
|
|
||||||
self.default_domain = domain
|
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
def __setup_hosts(self):
|
def __setup_hosts(self):
|
||||||
self.objects['host'] = {}
|
self.db.register_object('host', HostObject)
|
||||||
self.__host_object(None)
|
self.db.get_object('host', None)
|
||||||
self.groups['host'] = {}
|
self.groups['host'] = {}
|
||||||
self.handle_group(['host', 'defaults'])
|
self.handle_group(['host', 'defaults'])
|
||||||
self.attr_otype = 'host'
|
self.attr_otype = 'host'
|
||||||
def __fix_host(self, host):
|
def __fix_host(self, host):
|
||||||
if host.endswith('.'):
|
if host.endswith('.'):
|
||||||
host = host[:-1]
|
host = host[:-1]
|
||||||
elif '.' not in host and self.default_domain:
|
elif '.' not in host and self.db.has_default_domain():
|
||||||
host = '%s.%s' % (host, self.default_domain)
|
host = '%s.%s' % (host, self.db.default_domain)
|
||||||
return host
|
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):
|
def handle_host(self, args):
|
||||||
"""host [id=]host,...
|
"""host [id=]host,...
|
||||||
|
@ -370,7 +431,7 @@ class Parser(object):
|
||||||
# préparer la mise à jour du groupe courant
|
# préparer la mise à jour du groupe courant
|
||||||
self.reset_group_maybe('host')
|
self.reset_group_maybe('host')
|
||||||
self.attr_otype = 'host'
|
self.attr_otype = 'host'
|
||||||
default_ho = self.__host_object(None)
|
default_ho = self.db.get_object('host', None)
|
||||||
# traiter les hôtes
|
# traiter les hôtes
|
||||||
for nvs in nvss:
|
for nvs in nvss:
|
||||||
name, values = split_list(nvs)
|
name, values = split_list(nvs)
|
||||||
|
@ -381,20 +442,21 @@ class Parser(object):
|
||||||
dir, host = path.split(path.abspath(path.expanduser(host)))
|
dir, host = path.split(path.abspath(path.expanduser(host)))
|
||||||
host = self.__fix_host(host)
|
host = self.__fix_host(host)
|
||||||
if name:
|
if name:
|
||||||
ho = self.__host_object(name)
|
ho = self.db.get_object('host', name)
|
||||||
if host: ho.add_host(host)
|
if host: ho.add_host(host)
|
||||||
ho.copy_attrs(default_ho)
|
ho.copy_attrs(default_ho)
|
||||||
if dir is not None: ho.reset_attr('dir', dir)
|
if dir is not None: ho.reset_attr('dir', dir)
|
||||||
self.add_group('host', name)
|
self.add_group('host', name)
|
||||||
else:
|
else:
|
||||||
id = self.__hostid(host)
|
id = HostObject.genid(host)
|
||||||
ho = self.__host_object(id)
|
ho = self.db.get_object('host', id)
|
||||||
ho.add_host(host)
|
ho.add_host(host)
|
||||||
ho.copy_attrs(default_ho)
|
ho.copy_attrs(default_ho)
|
||||||
if dir is not None: ho.reset_attr('dir', dir)
|
if dir is not None: ho.reset_attr('dir', dir)
|
||||||
self.add_group('host', id)
|
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.add_host(host)
|
||||||
ho.copy_attrs(default_ho)
|
ho.copy_attrs(default_ho)
|
||||||
if dir is not None: ho.reset_attr('dir', dir)
|
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
|
if path.exists(user_conf): conf = user_conf
|
||||||
elif path.exists(system_conf): conf = system_conf
|
elif path.exists(system_conf): conf = system_conf
|
||||||
lexer = Lexer(conf)
|
lexer = Lexer(conf)
|
||||||
|
db = Database()
|
||||||
|
|
||||||
if o.action == 'nop':
|
if o.action == 'nop':
|
||||||
pass
|
pass
|
||||||
elif o.action == 'dump': #XXX
|
elif o.action == 'dump': #XXX
|
||||||
parser = Parser(lexer)
|
predicates = lexer.get_predicates()
|
||||||
|
parser = Parser(db).parse(predicates)
|
||||||
print "=== predicates"
|
print "=== predicates"
|
||||||
for p in parser.predicates:
|
for p in predicates:
|
||||||
print ' '.join(map(repr, p))
|
print ' '.join(map(repr, p))
|
||||||
print "=== hosts"
|
print "=== hosts"
|
||||||
for ho in parser.get_objects('host'):
|
for ho in db.get_objects('host'):
|
||||||
id, dir, hosts = ho.get_id(), ho.get_dir(), ho.get_hosts()
|
ho.dump()
|
||||||
attrs = ho.get_attrs()
|
|
||||||
print id
|
|
||||||
if dir: print " dir=%s" % dir
|
|
||||||
print " hosts=%r" % hosts
|
|
||||||
if attrs: print " attrs=%r" % attrs
|
|
||||||
elif o.action == 'query':
|
elif o.action == 'query':
|
||||||
parser = Parser(lexer)
|
parser = Parser(db).parse(lexer.get_predicates())
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from argparse import ArgumentParser, HelpFormatter
|
from argparse import ArgumentParser, HelpFormatter
|
||||||
|
|
Loading…
Reference in New Issue