suite gestion des liens
This commit is contained in:
parent
e0b15350c1
commit
5e0924aeb5
|
@ -9,6 +9,10 @@ from glob import glob
|
|||
USER_CONFDIR = '~/etc/deploy'
|
||||
SYSTEM_CONFDIR = '/var/local/deploy'
|
||||
|
||||
#XXX faire la différence entre "pas de profil défini" (=aucun profil) et
|
||||
# "définition par défaut pour les profils" (si pas de définition plus précise
|
||||
# pour un profil, prendre celle-là)
|
||||
|
||||
################################################################################
|
||||
# Diverses fonctions
|
||||
|
||||
|
@ -18,10 +22,6 @@ def isseq(t):
|
|||
################################################################################
|
||||
# Base de données
|
||||
|
||||
class UNDEFINED(object):
|
||||
__repr__ = __string__ = lambda self: 'UNDEFINED'
|
||||
UNDEFINED = UNDEFINED()
|
||||
|
||||
class GenericObject(object):
|
||||
_id = None
|
||||
_values = None
|
||||
|
@ -155,8 +155,12 @@ class GenericLink(object):
|
|||
self._tos = set()
|
||||
self._attrs = {}
|
||||
|
||||
def is_defaults(self):
|
||||
fos = list(self._fos)
|
||||
return len(fos) == 1 and fos[0] is None
|
||||
|
||||
def get_profile(self): return self._profile
|
||||
def set_profile(self): self._profile = profile
|
||||
def set_profile(self, profile): self._profile = profile
|
||||
profile = property(get_profile, set_profile)
|
||||
|
||||
def get_ftype(self): return self._ftype
|
||||
|
@ -200,6 +204,11 @@ class GenericLink(object):
|
|||
for value in values:
|
||||
self.modify_attr(name, value, method)
|
||||
|
||||
def match_profiles(self, profiles):
|
||||
if not isseq(profiles): profiles = [profiles]
|
||||
for profile in profiles:
|
||||
if profile == self._profile: return True
|
||||
return False
|
||||
def match_fos(self, fos, match='any'):
|
||||
if not isseq(fos): fos = [fos]
|
||||
for fo in fos:
|
||||
|
@ -221,7 +230,8 @@ class GenericLink(object):
|
|||
profile = self.profile or 'ALL'
|
||||
print "%s profile: %s" % (indent, profile)
|
||||
def _dump_fos(self, indent):
|
||||
print "%s from: %s" % (indent, ' '.join(self.fos))
|
||||
fos = [fo or '(default)' for fo in self.fos]
|
||||
print "%s from: %s" % (indent, ' '.join(fos))
|
||||
def _dump_tos(self, indent):
|
||||
print "%s to: %s" % (indent, ' '.join(self.tos))
|
||||
def _dump_attrs(self, indent):
|
||||
|
@ -255,25 +265,63 @@ class RuinstLink(GenericLink):
|
|||
super(RuinstLink, self).__init__('module', 'host')
|
||||
|
||||
def dump(self, indent=''):
|
||||
print "%suinst" % indent
|
||||
print "%sruinst" % indent
|
||||
self._dump_profile(indent)
|
||||
self._dump_fos(indent)
|
||||
self._dump_tos(indent)
|
||||
self._dump_attrs(indent)
|
||||
|
||||
class RwoinstBundleLink(GenericLink):
|
||||
def __init__(self):
|
||||
super(RwoinstBundleLink, self).__init__('wobundle', 'host')
|
||||
|
||||
def dump(self, indent=''):
|
||||
print "%srwoinst bundle" % indent
|
||||
self._dump_profile(indent)
|
||||
self._dump_fos(indent)
|
||||
self._dump_tos(indent)
|
||||
self._dump_attrs(indent)
|
||||
|
||||
class RwoinstWebresLink(GenericLink):
|
||||
def __init__(self):
|
||||
super(RwoinstWebresLink, self).__init__('wobundle', 'host')
|
||||
|
||||
def dump(self, indent=''):
|
||||
print "%srwoinst webres" % indent
|
||||
self._dump_profile(indent)
|
||||
self._dump_fos(indent)
|
||||
self._dump_tos(indent)
|
||||
self._dump_attrs(indent)
|
||||
|
||||
class RtoinstLink(GenericLink):
|
||||
def __init__(self):
|
||||
super(RtoinstLink, self).__init__('webapp', 'host')
|
||||
|
||||
def dump(self, indent=''):
|
||||
print "%srtoinst" % indent
|
||||
self._dump_profile(indent)
|
||||
self._dump_fos(indent)
|
||||
self._dump_tos(indent)
|
||||
self._dump_attrs(indent)
|
||||
|
||||
class UNDEF(object):
|
||||
__repr__ = __string__ = lambda self: 'UNDEF'
|
||||
UNDEF = UNDEF()
|
||||
|
||||
class Database(object):
|
||||
_default_profile = None
|
||||
_default_domain = None
|
||||
|
||||
_objects = None
|
||||
_objects_ids_otype = None
|
||||
_objects_classes = None
|
||||
|
||||
_links = None
|
||||
_links_ltype = None
|
||||
_links_classes = None
|
||||
|
||||
def __init__(self):
|
||||
self._objects = {}
|
||||
self._objects_ids_otype = {}
|
||||
self._objects_classes = {}
|
||||
self._links = {}
|
||||
self._links_ltype = {}
|
||||
self._links_classes = {}
|
||||
|
||||
def has_default_profile(self):
|
||||
|
@ -297,67 +345,68 @@ class Database(object):
|
|||
default_domain = property(get_default_domain, set_default_domain)
|
||||
|
||||
def register_object(self, otype, oclass=None):
|
||||
if not self._objects.has_key(otype):
|
||||
self._objects[otype] = {}
|
||||
if not self._objects_ids_otype.has_key(otype):
|
||||
self._objects_ids_otype[otype] = {}
|
||||
if oclass is None: oclass = GenericObject
|
||||
self._objects_classes[otype] = oclass
|
||||
def get_known_objects(self):
|
||||
return self._objects.keys()
|
||||
known_objects = property(get_known_objects)
|
||||
def get_known_otypes(self):
|
||||
return self._objects_ids_otype.keys()
|
||||
known_otypes = property(get_known_otypes)
|
||||
def get_objects(self, otype):
|
||||
objects = self._objects.get(otype, None)
|
||||
objects = self._objects_ids_otype.get(otype, None)
|
||||
if objects is None: return None
|
||||
return [objects[id] for id in objects if id is not None]
|
||||
def has_object(self, otype, id):
|
||||
objects = self._objects.get(otype, None)
|
||||
objects = self._objects_ids_otype.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)
|
||||
objects = self._objects_ids_otype.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
|
||||
self._objects_ids_otype[otype][id] = object
|
||||
return object
|
||||
|
||||
def register_link(self, ltype, lclass):
|
||||
if not self._links.has_key(ltype):
|
||||
self._links[ltype] = {}
|
||||
if not self._links_ltype.has_key(ltype):
|
||||
self._links_ltype[ltype] = []
|
||||
self._links_classes[ltype] = lclass
|
||||
def get_known_profiles(self, ltype):
|
||||
return self._links[ltype].keys()
|
||||
def get_links(self, ltype, profile, fo=UNDEFINED, to=UNDEFINED, attrs=UNDEFINED, create=False):
|
||||
if fo is UNDEFINED and to is UNDEFINED and attrs is UNDEFINED:
|
||||
raise ValueError("you must set either fo, to ou attrs")
|
||||
plinks = self._links.get(ltype, None)
|
||||
if plinks is None: return None
|
||||
links = plinks.get(profile, None)
|
||||
if links is None: links = plinks[profile] = []
|
||||
def get_known_ltypes(self):
|
||||
return self._links_ltype.keys()
|
||||
known_ltypes = property(get_known_ltypes)
|
||||
def get_links(self, ltype, profile=UNDEF, fo=UNDEF, to=UNDEF, attrs=UNDEF, create=False):
|
||||
links = self._links_ltype.get(ltype, None)
|
||||
if links is None: return None
|
||||
|
||||
found = None
|
||||
for link in links:
|
||||
if (fo is UNDEFINED or link.match_fos(fo)) \
|
||||
and (to is UNDEFINED or link.match_tos(to)) \
|
||||
and (attrs is UNDEFINED or link.match_attrs(attrs)):
|
||||
if (profile is UNDEF or link.match_profiles(profile)) \
|
||||
and (fo is UNDEF or link.match_fos(fo)) \
|
||||
and (to is UNDEF or link.match_tos(to)) \
|
||||
and (attrs is UNDEF or link.match_attrs(attrs)):
|
||||
if found is None: found = []
|
||||
found.append(link)
|
||||
if found is not None: return found
|
||||
if not create: return None
|
||||
if not create: return []
|
||||
# ici, create==True
|
||||
if profile is UNDEF: profile = None
|
||||
link = self._links_classes[ltype]()
|
||||
if fo is not UNDEFINED:
|
||||
link.profile = profile
|
||||
if fo is not UNDEF:
|
||||
if isseq(fo): fos = fo
|
||||
else: fos = [fo]
|
||||
for fo in fos:
|
||||
link.add_fo(fo)
|
||||
if to is not UNDEFINED:
|
||||
if to is not UNDEF:
|
||||
if isseq(to): tos = to
|
||||
else: tos = [to]
|
||||
for to in tos:
|
||||
link.add_to(to)
|
||||
if attrs is not UNDEFINED:
|
||||
if attrs is not UNDEF:
|
||||
for name, value in attrs.items():
|
||||
link.set_attr(name, value)
|
||||
links.append(link)
|
||||
|
@ -809,6 +858,7 @@ class Parser(object):
|
|||
AP.add_argument('nvss', nargs=REMAINDER)
|
||||
o = AP.parse_args(args)
|
||||
profiles = o.profiles or [None]
|
||||
#XXX spliter profiles sur ','
|
||||
for profile in profiles:
|
||||
# préparer la mise à jour du groupe courant
|
||||
currentls = self.db.get_links(ltype, profile, fo=self.groups['module']['current'], create=True)
|
||||
|
@ -823,7 +873,7 @@ class Parser(object):
|
|||
currentl.merge_attrs(defaultl)
|
||||
defaultl = defaultls[0]
|
||||
# traiter les liens
|
||||
for nvs in args:
|
||||
for nvs in o.nvss:
|
||||
name, value, type, method = split_namev(nvs)
|
||||
if name == defaultl.ttype:
|
||||
# définir des destinations du lien
|
||||
|
@ -846,6 +896,8 @@ class Parser(object):
|
|||
############################################################################
|
||||
def __setup_woinst(self):
|
||||
self.db.register_object('wobundle', WobundleObject)
|
||||
self.db.register_link('rwoinst-bundle', RwoinstBundleLink)
|
||||
self.db.register_link('rwoinst-webres', RwoinstWebresLink)
|
||||
self.db.get_object('wobundle', None)
|
||||
self.groups['wobundle'] = {}
|
||||
self.handle_group(['wobundle', 'defaults'])
|
||||
|
@ -919,12 +971,56 @@ class Parser(object):
|
|||
if valuep is not None: o.set_attr('path', valuep)
|
||||
self.add_group(otype, id)
|
||||
|
||||
def handle_rwoinst(self, cmd, *args):
|
||||
pass
|
||||
def handle_rwoinst(self, ltype, *args):
|
||||
"""rwoinst bundle -p profile attrs*
|
||||
rwoinst webres -p profile attrs*
|
||||
"""
|
||||
AP = ArgumentParser()
|
||||
AP.add_argument('-p', '--profile', action='append', dest='profiles')
|
||||
AP.add_argument('stype', nargs=1)
|
||||
AP.add_argument('nvss', nargs=REMAINDER)
|
||||
o = AP.parse_args(args)
|
||||
ltype = "%s-%s" % (ltype, o.stype[0])
|
||||
profiles = o.profiles or [None]
|
||||
#XXX spliter profiles sur ','
|
||||
for profile in profiles:
|
||||
# préparer la mise à jour du groupe courant
|
||||
currentls = self.db.get_links(ltype, profile, fo=self.groups['wobundle']['current'], create=True)
|
||||
if profile is not None:
|
||||
globalls = self.db.get_links(ltype, None, fo=None, create=True)
|
||||
for currentl in currentls:
|
||||
for globall in globalls:
|
||||
currentl.merge_attrs(globall)
|
||||
defaultls = self.db.get_links(ltype, profile, fo=None, create=True)
|
||||
for currentl in currentls:
|
||||
for defaultl in defaultls:
|
||||
currentl.merge_attrs(defaultl)
|
||||
defaultl = defaultls[0]
|
||||
# traiter les liens
|
||||
for nvs in o.nvss:
|
||||
name, value, type, method = split_namev(nvs)
|
||||
if name == defaultl.ttype:
|
||||
# définir des destinations du lien
|
||||
if value is not None:
|
||||
tos = split_nlist(nvs)[1]
|
||||
for to in tos:
|
||||
for currentl in currentls:
|
||||
currentl.add_to(to)
|
||||
else:
|
||||
# définir un attribut du lien
|
||||
#name, value, type, method = split_namev(nv)
|
||||
if value is None:
|
||||
method = 'set'
|
||||
value = '1'
|
||||
elif type == 'path':
|
||||
value = path.expanduser(value)
|
||||
for currentl in currentls:
|
||||
currentl.modify_attr(name, value, method)
|
||||
|
||||
############################################################################
|
||||
def __setup_toinst(self):
|
||||
self.db.register_object('webapp', WebappObject)
|
||||
self.db.register_link('rtoinst', RtoinstLink)
|
||||
self.db.get_object('webapp', None)
|
||||
self.groups['webapp'] = {}
|
||||
self.handle_group(['webapp', 'defaults'])
|
||||
|
@ -996,8 +1092,48 @@ class Parser(object):
|
|||
if valuep is not None: o.set_attr('path', valuep)
|
||||
self.add_group(otype, id)
|
||||
|
||||
def handle_rtoinst(self, cmd, *args):
|
||||
pass
|
||||
def handle_rtoinst(self, ltype, *args):
|
||||
"""rtoinst -p profile attrs*
|
||||
"""
|
||||
AP = ArgumentParser()
|
||||
AP.add_argument('-p', '--profile', action='append', dest='profiles')
|
||||
AP.add_argument('nvss', nargs=REMAINDER)
|
||||
o = AP.parse_args(args)
|
||||
profiles = o.profiles or [None]
|
||||
#XXX spliter profiles sur ','
|
||||
for profile in profiles:
|
||||
# préparer la mise à jour du groupe courant
|
||||
currentls = self.db.get_links(ltype, profile, fo=self.groups['webapp']['current'], create=True)
|
||||
if profile is not None:
|
||||
globalls = self.db.get_links(ltype, None, fo=None, create=True)
|
||||
for currentl in currentls:
|
||||
for globall in globalls:
|
||||
currentl.merge_attrs(globall)
|
||||
defaultls = self.db.get_links(ltype, profile, fo=None, create=True)
|
||||
for currentl in currentls:
|
||||
for defaultl in defaultls:
|
||||
currentl.merge_attrs(defaultl)
|
||||
defaultl = defaultls[0]
|
||||
# traiter les liens
|
||||
for nvs in o.nvss:
|
||||
name, value, type, method = split_namev(nvs)
|
||||
if name == defaultl.ttype:
|
||||
# définir des destinations du lien
|
||||
if value is not None:
|
||||
tos = split_nlist(nvs)[1]
|
||||
for to in tos:
|
||||
for currentl in currentls:
|
||||
currentl.add_to(to)
|
||||
else:
|
||||
# définir un attribut du lien
|
||||
#name, value, type, method = split_namev(nv)
|
||||
if value is None:
|
||||
method = 'set'
|
||||
value = '1'
|
||||
elif type == 'path':
|
||||
value = path.expanduser(value)
|
||||
for currentl in currentls:
|
||||
currentl.modify_attr(name, value, method)
|
||||
|
||||
################################################################################
|
||||
# Programme principal
|
||||
|
@ -1027,7 +1163,7 @@ def run_qdd(o):
|
|||
print "=== predicates"
|
||||
for p in predicates:
|
||||
print ' '.join(map(repr, p))
|
||||
otypes = db.known_objects
|
||||
otypes = db.known_otypes[:]
|
||||
otypes.remove('host')
|
||||
otypes.insert(0, 'host')
|
||||
for otype in otypes:
|
||||
|
@ -1036,6 +1172,13 @@ def run_qdd(o):
|
|||
print "=== %s" % otype
|
||||
for o in objects:
|
||||
o.dump()
|
||||
for ltype in db.known_ltypes:
|
||||
links = db.get_links(ltype)
|
||||
if links:
|
||||
print "=== %s" % ltype
|
||||
for link in links:
|
||||
if link.is_defaults(): continue
|
||||
link.dump(" ")
|
||||
|
||||
elif o.action == 'query':
|
||||
parser = Parser(db).parse(lexer.get_predicates())
|
||||
|
|
Loading…
Reference in New Issue