2017-06-15 01:51:48 +04:00
#!/usr/bin/env python
# -*- coding: utf-8 mode: python -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
import os , sys , re
from os import path
from argparse import ArgumentParser , REMAINDER
from glob import glob
USER_CONFDIR = ' ~/etc/deploy '
SYSTEM_CONFDIR = ' /var/local/deploy '
2017-06-18 11:57:38 +04:00
################################################################################
# Diverses fonctions
def isseq ( t ) :
2017-07-18 20:04:02 +04:00
""" Tester si t est une séquence
"""
2017-06-18 11:57:38 +04:00
return isinstance ( t , list ) or isinstance ( t , tuple ) or isinstance ( t , set )
2017-07-18 17:33:32 +04:00
def flatten ( src , unique = True , clean = True , sep = ' , ' ) :
""" découper chaque élément du tableau src selon sep et les aplatir dans une
seule liste .
Si unique == True , supprimer les doublons .
Si clean == True , supprimer les valeurs vides et les espaces périphériques
e . g flatten ( [ ' a , b ' , ' c, ' ] ) - - > [ ' a ' , ' b ' , ' c ' ]
"""
if not isseq ( src ) : src = [ src ]
dest = [ ]
for items in src :
items = items . split ( sep )
if clean : items = filter ( None , map ( lambda item : item . strip ( ) , items ) )
if unique :
for item in items :
if item not in dest : dest . append ( item )
else :
dest . extend ( items )
return dest
2017-07-18 20:04:02 +04:00
def qshell ( values ) :
if isseq ( values ) : return map ( qshell , values )
elif not values : return ' '
else : return " ' %s ' " % values . replace ( " ' " , " ' \\ ' ' " )
def strip_domain ( a ) :
if a . find ( ' . ' ) == - 1 : return a
else : return a [ : a . find ( ' . ' ) ]
def match_host ( a , b ) :
""" Les hôtes sont matchés de façon particulière:
NAME matche NAME et NAME . DOMAIN
NAME . matche NAME
NAME . DOMAIN matche NAME . DOMAIN
"""
a = a . lower ( )
b = b . lower ( )
if a == b : return True
if a . find ( ' . ' ) == - 1 : # NAME
return a == strip_domain ( b )
elif a . endswith ( ' . ' ) : # NAME.
return a [ : - 1 ] == b
else : # NAME.DOMAIN
return a == b
2017-06-15 21:11:58 +04:00
################################################################################
# Base de données
2017-06-15 23:20:38 +04:00
class GenericObject ( object ) :
2017-07-18 17:33:32 +04:00
""" Un objet générique
Un objet a un identifiant ( propriété id ) , une liste de valeurs ( propriété
values ) et des attributs ( propriété attrs )
"""
2017-07-18 20:04:02 +04:00
OTYPE = ' object '
VALUESNAME = ' values '
ATTRPREFIX = ' object_ '
2017-06-15 21:11:58 +04:00
_id = None
2017-06-15 23:20:38 +04:00
_values = None
2017-06-15 21:11:58 +04:00
_attrs = None
def __init__ ( self , id ) :
self . _id = id
2017-06-18 11:57:38 +04:00
self . _values = set ( )
2017-06-15 21:11:58 +04:00
self . _attrs = { }
2017-06-15 23:20:38 +04:00
2017-06-15 21:11:58 +04:00
def get_id ( self ) : return self . _id
id = property ( get_id )
2017-07-18 20:04:02 +04:00
def is_defaults ( self ) :
""" Cet objet contient-il les attributs par défaut pour le type?
"""
return self . _id is None
def get_values ( self ) : return tuple ( self . _values )
2017-06-15 23:20:38 +04:00
values = property ( get_values )
def add_value ( self , value ) :
2017-06-18 11:57:38 +04:00
self . _values . add ( value )
2017-06-15 21:11:58 +04:00
def get_attrs ( self ) : return self . _attrs
attrs = property ( get_attrs )
2017-07-18 17:33:32 +04:00
def get_attr ( self , name ) :
""" Obtenir la valeur d ' un attribut ou None si l ' attribut n ' existe pas
"""
return self . _attrs . get ( name , None )
2017-06-15 21:11:58 +04:00
def set_attr ( self , name , value ) :
2017-07-18 17:33:32 +04:00
""" Ajouter une valeur à la liste des valeurs d ' un attribut si elle n ' y est pas
déjà .
"""
2017-06-15 21:11:58 +04:00
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 ) :
2017-07-18 17:33:32 +04:00
""" Recommencer à zéro la valeur d ' un attribut
"""
2017-06-15 21:11:58 +04:00
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 ) :
2017-07-18 17:33:32 +04:00
""" Ajouter une valeur à la liste des valeurs d ' un attribut
"""
2017-06-15 21:11:58 +04:00
if name not in self . _attrs : self . _attrs [ name ] = [ ]
self . _attrs [ name ] . append ( value )
def del_attr ( self , name , value ) :
2017-07-18 17:33:32 +04:00
""" Supprimer une valeur d ' un attribut
"""
2017-06-15 21:11:58 +04:00
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 ' ) :
2017-07-18 17:33:32 +04:00
""" Méthode générique pour modifier les valeurs d ' un attribut
method peut valoir set , reset , add , del
"""
2017-06-15 21:11:58 +04:00
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 )
2017-06-16 00:36:36 +04:00
def merge_attrs ( self , other , method = ' set ' ) :
2017-07-18 17:33:32 +04:00
""" Fusionner dans cet objet les attributs d ' un autre objet, avec la méthode
spécifiée .
"""
2017-06-15 21:11:58 +04:00
for name , values in other . attrs . items ( ) :
for value in values :
self . modify_attr ( name , value , method )
2017-07-18 20:04:02 +04:00
def invalid_match ( self , match ) :
return ValueError ( " %s : invalid match type " )
def match_values ( self , values , match = ' any ' , reverse = False ) :
""" Tester si cet objet a l ' une des valeurs spécifiées (avec match== ' any ' qui est
la valeur par défaut )
"""
if not isseq ( values ) : values = [ values ]
if reverse : Yes , No = False , True
else : Yes , No = True , False
if match == ' any ' :
for value in values :
if value in self . _values : return Yes
return No
elif match == ' all ' :
for value in values :
if value not in self . _values : return No
return Yes
else :
raise self . invalid_match ( match )
def match_attrs ( self , attrs , match = ' any ' , reverse = False ) :
""" Tester si cet objet a un des attributs correspondant aux valeurs spécifiées
( avec match == ' any ' qui est la valeur par défaut )
"""
if reverse : Yes , No = False , True
else : Yes , No = True , False
if match == ' any ' :
for name , value in attrs . items ( ) :
values = self . _attrs . get ( name , None )
if values is None : continue
if value in values : return Yes
return No
elif match == ' all ' :
for name , value in attrs . items ( ) :
values = self . _attrs . get ( name , None )
if values is None : return No
if value not in values : return No
return Yes
else :
raise self . invalid_match ( match )
2017-06-15 23:20:38 +04:00
def _dump_id ( self , indent ) :
2017-06-15 21:11:58 +04:00
print " %s %s " % ( indent , self . id )
2017-06-15 23:20:38 +04:00
def _dump_values ( self , indent , name ) :
print " %s %s : %s " % ( indent , name , ' ' . join ( self . values ) )
def _dump_attrs ( self , indent ) :
2017-06-15 21:11:58 +04:00
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 ) ) )
2017-06-15 23:20:38 +04:00
def dump ( self , indent = ' ' ) :
2017-07-18 17:33:32 +04:00
""" Afficher l ' identifiant, les valeurs et les attributs de cet objet
"""
2017-06-15 23:20:38 +04:00
self . _dump_id ( indent )
2017-07-18 20:04:02 +04:00
self . _dump_values ( indent , self . VALUESNAME )
2017-06-15 23:20:38 +04:00
self . _dump_attrs ( indent )
class HostObject ( GenericObject ) :
2017-07-18 17:33:32 +04:00
""" Un hôte
"""
2017-07-18 20:04:02 +04:00
OTYPE = ' host '
VALUESNAME = ' hosts '
ATTRPREFIX = ' host_ '
2017-06-15 23:20:38 +04:00
@staticmethod
def genid ( host ) :
2017-07-18 17:33:32 +04:00
""" Générer un identifiant à partir du nom d ' hôte
e . g . MY - Host42 . tld - - > my_host42
"""
2017-06-15 23:20:38 +04:00
host = re . sub ( r ' \ ..* ' , ' ' , host )
host = re . sub ( r ' [^a-zA-Z0-9] ' , ' _ ' , host )
host = host . lower ( )
return host
@staticmethod
def genib ( id ) :
2017-07-18 17:33:32 +04:00
""" Générer un identifiant générique à partir d ' un identifiant qualifié
e . g . my_host42 - - > my_host
"""
2017-06-15 23:20:38 +04:00
if re . match ( r ' \ d+$ ' , id ) : return id
ib = re . sub ( r ' ^(.*?) \ d+$ ' , r ' \ 1 ' , id )
return ib
2017-07-18 20:04:02 +04:00
def match_values ( self , values , match = ' any ' , reverse = False ) :
if not isseq ( values ) : values = [ values ]
if reverse : Yes , No = False , True
else : Yes , No = True , False
if match == ' any ' :
for value in values :
for host in self . _values :
if match_host ( value , host ) : return Yes
return No
elif match == ' all ' :
for value in values :
for host in self . _values :
if not match_host ( value , host ) : return No
return Yes
else :
raise self . invalid_match ( match )
2017-06-15 23:20:38 +04:00
class ModuleObject ( GenericObject ) :
2017-07-18 17:33:32 +04:00
""" Un module, uinst-allable
"""
2017-07-18 20:04:02 +04:00
OTYPE = ' module '
VALUESNAME = ' modules '
ATTRPREFIX = ' module_ '
2017-06-15 23:20:38 +04:00
@staticmethod
def genid ( module ) :
2017-07-18 17:33:32 +04:00
""" Générér un identifiant à partir du nom du module
e . g . MY - Module - - > MY_Module
"""
2017-06-15 23:20:38 +04:00
module = re . sub ( r ' [^a-zA-Z0-9] ' , ' _ ' , module )
return module
class WobundleObject ( GenericObject ) :
2017-07-18 17:33:32 +04:00
""" Un bundle Webobjects, woinst-allable
"""
2017-07-18 20:04:02 +04:00
OTYPE = ' wobundle '
VALUESNAME = ' wobundles '
ATTRPREFIX = ' wobundle_ '
2017-06-15 23:20:38 +04:00
@staticmethod
def genid ( wobundle ) :
2017-07-18 17:33:32 +04:00
""" Générér un identifiant à partir du nom du bundle
e . g . MY - App . woa - - > MY_App
"""
2017-06-15 23:20:38 +04:00
wobundle = re . sub ( r ' \ .(woa|framework)$ ' , ' ' , wobundle )
wobundle = re . sub ( r ' [^a-zA-Z0-9] ' , ' _ ' , wobundle )
return wobundle
class WebappObject ( GenericObject ) :
2017-07-18 17:33:32 +04:00
""" Une webapp, toinst-allable
"""
2017-07-18 20:04:02 +04:00
OTYPE = ' webapp '
VALUESNAME = ' webapps '
ATTRPREFIX = ' webapp_ '
2017-06-15 23:20:38 +04:00
@staticmethod
def genid ( webapp ) :
2017-07-18 17:33:32 +04:00
""" Générér un identifiant à partir du nom de la webapp
e . g . MY - Webapp - - > MY_Webapp
"""
2017-06-15 23:20:38 +04:00
webapp = re . sub ( r ' [^a-zA-Z0-9] ' , ' _ ' , webapp )
return webapp
2017-06-16 00:36:36 +04:00
class GenericLink ( object ) :
2017-07-18 17:33:32 +04:00
""" Un lien générique
Un lien est valide dans un profil ( propriété profile ) , a un type d ' objets de
départ ( propriété ftype ) , un type d ' objet d ' arrivée ( propriété ttype ) , un
ensemble d ' objets de départ (propriété fos), un ensemble d ' objets d ' arrivée
( propriété tos ) , et des attributs ( propriété attrs ) .
"""
2017-06-16 00:36:36 +04:00
_profile = None
_ftype = None
2017-06-18 11:57:38 +04:00
_fos = None
2017-06-16 00:36:36 +04:00
_ttype = None
_tos = None
_attrs = None
def __init__ ( self , ftype , ttype ) :
self . _ftype = ftype
2017-06-18 11:57:38 +04:00
self . _fos = set ( )
2017-06-16 00:36:36 +04:00
self . _ttype = ttype
2017-06-18 11:57:38 +04:00
self . _tos = set ( )
2017-06-16 00:36:36 +04:00
self . _attrs = { }
2017-06-18 21:59:38 +04:00
def is_defaults ( self ) :
2017-07-18 17:33:32 +04:00
""" Cet objet contient-il les attributs par défaut pour les liens provenant du
type d ' objet ftype
"""
2017-06-18 21:59:38 +04:00
fos = list ( self . _fos )
return len ( fos ) == 1 and fos [ 0 ] is None
2017-06-16 00:36:36 +04:00
def get_profile ( self ) : return self . _profile
2017-06-18 21:59:38 +04:00
def set_profile ( self , profile ) : self . _profile = profile
2017-06-16 00:36:36 +04:00
profile = property ( get_profile , set_profile )
def get_ftype ( self ) : return self . _ftype
ftype = property ( get_ftype )
2017-06-18 11:57:38 +04:00
def get_fos ( self ) : return self . _fos
fos = property ( get_fos )
def add_fo ( self , fo ) :
self . _fos . add ( fo )
2017-06-16 00:36:36 +04:00
def get_ttype ( self ) : return self . _ttype
ttype = property ( get_ttype )
def get_tos ( self ) : return self . _tos
tos = property ( get_tos )
def add_to ( self , to ) :
2017-06-18 11:57:38 +04:00
self . _tos . add ( to )
2017-06-16 00:36:36 +04:00
def get_attrs ( self ) : return self . _attrs
attrs = property ( get_attrs )
2017-07-18 17:33:32 +04:00
def get_attr ( self , name ) :
""" Obtenir la valeur d ' un attribut ou None si l ' attribut n ' existe pas
"""
return self . _attrs . get ( name , None )
2017-06-16 00:36:36 +04:00
def set_attr ( self , name , value ) :
2017-07-18 17:33:32 +04:00
""" Ajouter une valeur à la liste des valeurs d ' un attribut si elle n ' y est pas
déjà .
"""
2017-06-16 00:36:36 +04:00
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 ) :
2017-07-18 17:33:32 +04:00
""" Recommencer à zéro la valeur d ' un attribut
"""
2017-06-16 00:36:36 +04:00
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 ) :
2017-07-18 17:33:32 +04:00
""" Ajouter une valeur à la liste des valeurs d ' un attribut
"""
2017-06-16 00:36:36 +04:00
if name not in self . _attrs : self . _attrs [ name ] = [ ]
self . _attrs [ name ] . append ( value )
def del_attr ( self , name , value ) :
2017-07-18 17:33:32 +04:00
""" Supprimer une valeur d ' un attribut
"""
2017-06-16 00:36:36 +04:00
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 ' ) :
2017-07-18 17:33:32 +04:00
""" Méthode générique pour modifier les valeurs d ' un attribut
method peut valoir set , reset , add , del
"""
2017-06-16 00:36:36 +04:00
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 merge_attrs ( self , other , method = ' set ' ) :
2017-07-18 17:33:32 +04:00
""" Fusionner dans ce lien les attributs d ' un autre lien, avec la méthode
spécifiée .
"""
2017-06-16 00:36:36 +04:00
for name , values in other . attrs . items ( ) :
for value in values :
self . modify_attr ( name , value , method )
2017-07-18 17:47:58 +04:00
def invalid_match ( self , match ) :
return ValueError ( " %s : invalid match type " )
2017-06-18 21:59:38 +04:00
def match_profiles ( self , profiles ) :
2017-07-18 17:33:32 +04:00
""" Tester si ce lien est dans l ' un des profils spécifiés
Si profiles == None , alors l ' utilisateur ne demande aucun profil en
particulier . Dans ce cas , la réponse est OUI .
Si profiles == [ ] , alors l ' utilisateur demande tous les liens pour
lesquels aucun profil n ' est défini. Dans ce cas, la réponse est OUI si
ce lien ne définit aucun profil .
Sinon , profiles est une liste des profils recherchés . Dans ce cas , la
réponse n ' est OUI que si le profil de ce lien fait partie des profils
spécifiés .
"""
if profiles is None : return True
2017-06-18 21:59:38 +04:00
if not isseq ( profiles ) : profiles = [ profiles ]
2017-07-18 17:33:32 +04:00
if profiles == [ ] : return self . _profile is None
2017-06-18 21:59:38 +04:00
for profile in profiles :
if profile == self . _profile : return True
return False
2017-07-18 17:47:58 +04:00
def match_fos ( self , fos , match = ' any ' , reverse = False ) :
2017-07-18 17:33:32 +04:00
""" Tester si ce lien a l ' un des objets spécifiés dans ses objets de départ (avec
match == ' any ' qui est la valeur par défaut )
"""
2017-06-18 11:57:38 +04:00
if not isseq ( fos ) : fos = [ fos ]
2017-07-18 17:47:58 +04:00
if reverse : Yes , No = False , True
else : Yes , No = True , False
if match == ' any ' :
for fo in fos :
if fo in self . _fos : return Yes
return No
elif match == ' all ' :
for fo in fos :
if fo not in self . _fos : return No
return Yes
else :
raise self . invalid_match ( match )
def match_tos ( self , tos , match = ' any ' , reverse = False ) :
2017-07-18 17:33:32 +04:00
""" Tester si ce lien a l ' un des objets spécifiés dans ses objets d ' arrivée (avec
match == ' any ' qui est la valeur par défaut )
"""
2017-06-18 11:57:38 +04:00
if not isseq ( tos ) : tos = [ tos ]
2017-07-18 17:47:58 +04:00
if reverse : Yes , No = False , True
else : Yes , No = True , False
if match == ' any ' :
for to in tos :
if to in self . _tos : return Yes
return No
elif match == ' all ' :
for to in tos :
if to not in self . _tos : return No
return Yes
else :
raise self . invalid_match ( match )
def match_attrs ( self , attrs , match = ' any ' , reverse = False ) :
2017-07-18 17:33:32 +04:00
""" Tester si ce lien a un des attributs correspondant aux valeurs spécifiées
( avec match == ' any ' qui est la valeur par défaut )
"""
2017-07-18 17:47:58 +04:00
if reverse : Yes , No = False , True
else : Yes , No = True , False
if match == ' any ' :
for name , value in attrs . items ( ) :
values = self . _attrs . get ( name , None )
if values is None : continue
if value in values : return Yes
return No
elif match == ' all ' :
for name , value in attrs . items ( ) :
values = self . _attrs . get ( name , None )
if values is None : return No
if value not in values : return No
return Yes
else :
raise self . invalid_match ( match )
2017-06-18 11:57:38 +04:00
2017-06-16 00:36:36 +04:00
def _dump_profile ( self , indent ) :
profile = self . profile or ' ALL '
print " %s profile: %s " % ( indent , profile )
2017-06-18 11:57:38 +04:00
def _dump_fos ( self , indent ) :
2017-06-18 21:59:38 +04:00
fos = [ fo or ' (default) ' for fo in self . fos ]
print " %s from: %s " % ( indent , ' ' . join ( fos ) )
2017-06-16 00:36:36 +04:00
def _dump_tos ( self , indent ) :
print " %s to: %s " % ( indent , ' ' . join ( self . tos ) )
def _dump_attrs ( self , indent ) :
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 ) ) )
def dump ( self , indent = ' ' ) :
2017-07-18 17:33:32 +04:00
""" Afficher le profil, les objets de départ, les objets d ' arrivée, et les
attributs de ce lien
"""
2017-06-16 00:36:36 +04:00
print " %s link " % indent
self . _dump_profile ( indent )
2017-06-18 11:57:38 +04:00
self . _dump_fos ( indent )
2017-06-16 00:36:36 +04:00
self . _dump_tos ( indent )
self . _dump_attrs ( indent )
class UinstLink ( GenericLink ) :
2017-07-18 17:33:32 +04:00
""" Un module déployé sur un hôte avec le type uinst:rsync
"""
2017-06-16 00:36:36 +04:00
def __init__ ( self ) :
super ( UinstLink , self ) . __init__ ( ' module ' , ' host ' )
def dump ( self , indent = ' ' ) :
print " %s uinst " % indent
self . _dump_profile ( indent )
2017-06-18 11:57:38 +04:00
self . _dump_fos ( indent )
2017-06-16 00:36:36 +04:00
self . _dump_tos ( indent )
self . _dump_attrs ( indent )
class RuinstLink ( GenericLink ) :
2017-07-18 17:33:32 +04:00
""" Un module déployé sur un hôte avec ruinst
"""
2017-06-16 00:36:36 +04:00
def __init__ ( self ) :
2017-06-18 11:57:38 +04:00
super ( RuinstLink , self ) . __init__ ( ' module ' , ' host ' )
2017-06-16 00:36:36 +04:00
def dump ( self , indent = ' ' ) :
2017-06-18 21:59:38 +04:00
print " %s ruinst " % indent
self . _dump_profile ( indent )
self . _dump_fos ( indent )
self . _dump_tos ( indent )
self . _dump_attrs ( indent )
class RwoinstBundleLink ( GenericLink ) :
2017-07-18 17:33:32 +04:00
""" Un bundle déployé sur un hôte avec rwoinst
"""
2017-06-18 21:59:38 +04:00
def __init__ ( self ) :
super ( RwoinstBundleLink , self ) . __init__ ( ' wobundle ' , ' host ' )
def dump ( self , indent = ' ' ) :
print " %s rwoinst bundle " % indent
self . _dump_profile ( indent )
self . _dump_fos ( indent )
self . _dump_tos ( indent )
self . _dump_attrs ( indent )
class RwoinstWebresLink ( GenericLink ) :
2017-07-18 17:33:32 +04:00
""" Les resources web d ' un bundle déployées sur un hôte avec rwoinst
"""
2017-06-18 21:59:38 +04:00
def __init__ ( self ) :
super ( RwoinstWebresLink , self ) . __init__ ( ' wobundle ' , ' host ' )
def dump ( self , indent = ' ' ) :
print " %s rwoinst webres " % indent
self . _dump_profile ( indent )
self . _dump_fos ( indent )
self . _dump_tos ( indent )
self . _dump_attrs ( indent )
class RtoinstLink ( GenericLink ) :
2017-07-18 17:33:32 +04:00
""" Une webapp déployée sur un hôte avec rtoinst
"""
2017-06-18 21:59:38 +04:00
def __init__ ( self ) :
super ( RtoinstLink , self ) . __init__ ( ' webapp ' , ' host ' )
def dump ( self , indent = ' ' ) :
print " %s rtoinst " % indent
self . _dump_profile ( indent )
2017-06-18 11:57:38 +04:00
self . _dump_fos ( indent )
2017-06-16 00:36:36 +04:00
self . _dump_tos ( indent )
self . _dump_attrs ( indent )
2017-06-18 21:59:38 +04:00
class UNDEF ( object ) :
__repr__ = __string__ = lambda self : ' UNDEF '
UNDEF = UNDEF ( )
2017-06-15 21:11:58 +04:00
class Database ( object ) :
2017-07-18 17:33:32 +04:00
""" La base de données des objets et des liens
"""
2017-06-15 21:11:58 +04:00
_default_profile = None
_default_domain = None
2017-06-18 21:59:38 +04:00
_objects_ids_otype = None
2017-06-15 21:11:58 +04:00
_objects_classes = None
2017-06-18 21:59:38 +04:00
_links_ltype = None
2017-06-16 00:36:36 +04:00
_links_classes = None
2017-06-15 21:11:58 +04:00
def __init__ ( self ) :
2017-06-18 21:59:38 +04:00
self . _objects_ids_otype = { }
2017-06-15 21:11:58 +04:00
self . _objects_classes = { }
2017-06-18 21:59:38 +04:00
self . _links_ltype = { }
2017-06-16 00:36:36 +04:00
self . _links_classes = { }
2017-06-15 21:11:58 +04:00
def has_default_profile ( self ) :
2017-07-18 17:33:32 +04:00
""" Vérifier si un profil par défaut a été spécifié
"""
2017-06-15 21:11:58 +04:00
return self . _default_profile is not None
def get_default_profile ( self ) :
2017-07-18 17:33:32 +04:00
""" Obtenir le profil par défaut, ou None si aucun profil par défaut n ' a été
défini
"""
2017-06-15 21:11:58 +04:00
return self . _default_profile
def set_default_profile ( self , profile ) :
2017-07-18 17:33:32 +04:00
""" Spécifier le profil par défaut
Si un lien est spécifié sans profil , il est réputé défini dans le
profil par défaut .
"""
2017-06-15 21:11:58 +04:00
self . _default_profile = profile or None
default_profile = property ( get_default_profile , set_default_profile )
def has_default_domain ( self ) :
2017-07-18 17:33:32 +04:00
""" Vérifier si un domaine par défaut a été spécifié
"""
2017-06-15 21:11:58 +04:00
return self . _default_domain is not None
def get_default_domain ( self ) :
2017-07-18 17:33:32 +04:00
""" Obtenir le domaine par défaut, ou None si aucun domaine par défaut n ' a été
défini
"""
2017-06-15 21:11:58 +04:00
return self . _default_domain
def set_default_domain ( self , domain ) :
2017-07-18 17:33:32 +04:00
""" Spécifier le domaine par défaut
Si un hôte est spécifié sans domaine , il est réputé défini avec le
domaine par défaut .
"""
2017-06-15 21:11:58 +04:00
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 )
2017-06-15 23:20:38 +04:00
def register_object ( self , otype , oclass = None ) :
2017-07-18 17:33:32 +04:00
""" Enregistrer un type d ' objet et la classe utilisée pour l ' instancier.
Par défaut , le classe utilisé est GenericObject .
"""
2017-06-18 21:59:38 +04:00
if not self . _objects_ids_otype . has_key ( otype ) :
self . _objects_ids_otype [ otype ] = { }
2017-06-15 23:20:38 +04:00
if oclass is None : oclass = GenericObject
2017-06-15 21:11:58 +04:00
self . _objects_classes [ otype ] = oclass
2017-06-18 21:59:38 +04:00
def get_known_otypes ( self ) :
2017-07-18 17:33:32 +04:00
""" Obtenir la liste des types d ' objets connus
"""
2017-06-18 21:59:38 +04:00
return self . _objects_ids_otype . keys ( )
known_otypes = property ( get_known_otypes )
2017-07-18 20:04:02 +04:00
def get_objects ( self , otype , value = UNDEF , attrs = UNDEF ) :
2017-07-18 17:33:32 +04:00
""" Obtenir tous les objets définis du type spécifié ou None si le type d ' objets
2017-07-18 20:04:02 +04:00
est invalide . Si value ou attrs sont définis , filtrer sur ces valeurs .
2017-07-18 17:33:32 +04:00
"""
2017-07-18 20:04:02 +04:00
if otype is None :
objects = [ ]
for objects_ids in self . _objects_ids_otype . values ( ) :
objects . extend ( objects_ids . values ( ) )
else :
objects = self . _objects_ids_otype . get ( otype , None )
if objects is None : return None
objects = [ objects [ id ] for id in objects if id is not None ]
return [
object for object in objects if
( value is UNDEF or object . match_values ( value ) ) and
( attrs is UNDEF or object . match_attrs ( attrs ) )
]
2017-06-15 21:11:58 +04:00
def has_object ( self , otype , id ) :
2017-07-18 17:33:32 +04:00
""" Vérifier si l ' objet avec l ' identifiant spécifié est défini
"""
2017-06-18 21:59:38 +04:00
objects = self . _objects_ids_otype . get ( otype , None )
2017-06-15 21:11:58 +04:00
if objects is None : return False
return objects . has_key ( id )
2017-07-18 17:33:32 +04:00
def get_object ( self , otype , id , create = True ) :
""" Obtenir l ' objet avec l ' identifiant spécifié, ou None si l ' objet n ' existe pas.
Si create == True , l ' objet est créé s ' il n ' existe pas, et cette méthode ne
retourne pas None .
"""
2017-06-18 21:59:38 +04:00
objects = self . _objects_ids_otype . get ( otype , None )
2017-06-15 21:11:58 +04:00
if objects is None : return None
object = objects . get ( id , None )
2017-07-18 17:33:32 +04:00
if object is None and create :
2017-06-15 21:11:58 +04:00
object_class = self . _objects_classes . get ( otype , None )
if object_class is not None :
object = object_class ( id )
2017-06-18 21:59:38 +04:00
self . _objects_ids_otype [ otype ] [ id ] = object
2017-06-15 21:11:58 +04:00
return object
2017-06-18 11:57:38 +04:00
def register_link ( self , ltype , lclass ) :
2017-07-18 17:33:32 +04:00
""" Enregister un type de lien et la classe utilisée pour l ' instancier.
Il n ' y a pas de classe par défaut, il faut absolument spécifier une
classe valide .
"""
2017-06-18 21:59:38 +04:00
if not self . _links_ltype . has_key ( ltype ) :
self . _links_ltype [ ltype ] = [ ]
2017-06-16 00:36:36 +04:00
self . _links_classes [ ltype ] = lclass
2017-06-18 21:59:38 +04:00
def get_known_ltypes ( self ) :
2017-07-18 17:33:32 +04:00
""" Obtenir la liste des types de liens connus
"""
2017-06-18 21:59:38 +04:00
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 ) :
2017-07-18 17:33:32 +04:00
""" Obtenir les liens correspondant aux critères.
XXX compléter la doc
"""
2017-06-18 21:59:38 +04:00
links = self . _links_ltype . get ( ltype , None )
if links is None : return None
2017-06-18 11:57:38 +04:00
found = None
for link in links :
2017-06-18 21:59:38 +04:00
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 ) ) :
2017-06-18 11:57:38 +04:00
if found is None : found = [ ]
found . append ( link )
if found is not None : return found
2017-06-18 21:59:38 +04:00
if not create : return [ ]
# ici, create==True
if profile is UNDEF : profile = None
2017-06-18 11:57:38 +04:00
link = self . _links_classes [ ltype ] ( )
2017-06-18 21:59:38 +04:00
link . profile = profile
if fo is not UNDEF :
2017-06-18 11:57:38 +04:00
if isseq ( fo ) : fos = fo
else : fos = [ fo ]
for fo in fos :
link . add_fo ( fo )
2017-06-18 21:59:38 +04:00
if to is not UNDEF :
2017-06-18 11:57:38 +04:00
if isseq ( to ) : tos = to
else : tos = [ to ]
for to in tos :
link . add_to ( to )
2017-06-18 21:59:38 +04:00
if attrs is not UNDEF :
2017-06-18 11:57:38 +04:00
for name , value in attrs . items ( ) :
link . set_attr ( name , value )
links . append ( link )
return [ link ]
2017-06-16 00:36:36 +04:00
2017-06-15 21:11:58 +04:00
################################################################################
# Analyse des fichiers de configuration
2017-06-15 01:51:48 +04:00
class EOL ( object ) :
__repr__ = __string__ = lambda self : ' EOL '
EOL = EOL ( )
class EOF ( object ) :
__repr__ = __string__ = lambda self : ' EOF '
EOF = EOF ( )
class Lexer ( object ) :
file = None
lexems = None
_inf = None
_lcount = None
_line = None
def __init__ ( self , file , parse = True ) :
self . file = file
if parse : self . parse ( )
def next_line ( self ) :
line = self . _inf . readline ( )
if line == ' ' : return None
if line . endswith ( " \r \n " ) : line = line [ : - 2 ]
elif line . endswith ( " \n " ) : line = line [ : - 1 ]
elif line . endswith ( " \r " ) : line = line [ : - 1 ]
self . _lcount + = 1
self . _line = line
return line
def is_empty ( self ) : return self . _line == ' '
def isa_comment ( self ) : return self . _line [ : 1 ] == ' # '
def isa_squote ( self ) : return self . _line [ : 1 ] == " ' "
def isa_dquote ( self ) : return self . _line [ : 1 ] == ' " '
RE_SPACE = re . compile ( r ' \ s+ ' )
RE_COMMENT = re . compile ( r ' #.* ' )
def parse_ws ( self ) :
mo = self . RE_SPACE . match ( self . _line )
if mo is not None :
self . _line = self . _line [ mo . end ( 0 ) : ]
mo = self . RE_COMMENT . match ( self . _line )
if mo is not None :
self . _line = self . _line [ mo . end ( 0 ) : ]
def isa_space ( self ) : return self . RE_SPACE . match ( self . _line ) is not None
def isa_comment ( self ) : return self . RE_COMMENT . match ( self . _line ) is not None
RE_SQUOTE = re . compile ( r " ' " )
def parse_sstring ( self ) :
slos = self . _lcount
lexem = ' '
self . _line = self . _line [ 1 : ]
mo = self . RE_SQUOTE . search ( self . _line )
while mo is None :
lexem + = self . _line
if self . next_line ( ) is None :
raise ValueError ( " unterminated quoted string starting at line %i " % slos )
lexem + = " \n "
mo = self . RE_SQUOTE . search ( self . _line )
lexem + = self . _line [ 0 : mo . start ( 0 ) ]
self . _line = self . _line [ mo . end ( 0 ) : ]
return lexem
RE_DQUOTE = re . compile ( r ' " ' )
def parse_dstring ( self ) :
slos = self . _lcount
lexem = ' '
self . _line = self . _line [ 1 : ]
mo = self . RE_DQUOTE . search ( self . _line )
while mo is None :
lexem + = self . _line
if self . next_line ( ) is None :
raise ValueError ( " unterminated double-quoted string starting at line %i " % slos )
lexem + = " \n "
mo = self . RE_DQUOTE . search ( self . _line )
lexem + = self . _line [ 0 : mo . start ( 0 ) ]
self . _line = self . _line [ mo . end ( 0 ) : ]
lexem = lexem . replace ( ' \\ " ' , ' " ' )
lexem = lexem . replace ( " \\ ' " , " ' " )
lexem = lexem . replace ( ' \\ \\ ' , ' \\ ' )
return lexem
RE_EOS = re . compile ( r ''' \ s|(?<! \ \ )[ ' " ] ''' )
def parse_string ( self ) :
mo = self . RE_EOS . search ( self . _line )
if mo is not None :
lexem = self . _line [ 0 : mo . start ( 0 ) ]
self . _line = self . _line [ mo . start ( 0 ) : ]
else :
lexem = self . _line
self . _line = ' '
lexem = lexem . replace ( ' \\ " ' , ' " ' )
lexem = lexem . replace ( " \\ ' " , " ' " )
lexem = lexem . replace ( ' \\ \\ ' , ' \\ ' )
return lexem
def parse ( self ) :
if self . lexems is not None : return self . lexems
lexems = self . lexems = [ ]
self . _inf = open ( self . file , ' rb ' )
self . _lcount = 0
self . _line = ' '
try :
SOL = False
while True :
# Ignorer lignes vides et commentaires
self . parse_ws ( )
stop = False
while self . is_empty ( ) :
if SOL :
lexems . append ( EOL )
SOL = False
if self . next_line ( ) is None :
stop = True
break
self . parse_ws ( )
if stop : break
SOL = True
# Construire une chaine
lexem = ' '
while True :
if self . is_empty ( ) : break
elif self . isa_space ( ) : break
if self . isa_squote ( ) : lexem + = self . parse_sstring ( )
elif self . isa_dquote ( ) : lexem + = self . parse_dstring ( )
else : lexem + = self . parse_string ( )
lexems . append ( lexem )
lexems . append ( EOF )
return lexems
finally :
self . _inf . close ( )
self . _inf = None
return lexems
def get_predicates ( self ) :
predicates = [ ]
predicate = [ ]
for lexem in self . parse ( ) :
if lexem is EOF : break
elif lexem is EOL :
predicates . append ( predicate )
predicate = [ ]
else :
predicate . append ( lexem )
return predicates
2017-06-15 23:20:38 +04:00
RE_NAMETYPE = re . compile ( r ' ( \ S+):( \ w+)$ ' )
def split_namev ( arg ) :
" spliter name[:type][method][=value] "
2017-06-15 01:51:48 +04:00
if ' = ' in arg :
name , value = arg . split ( ' = ' , 1 )
else :
name = arg
value = None
if name . endswith ( ' % ' ) :
name = name [ : - 1 ]
2017-06-15 02:24:17 +04:00
method = ' reset '
elif name . endswith ( ' + ' ) :
name = name [ : - 1 ]
method = ' add '
elif name . endswith ( ' - ' ) :
name = name [ : - 1 ]
method = ' del '
2017-06-15 01:51:48 +04:00
else :
2017-06-15 02:24:17 +04:00
method = ' set '
2017-06-15 23:20:38 +04:00
mo = RE_NAMETYPE . match ( name )
if mo is not None :
name , type = mo . groups ( )
else :
type = None
return name , value , type , method
2017-06-15 01:51:48 +04:00
2017-06-15 23:20:38 +04:00
def split_nvalue ( arg ) :
" spliter [name=]value "
if ' = ' in arg :
name , value = arg . split ( ' = ' , 1 )
else :
name = None
value = arg
return name , value
def split_nlist ( arg ) :
" spliter [name=]values "
2017-06-15 01:51:48 +04:00
if ' = ' in arg :
name , values = arg . split ( ' = ' , 1 )
values = values . split ( ' , ' )
else :
name = None
values = arg . split ( ' , ' )
return name , values
class Parser ( object ) :
2017-06-15 21:11:58 +04:00
db = None
2017-06-15 01:51:48 +04:00
groups = None
attr_otype = None
2017-06-15 23:20:38 +04:00
commands = None
2017-06-15 21:11:58 +04:00
def __init__ ( self , db = None ) :
if db is None : db = Database ( )
self . db = db
2017-06-15 01:51:48 +04:00
self . groups = { }
2017-07-18 17:33:32 +04:00
self . commands = {
' default_profile ' : self . handle_default_profile ,
' default_domain ' : self . handle_default_domain ,
' group ' : self . handle_group ,
' attr ' : self . handle_attr ,
}
2017-06-15 01:51:48 +04:00
self . __setup_hosts ( )
2017-06-15 23:20:38 +04:00
self . __setup_uinst ( )
self . __setup_woinst ( )
self . __setup_toinst ( )
2017-07-18 17:33:32 +04:00
self . __setup_query ( )
2017-06-15 01:51:48 +04:00
2017-06-15 21:11:58 +04:00
def parse ( self , predicates ) :
for p in predicates :
2017-06-15 01:51:48 +04:00
cmd = p [ 0 ]
args = p [ 1 : ]
2017-07-18 17:33:32 +04:00
if cmd in self . commands : self . commands [ cmd ] ( * p )
else : raise ValueError ( " %s : unknown command " % cmd )
2017-06-15 21:11:58 +04:00
return self
2017-06-15 01:51:48 +04:00
2017-06-15 23:20:38 +04:00
def register_command ( self , name , method ) :
self . commands [ name ] = method
2017-06-15 01:51:48 +04:00
############################################################################
def reset_group ( self , otype ) :
2017-06-18 11:57:38 +04:00
self . groups [ otype ] [ ' current ' ] = set ( )
2017-06-15 01:51:48 +04:00
def reset_group_maybe ( self , otype ) :
if self . groups [ otype ] [ ' type ' ] in ( ' defaults ' , ' once ' ) :
self . reset_group ( otype )
self . groups [ otype ] [ ' type ' ] = ' once '
def add_group ( self , otype , id ) :
2017-06-18 11:57:38 +04:00
self . groups [ otype ] [ ' current ' ] . add ( id )
2017-06-15 01:51:48 +04:00
2017-07-18 17:33:32 +04:00
def handle_group ( self , cmd , * args ) :
""" group otype [gtype]
2017-06-15 01:51:48 +04:00
gtype peut valoir :
- defaults : revenir à l ' état initial, permettant de spécifier les
attributs et liens pour tous les hôtes définis à partir de cette ligne
2017-07-18 17:33:32 +04:00
- once : un nouveau groupe est défini à chaque nouvelle définition
d ' objet. en d ' autres termes , ne font partie du groupe que les objets
faisant partie d ' une même définition. c ' est la valeur par défaut
- until : définir un groupe qui va jusqu ' à la prochaine définition de
groupe ou de lien .
2017-06-15 01:51:48 +04:00
"""
otype = args [ 0 : 1 ] and args [ 0 ] or ' host '
2017-06-15 02:24:17 +04:00
if otype not in self . groups :
raise ValueError ( ' %s : invalid object type ' % otype )
2017-07-18 17:33:32 +04:00
gtype = args [ 1 : 2 ] and args [ 1 ] or ' once '
2017-06-15 01:51:48 +04:00
self . groups [ otype ] [ ' type ' ] = gtype
if gtype == ' defaults ' :
2017-06-18 11:57:38 +04:00
self . groups [ otype ] [ ' current ' ] = set ( [ None ] )
2017-06-15 01:51:48 +04:00
elif gtype in ( ' once ' , ' until ' ) :
2017-06-18 11:57:38 +04:00
self . groups [ otype ] [ ' current ' ] = set ( )
2017-06-15 02:24:17 +04:00
else :
raise ValueError ( ' %s : invalid group type ' % gtype )
2017-06-15 23:20:38 +04:00
self . attr_otype = otype
2017-06-15 01:51:48 +04:00
############################################################################
2017-07-18 17:33:32 +04:00
def handle_attr ( self , cmd , * args ) :
2017-06-15 01:51:48 +04:00
otype = self . attr_otype
assert otype is not None , " attr_otype should not be None "
for nv in args :
2017-06-15 23:20:38 +04:00
name , value , type , method = split_namev ( nv )
2017-06-15 01:51:48 +04:00
if value is None :
2017-06-15 02:24:17 +04:00
method = ' set '
2017-06-15 01:51:48 +04:00
value = ' 1 '
2017-06-15 23:20:38 +04:00
elif type == ' path ' :
value = path . expanduser ( value )
2017-06-15 01:51:48 +04:00
for id in self . groups [ otype ] [ ' current ' ] :
2017-06-15 21:11:58 +04:00
self . db . get_object ( otype , id ) . modify_attr ( name , value , method )
2017-06-15 01:51:48 +04:00
############################################################################
2017-07-18 17:33:32 +04:00
def handle_default_profile ( self , cmd , * args ) :
2017-06-15 21:11:58 +04:00
if not args or not args [ 0 ] : profile = None
else : profile = args [ 0 ]
self . db . default_profile = profile
2017-06-15 01:51:48 +04:00
############################################################################
2017-07-18 17:33:32 +04:00
def handle_default_domain ( self , cmd , * args ) :
2017-06-15 21:11:58 +04:00
if not args or not args [ 0 ] : domain = None
else : domain = args [ 0 ]
self . db . default_domain = domain
2017-06-15 01:51:48 +04:00
############################################################################
def __setup_hosts ( self ) :
2017-06-15 21:11:58 +04:00
self . db . register_object ( ' host ' , HostObject )
self . db . get_object ( ' host ' , None )
2017-06-15 01:51:48 +04:00
self . groups [ ' host ' ] = { }
2017-07-18 17:33:32 +04:00
self . handle_group ( ' group ' , ' host ' , ' defaults ' )
self . register_command ( ' host ' , self . handle_host )
2017-06-15 01:51:48 +04:00
def __fix_host ( self , host ) :
if host . endswith ( ' . ' ) :
host = host [ : - 1 ]
2017-06-15 21:11:58 +04:00
elif ' . ' not in host and self . db . has_default_domain ( ) :
host = ' %s . %s ' % ( host , self . db . default_domain )
2017-06-15 01:51:48 +04:00
return host
2017-06-16 07:36:13 +04:00
def handle_host ( self , otype , * args ) :
2017-06-15 01:51:48 +04:00
""" host [id=]host,...
2017-06-15 23:20:38 +04:00
host - b [ id = ] basedir
host - d [ id = ] dirspec
2017-06-15 01:51:48 +04:00
"""
AP = ArgumentParser ( )
AP . add_argument ( ' -b ' , ' --basedir ' , action = ' append ' , dest = ' basedirs ' )
AP . add_argument ( ' -d ' , ' --dirspec ' , action = ' append ' , dest = ' dirspecs ' )
AP . add_argument ( ' nvss ' , nargs = REMAINDER )
o = AP . parse_args ( args )
# construire la liste des hôtes à traiter
nvss = [ ]
if o . basedirs is not None :
2017-06-15 23:20:38 +04:00
for pb in o . basedirs :
p , b = split_nvalue ( pb )
if p is None : prefix = ' '
else : prefix = p + ' = '
basedir = path . expanduser ( b )
nvss . extend ( [ prefix + path . abspath ( path . join ( basedir , name ) )
2017-06-15 01:51:48 +04:00
for name in os . listdir ( basedir )
if path . isdir ( path . join ( basedir , name ) ) ] )
if o . dirspecs is not None :
2017-06-15 23:20:38 +04:00
for pd in o . dirspecs :
p , d = split_nvalue ( pd )
if p is None : prefix = ' '
else : prefix = p + ' = '
dirspec = path . expanduser ( d )
nvss . extend ( [ prefix + path . abspath ( dir )
2017-06-15 01:51:48 +04:00
for dir in glob ( dirspec )
if path . isdir ( dir ) ] )
nvss . extend ( o . nvss )
# préparer la mise à jour du groupe courant
2017-06-16 07:36:13 +04:00
self . reset_group_maybe ( otype )
self . attr_otype = otype
defaulto = self . db . get_object ( otype , None )
2017-06-15 01:51:48 +04:00
# traiter les hôtes
for nvs in nvss :
2017-06-15 23:20:38 +04:00
name , values = split_nlist ( nvs )
2017-06-18 08:53:34 +04:00
for value in values :
2017-06-15 02:24:17 +04:00
dir = None
2017-06-18 08:53:34 +04:00
if value :
if ' / ' in value :
dir , value = path . split ( path . abspath ( path . expanduser ( value ) ) )
value = self . __fix_host ( value )
2017-06-15 01:51:48 +04:00
if name :
2017-06-16 07:36:13 +04:00
o = self . db . get_object ( otype , name )
2017-06-18 08:53:34 +04:00
if value : o . add_value ( value )
2017-06-16 00:36:36 +04:00
o . merge_attrs ( defaulto )
2017-06-15 23:20:38 +04:00
if dir is not None : o . set_attr ( ' dir ' , dir )
2017-06-16 07:36:13 +04:00
self . add_group ( otype , name )
2017-06-15 01:51:48 +04:00
else :
2017-06-18 08:53:34 +04:00
id = HostObject . genid ( value )
2017-06-16 07:36:13 +04:00
o = self . db . get_object ( otype , id )
2017-06-18 08:53:34 +04:00
o . add_value ( value )
2017-06-16 00:36:36 +04:00
o . merge_attrs ( defaulto )
2017-06-15 23:20:38 +04:00
if dir is not None : o . set_attr ( ' dir ' , dir )
2017-06-16 07:36:13 +04:00
self . add_group ( otype , id )
2017-06-15 21:11:58 +04:00
ib = HostObject . genib ( id )
2017-06-16 07:36:13 +04:00
o = self . db . get_object ( otype , ib )
2017-06-18 08:53:34 +04:00
o . add_value ( value )
2017-06-16 00:36:36 +04:00
o . merge_attrs ( defaulto )
2017-06-15 23:20:38 +04:00
if dir is not None : o . set_attr ( ' dir ' , dir )
2017-06-16 07:36:13 +04:00
self . add_group ( otype , ib )
2017-06-15 01:51:48 +04:00
2017-06-15 23:20:38 +04:00
############################################################################
def __setup_uinst ( self ) :
self . db . register_object ( ' module ' , ModuleObject )
2017-06-16 00:36:36 +04:00
self . db . register_link ( ' uinst ' , UinstLink )
self . db . register_link ( ' ruinst ' , RuinstLink )
2017-06-15 23:20:38 +04:00
self . db . get_object ( ' module ' , None )
self . groups [ ' module ' ] = { }
2017-07-18 17:33:32 +04:00
self . handle_group ( ' group ' , ' module ' , ' defaults ' )
2017-06-15 23:20:38 +04:00
self . register_command ( ' module ' , self . handle_module )
self . register_command ( ' uinst ' , self . handle_xuinst )
self . register_command ( ' ruinst ' , self . handle_xuinst )
def __fix_module ( self , module ) :
return module
2017-06-16 07:36:13 +04:00
def handle_module ( self , otype , * args ) :
2017-06-15 23:20:38 +04:00
""" module [id=]path/to/module
module - b [ id = ] basedir
module - d [ id = ] dirspec
"""
AP = ArgumentParser ( )
AP . add_argument ( ' -b ' , ' --basedir ' , action = ' append ' , dest = ' basedirs ' )
AP . add_argument ( ' -d ' , ' --dirspec ' , action = ' append ' , dest = ' dirspecs ' )
AP . add_argument ( ' nvss ' , nargs = REMAINDER )
o = AP . parse_args ( args )
# construire la liste des modules à traiter
nvss = [ ]
if o . basedirs is not None :
for pb in o . basedirs :
p , b = split_nvalue ( pb )
if p is None : prefix = ' '
else : prefix = p + ' = '
basedir = path . expanduser ( b )
nvss . extend ( [ prefix + path . abspath ( path . join ( basedir , name ) )
for name in os . listdir ( basedir )
if path . isdir ( path . join ( basedir , name ) ) ] )
if o . dirspecs is not None :
for pd in o . dirspecs :
p , d = split_nvalue ( pd )
if p is None : prefix = ' '
else : prefix = p + ' = '
dirspec = path . expanduser ( d )
nvss . extend ( [ prefix + path . abspath ( dir )
for dir in glob ( dirspec )
if path . isdir ( dir ) ] )
nvss . extend ( o . nvss )
# préparer la mise à jour du groupe courant
2017-06-16 07:36:13 +04:00
self . reset_group_maybe ( otype )
self . attr_otype = otype
defaulto = self . db . get_object ( otype , None )
2017-06-15 23:20:38 +04:00
# traiter les modules
for nvs in nvss :
name , values = split_nlist ( nvs )
2017-06-18 08:53:34 +04:00
for value in values :
2017-06-15 23:20:38 +04:00
dir = None
2017-06-18 08:53:34 +04:00
valuep = None
if value :
if ' / ' in value :
dir , value = path . split ( path . abspath ( path . expanduser ( value ) ) )
value = self . __fix_module ( value )
2017-06-15 23:20:38 +04:00
if dir is not None :
2017-06-18 08:53:34 +04:00
valuep = path . join ( dir , value )
2017-06-15 23:20:38 +04:00
if name :
2017-06-16 07:36:13 +04:00
o = self . db . get_object ( otype , name )
2017-06-18 08:53:34 +04:00
if value : o . add_value ( value )
2017-06-16 00:36:36 +04:00
o . merge_attrs ( defaulto )
2017-06-15 23:20:38 +04:00
if dir is not None : o . set_attr ( ' dir ' , dir )
2017-06-18 08:53:34 +04:00
if valuep is not None : o . set_attr ( ' path ' , valuep )
2017-06-16 07:36:13 +04:00
self . add_group ( otype , name )
2017-06-15 23:20:38 +04:00
else :
2017-06-18 08:53:34 +04:00
id = ModuleObject . genid ( value )
2017-06-16 07:36:13 +04:00
o = self . db . get_object ( otype , id )
2017-06-18 08:53:34 +04:00
if value : o . add_value ( value )
2017-06-16 00:36:36 +04:00
o . merge_attrs ( defaulto )
2017-06-15 23:20:38 +04:00
if dir is not None : o . set_attr ( ' dir ' , dir )
2017-06-18 08:53:34 +04:00
if valuep is not None : o . set_attr ( ' path ' , valuep )
2017-06-16 07:36:13 +04:00
self . add_group ( otype , id )
2017-06-15 23:20:38 +04:00
2017-06-16 00:36:36 +04:00
def handle_xuinst ( self , ltype , * args ) :
""" uinst -p profile attrs*
ruinst - p profile attrs *
2017-07-18 17:33:32 +04:00
usage de l ' option -p:
pas d ' option -p
définir les liens dans le profil par défaut . équivalent à - p ' ' s ' il
n ' y a pas de profil par défaut.
- p ' '
définir les liens en ne les associant à aucun profil
- p PROFILE , . . .
définir les liens dans les profils spécifiés
2017-06-16 00:36:36 +04:00
"""
AP = ArgumentParser ( )
AP . add_argument ( ' -p ' , ' --profile ' , action = ' append ' , dest = ' profiles ' )
AP . add_argument ( ' nvss ' , nargs = REMAINDER )
o = AP . parse_args ( args )
2017-07-18 17:33:32 +04:00
if o . profiles is None : profiles = [ self . db . default_profile ]
else : profiles = flatten ( o . profiles )
if profiles == [ ] : profiles = [ None ]
2017-06-16 00:36:36 +04:00
for profile in profiles :
# préparer la mise à jour du groupe courant
2017-06-18 11:57:38 +04:00
currentls = self . db . get_links ( ltype , profile , fo = self . groups [ ' module ' ] [ ' current ' ] , create = True )
2017-06-16 00:36:36 +04:00
if profile is not None :
2017-06-18 11:57:38 +04:00
globalls = self . db . get_links ( ltype , None , fo = None , create = True )
2017-06-16 00:36:36 +04:00
for currentl in currentls :
2017-06-18 11:57:38 +04:00
for globall in globalls :
currentl . merge_attrs ( globall )
defaultls = self . db . get_links ( ltype , profile , fo = None , create = True )
2017-06-16 00:36:36 +04:00
for currentl in currentls :
2017-06-18 11:57:38 +04:00
for defaultl in defaultls :
currentl . merge_attrs ( defaultl )
defaultl = defaultls [ 0 ]
2017-06-16 00:36:36 +04:00
# traiter les liens
2017-06-18 21:59:38 +04:00
for nvs in o . nvss :
2017-06-18 11:57:38 +04:00
name , value , type , method = split_namev ( nvs )
2017-06-16 00:36:36 +04:00
if name == defaultl . ttype :
# définir des destinations du lien
2017-06-18 11:57:38 +04:00
if value is not None :
tos = split_nlist ( nvs ) [ 1 ]
for to in tos :
for currentl in currentls :
currentl . add_to ( to )
2017-06-16 00:36:36 +04:00
else :
# définir un attribut du lien
2017-06-18 11:57:38 +04:00
#name, value, type, method = split_namev(nv)
2017-06-16 00:36:36 +04:00
if value is None :
method = ' set '
value = ' 1 '
elif type == ' path ' :
value = path . expanduser ( value )
2017-06-18 11:57:38 +04:00
for currentl in currentls :
currentl . modify_attr ( name , value , method )
2017-06-15 23:20:38 +04:00
############################################################################
def __setup_woinst ( self ) :
self . db . register_object ( ' wobundle ' , WobundleObject )
2017-06-18 21:59:38 +04:00
self . db . register_link ( ' rwoinst-bundle ' , RwoinstBundleLink )
self . db . register_link ( ' rwoinst-webres ' , RwoinstWebresLink )
2017-06-15 23:20:38 +04:00
self . db . get_object ( ' wobundle ' , None )
self . groups [ ' wobundle ' ] = { }
2017-07-18 17:33:32 +04:00
self . handle_group ( ' group ' , ' wobundle ' , ' defaults ' )
2017-06-15 23:20:38 +04:00
self . register_command ( ' wobundle ' , self . handle_wobundle )
self . register_command ( ' rwoinst ' , self . handle_rwoinst )
def __fix_wobundle ( self , wobundle ) :
if path . splitext ( wobundle ) [ 1 ] not in ( ' .woa ' , ' .framework ' ) :
wobundle = wobundle + ' .woa '
return wobundle
2017-06-16 07:36:13 +04:00
def handle_wobundle ( self , otype , * args ) :
2017-06-15 23:20:38 +04:00
""" wobundle [id=]path/to/wobundle
wobundle - b [ id = ] basedir
wobundle - d [ id = ] dirspec
"""
AP = ArgumentParser ( )
AP . add_argument ( ' -b ' , ' --basedir ' , action = ' append ' , dest = ' basedirs ' )
AP . add_argument ( ' -d ' , ' --dirspec ' , action = ' append ' , dest = ' dirspecs ' )
AP . add_argument ( ' nvss ' , nargs = REMAINDER )
o = AP . parse_args ( args )
# construire la liste des wobundles à traiter
nvss = [ ]
if o . basedirs is not None :
for pb in o . basedirs :
p , b = split_nvalue ( pb )
if p is None : prefix = ' '
else : prefix = p + ' = '
basedir = path . expanduser ( b )
nvss . extend ( [ prefix + path . abspath ( path . join ( basedir , name ) )
for name in os . listdir ( basedir )
if path . isdir ( path . join ( basedir , name ) ) and path . splitext ( name ) [ 1 ] in ( ' .woa ' , ' .framework ' ) ] )
if o . dirspecs is not None :
for pd in o . dirspecs :
p , d = split_nvalue ( pd )
if p is None : prefix = ' '
else : prefix = p + ' = '
dirspec = path . expanduser ( d )
nvss . extend ( [ prefix + path . abspath ( dir )
for dir in glob ( dirspec )
if path . isdir ( dir ) and path . splitext ( dir ) [ 1 ] in ( ' .woa ' , ' .framework ' ) ] )
nvss . extend ( o . nvss )
# préparer la mise à jour du groupe courant
2017-06-16 07:36:13 +04:00
self . reset_group_maybe ( otype )
self . attr_otype = otype
defaulto = self . db . get_object ( otype , None )
2017-06-15 23:20:38 +04:00
# traiter les wobundles
for nvs in nvss :
name , values = split_nlist ( nvs )
2017-06-18 08:53:34 +04:00
for value in values :
2017-06-15 23:20:38 +04:00
dir = None
2017-06-18 08:53:34 +04:00
valuep = None
if value :
if ' / ' in value :
dir , value = path . split ( path . abspath ( path . expanduser ( value ) ) )
value = self . __fix_wobundle ( value )
2017-06-15 23:20:38 +04:00
if dir is not None :
2017-06-18 08:53:34 +04:00
valuep = path . join ( dir , value )
2017-06-15 23:20:38 +04:00
if name :
2017-06-16 07:36:13 +04:00
o = self . db . get_object ( otype , name )
2017-06-18 08:53:34 +04:00
if value : o . add_value ( value )
2017-06-16 00:36:36 +04:00
o . merge_attrs ( defaulto )
2017-06-15 23:20:38 +04:00
if dir is not None : o . set_attr ( ' dir ' , dir )
2017-06-18 08:53:34 +04:00
if valuep is not None : o . set_attr ( ' path ' , valuep )
2017-06-16 07:36:13 +04:00
self . add_group ( otype , name )
2017-06-15 23:20:38 +04:00
else :
2017-06-18 08:53:34 +04:00
id = WobundleObject . genid ( value )
2017-06-16 07:36:13 +04:00
o = self . db . get_object ( otype , id )
2017-06-18 08:53:34 +04:00
if value : o . add_value ( value )
2017-06-16 00:36:36 +04:00
o . merge_attrs ( defaulto )
2017-06-15 23:20:38 +04:00
if dir is not None : o . set_attr ( ' dir ' , dir )
2017-06-18 08:53:34 +04:00
if valuep is not None : o . set_attr ( ' path ' , valuep )
2017-06-16 07:36:13 +04:00
self . add_group ( otype , id )
2017-06-15 23:20:38 +04:00
2017-06-18 21:59:38 +04:00
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 )
2017-07-18 17:33:32 +04:00
if o . profiles is None : profiles = [ self . db . default_profile ]
else : profiles = flatten ( o . profiles )
if profiles == [ ] : profiles = [ None ]
2017-06-18 21:59:38 +04:00
ltype = " %s - %s " % ( ltype , o . stype [ 0 ] )
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 )
2017-06-15 23:20:38 +04:00
############################################################################
def __setup_toinst ( self ) :
self . db . register_object ( ' webapp ' , WebappObject )
2017-06-18 21:59:38 +04:00
self . db . register_link ( ' rtoinst ' , RtoinstLink )
2017-06-15 23:20:38 +04:00
self . db . get_object ( ' webapp ' , None )
self . groups [ ' webapp ' ] = { }
2017-07-18 17:33:32 +04:00
self . handle_group ( ' group ' , ' webapp ' , ' defaults ' )
2017-06-15 23:20:38 +04:00
self . register_command ( ' webapp ' , self . handle_webapp )
self . register_command ( ' rtoinst ' , self . handle_rtoinst )
def __fix_webapp ( self , webapp ) :
return webapp
2017-06-16 07:36:13 +04:00
def handle_webapp ( self , otype , * args ) :
2017-06-15 23:20:38 +04:00
""" webapp [id=]path/to/webapp
webapp - b [ id = ] basedir
webapp - d [ id = ] dirspec
"""
AP = ArgumentParser ( )
AP . add_argument ( ' -b ' , ' --basedir ' , action = ' append ' , dest = ' basedirs ' )
AP . add_argument ( ' -d ' , ' --dirspec ' , action = ' append ' , dest = ' dirspecs ' )
AP . add_argument ( ' nvss ' , nargs = REMAINDER )
o = AP . parse_args ( args )
# construire la liste des webapps à traiter
nvss = [ ]
if o . basedirs is not None :
for pb in o . basedirs :
p , b = split_nvalue ( pb )
if p is None : prefix = ' '
else : prefix = p + ' = '
basedir = path . expanduser ( b )
nvss . extend ( [ prefix + path . abspath ( path . join ( basedir , name ) )
for name in os . listdir ( basedir )
if path . isdir ( path . join ( basedir , name ) ) ] )
if o . dirspecs is not None :
for pd in o . dirspecs :
p , d = split_nvalue ( pd )
if p is None : prefix = ' '
else : prefix = p + ' = '
dirspec = path . expanduser ( d )
nvss . extend ( [ prefix + path . abspath ( dir )
for dir in glob ( dirspec )
if path . isdir ( dir ) ] )
nvss . extend ( o . nvss )
# préparer la mise à jour du groupe courant
2017-06-16 07:36:13 +04:00
self . reset_group_maybe ( otype )
self . attr_otype = otype
defaulto = self . db . get_object ( otype , None )
2017-06-15 23:20:38 +04:00
# traiter les webapps
for nvs in nvss :
name , values = split_nlist ( nvs )
2017-06-18 08:53:34 +04:00
for value in values :
2017-06-15 23:20:38 +04:00
dir = None
2017-06-18 08:53:34 +04:00
valuep = None
if value :
if ' / ' in value :
dir , value = path . split ( path . abspath ( path . expanduser ( value ) ) )
value = self . __fix_webapp ( value )
2017-06-15 23:20:38 +04:00
if dir is not None :
2017-06-18 08:53:34 +04:00
valuep = path . join ( dir , value )
2017-06-15 23:20:38 +04:00
if name :
2017-06-16 07:36:13 +04:00
o = self . db . get_object ( otype , name )
2017-06-18 08:53:34 +04:00
if value : o . add_value ( value )
2017-06-16 00:36:36 +04:00
o . merge_attrs ( defaulto )
2017-06-15 23:20:38 +04:00
if dir is not None : o . set_attr ( ' dir ' , dir )
2017-06-18 08:53:34 +04:00
if valuep is not None : o . set_attr ( ' path ' , valuep )
2017-06-16 07:36:13 +04:00
self . add_group ( otype , name )
2017-06-15 23:20:38 +04:00
else :
2017-06-18 08:53:34 +04:00
id = WebappObject . genid ( value )
2017-06-16 07:36:13 +04:00
o = self . db . get_object ( otype , id )
2017-06-18 08:53:34 +04:00
if value : o . add_value ( value )
2017-06-16 00:36:36 +04:00
o . merge_attrs ( defaulto )
2017-06-15 23:20:38 +04:00
if dir is not None : o . set_attr ( ' dir ' , dir )
2017-06-18 08:53:34 +04:00
if valuep is not None : o . set_attr ( ' path ' , valuep )
2017-06-16 07:36:13 +04:00
self . add_group ( otype , id )
2017-06-15 23:20:38 +04:00
2017-06-18 21:59:38 +04:00
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 )
2017-07-18 17:33:32 +04:00
if o . profiles is None : profiles = [ self . db . default_profile ]
else : profiles = flatten ( o . profiles )
if profiles == [ ] : profiles = [ None ]
2017-06-18 21:59:38 +04:00
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 )
2017-06-15 23:20:38 +04:00
2017-07-18 17:33:32 +04:00
############################################################################
def __setup_query ( self ) :
self . register_command ( ' query ' , self . handle_query )
def handle_query ( self , cmd , * args ) :
""" query config
"""
print " WARNING: query not implemented " #XXX
2017-06-15 23:20:38 +04:00
################################################################################
# Programme principal
2017-07-18 20:04:02 +04:00
VALID_QUERY_TYPES = ( ' object ' , ' source ' , ' dest ' , ' link ' )
def __fix_query_type ( query_type ) :
if query_type is None : return None
query_type = query_type . lower ( )
if query_type == ' o ' : query_type = ' object '
elif query_type == ' s ' : query_type = ' source '
elif query_type == ' d ' : query_type = ' dest '
elif query_type == ' l ' : query_type = ' link '
if query_type not in VALID_QUERY_TYPES :
raise ValuerError ( " %s : invalid query type " )
return query_type
def __resolve_format ( o , query_type ) :
format = o . format or ' shell '
ovars , lvars = o . object_vars , o . link_vars
if not ovars and not lvars :
if query_type == ' object ' :
ovars = True
lvars = False
elif query_type in ( ' source ' , ' dest ' ) :
ovars = True
lvars = True
elif query_type == ' link ' :
ovars = False
lvars = True
ofunc , lfunc = o . object_func , o . link_func
ivars = flatten ( o . vars ) or None
return format , ovars , lvars , ofunc , lfunc , ivars
def print_var ( name , values , format , ivars , is_values = False ) :
if ivars is not None and name not in ivars : return
if not isseq ( values ) : values = [ values ]
if format == ' shell ' :
params = ( name , " " . join ( qshell ( values ) ) )
if len ( values ) < = 1 : print " %s = %s " % params
else : print " %s =( %s ) " % params
return
if not is_values : return
if format == ' lines ' :
for value in values :
print value
elif format == ' spaces ' :
print " " . join ( values )
elif format == ' path ' :
print " : " . join ( values )
elif format == ' comma ' :
print " , " . join ( values )
else :
raise ValueError ( " %s : invalid format " % format )
def print_objects ( objects , query_type , o ) :
if objects is None : return
format , ovars , lvars , ofunc , lfunc , ivars = __resolve_format ( o , query_type )
if not ovars : return
for o in objects :
if o . is_defaults ( ) : continue
print_var ( ' otype ' , o . OTYPE , format , ivars )
print_var ( o . VALUESNAME , o . values , format , ivars , True )
for name , values in o . attrs . items ( ) :
print_var ( ' %s %s ' % ( o . ATTRPREFIX , name ) , values , format , ivars )
if ofunc and format == ' shell ' :
print ofunc
2017-06-15 01:51:48 +04:00
def run_qdd ( o ) :
# fichier de configuration
confname = o . confname or ' deploy '
if ' / ' in confname :
conf = path . abspath ( confname )
elif path . exists ( ' %s .conf ' % confname ) :
conf = ' %s .conf ' % confname
else :
conf = confname
if not conf . endswith ( ' .conf ' ) : conf = ' %s .conf ' % conf
user_conf = path . join ( path . expanduser ( USER_CONFDIR ) , conf )
system_conf = path . join ( SYSTEM_CONFDIR , conf )
if path . exists ( user_conf ) : conf = user_conf
elif path . exists ( system_conf ) : conf = system_conf
lexer = Lexer ( conf )
2017-06-15 21:11:58 +04:00
db = Database ( )
2017-06-15 01:51:48 +04:00
if o . action == ' nop ' :
pass
2017-07-18 20:04:02 +04:00
elif o . action == ' dump ' :
2017-06-15 21:11:58 +04:00
predicates = lexer . get_predicates ( )
parser = Parser ( db ) . parse ( predicates )
2017-06-15 01:51:48 +04:00
print " === predicates "
2017-06-15 21:11:58 +04:00
for p in predicates :
2017-06-15 01:51:48 +04:00
print ' ' . join ( map ( repr , p ) )
2017-06-18 21:59:38 +04:00
otypes = db . known_otypes [ : ]
2017-06-15 23:20:38 +04:00
otypes . remove ( ' host ' )
otypes . insert ( 0 , ' host ' )
for otype in otypes :
objects = db . get_objects ( otype )
if objects :
print " === %s " % otype
for o in objects :
o . dump ( )
2017-06-18 21:59:38 +04:00
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 ( " " )
2017-06-15 23:20:38 +04:00
2017-06-15 01:51:48 +04:00
elif o . action == ' query ' :
2017-06-15 21:11:58 +04:00
parser = Parser ( db ) . parse ( lexer . get_predicates ( ) )
2017-07-18 20:04:02 +04:00
query_type , object_type , link_type = __fix_query_type ( o . query_type ) , o . object_type , o . link_type
if query_type is None and object_type is None and link_type is None :
query_type = ' dest '
object_type = ' host '
if o . profile is not None : profile = o . profile or None
else : profile = UNDEF
args = o . args or UNDEF
if query_type == ' object ' :
objects = db . get_objects ( object_type , args )
print_objects ( objects , query_type , o )
elif query_type == ' source ' :
pass
elif query_type == ' dest ' :
pass
elif query_type == ' link ' :
pass
2017-06-15 01:51:48 +04:00
if __name__ == ' __main__ ' :
from argparse import ArgumentParser , HelpFormatter
if sys . argv [ 1 : 2 ] == [ ' --compat ' ] :
# Avec l'argument --compat, désactiver la classe FancyHelpFormatter qui
# se base sur une API non documentée
sys . argv = sys . argv [ 0 : 1 ] + sys . argv [ 2 : ]
FancyHelpFormatter = HelpFormatter
else :
class FancyHelpFormatter ( HelpFormatter ) :
""" Comme HelpFormatter, mais ne touche pas aux lignes qui commencent par les
caractères ' >>> ' . Cela permet de mixer du texte formaté et du texte non
formaté .
"""
def _fill_text ( self , text , width , indent ) :
return ' ' . join ( [ indent + line for line in text . splitlines ( True ) ] )
def _split_lines ( self , text , width ) :
lines = [ ' ' ]
for line in text . splitlines ( ) :
if line . startswith ( ' >>> ' ) :
lines . append ( line )
lines . append ( ' ' )
else :
lines [ - 1 ] + = ' \n ' + line
lines = filter ( None , lines )
texts = [ ]
for line in lines :
if line . startswith ( ' >>> ' ) :
line = line [ 3 : ]
if line : texts . append ( line )
else :
texts . extend ( super ( FancyHelpFormatter , self ) . _split_lines ( line , width ) )
return texts
AP = ArgumentParser (
usage = u " %(prog)s --query FILTER " ,
description = __doc__ ,
formatter_class = FancyHelpFormatter ,
)
AP . set_defaults ( action = ' query ' )
AP . add_argument ( ' -Q ' , ' --query-action ' , action = ' store_const ' , dest = ' action ' , const = ' query ' ,
help = u " Interroger la base de données. C ' est l ' option par défaut " )
AP . add_argument ( ' -N ' , ' --nop-action ' , action = ' store_const ' , dest = ' action ' , const = ' nop ' ,
help = u " Ne rien faire. Utile pour vérifier si le fichier ne contient pas d ' erreur de syntaxe. " )
AP . add_argument ( ' -P ' , ' --dump-action ' , action = ' store_const ' , dest = ' action ' , const = ' dump ' ,
help = u " Afficher le contenu de la base de données. " )
AP . add_argument ( ' -c ' , ' --config ' , dest = ' confname ' ,
help = u " Spécifier le nom de la configuration à utiliser. Par défaut, utiliser le nom générique deploy. " )
AP . add_argument ( ' -q ' , ' --query-type ' , dest = ' query_type ' ,
2017-07-18 20:04:02 +04:00
help = u " Spécifier le type d ' information à afficher: \n "
+ u " >>> \n "
+ u " * object pour des informations sur les objets, \n "
+ u " >>> \n "
+ u " * source pour des informations sur les objets sources d ' un lien, \n "
+ u " >>> \n "
+ u " * dest pour des informations sur les objets destinations d ' un lien, \n "
+ u " >>> \n "
+ u " * link pour des informations sur un lien. \n "
+ u " >>> \n "
+ u " La valeur par défaut est ' -q dest -j host ' " )
2017-06-15 01:51:48 +04:00
AP . add_argument ( ' -j ' , ' --object-type ' , dest = ' object_type ' ,
2017-07-18 20:04:02 +04:00
help = u " Spécifier le type d ' objet à chercher pour -q object|source|dest " )
2017-06-15 01:51:48 +04:00
AP . add_argument ( ' -t ' , ' --link-type ' , dest = ' link_type ' ,
2017-07-18 20:04:02 +04:00
help = u " Spécifier le type de lien à chercher pour -q source|dest|link " )
2017-06-15 01:51:48 +04:00
AP . add_argument ( ' -p ' , ' --profile ' , dest = ' profile ' ,
2017-07-18 20:04:02 +04:00
help = u " Spécifier le profil de déploiement pour -q source|dest|link. Utiliser une valeur vide pour ne sélectionner que les liens sans profils. Ne pas spécifier l ' option pour afficher tous les profils définis. " )
2017-06-15 01:51:48 +04:00
AP . add_argument ( ' -F ' , ' --format ' , dest = ' format ' ,
2017-07-18 20:04:02 +04:00
help = u " Spécifier le format pour la sortie. La valeur par défaut est shell. \n "
+ u " >>> \n "
+ u " * shell affiche les définitions de variables \n "
+ u " >>> \n "
+ u " * lines affiches les valeurs à raison d ' une par lignes. les attributs ne sont pas affichés. \n "
+ u " >>> \n "
+ u " * spaces, path et comma affichent les valeurs séparées respectivement par un espace ' ' , deux point ' : ' et une virgule ' , ' . les attributs ne sont pas affichés. \n " )
AP . add_argument ( ' -v ' , ' --include-vars ' , action = ' append ' , dest = ' vars ' , metavar = ' VARS... ' ,
2017-06-15 01:51:48 +04:00
help = u " Spécifier les variables qui doivent être affichées. Par défaut, toutes les variables sont affichées. " )
AP . add_argument ( ' -o ' , ' --object-vars ' , action = ' store_true ' , dest = ' object_vars ' ,
2017-07-18 20:04:02 +04:00
help = u " Afficher uniquement les variables associées aux objets. " )
2017-06-15 01:51:48 +04:00
AP . add_argument ( ' -l ' , ' --link-vars ' , action = ' store_true ' , dest = ' link_vars ' ,
2017-07-18 20:04:02 +04:00
help = u " Afficher uniquement les variables associées aux liens. " )
2017-06-15 01:51:48 +04:00
AP . add_argument ( ' --of ' , ' --object-func ' , dest = ' object_func ' , metavar = ' FUNC ' ,
help = u " Avec le format shell, spécifier le nom d ' une fonction à afficher après les variables associées aux objets. " )
AP . add_argument ( ' --lf ' , ' --link-func ' , dest = ' link_func ' , metavar = ' FUNC ' ,
help = u " Avec le format shell, spécifier le nom d ' une fonction à afficher après les variables associées aux liens. " )
2017-07-18 20:04:02 +04:00
AP . add_argument ( ' args ' , nargs = REMAINDER )
2017-06-15 01:51:48 +04:00
o = AP . parse_args ( )
run_qdd ( o )