On utilise un champ ldap_name pour savoir quelle classe doit être utilisée pour instancier quel objet/attribut LDAP.
Et comme ça on fiche à la poubelle le dégueulasse globals() et on décorrelle les noms des classes des noms LDAP.
This commit is contained in:
parent
294f7ce949
commit
c392a2a986
3 changed files with 391 additions and 170 deletions
219
attributs.py
219
attributs.py
|
@ -37,6 +37,10 @@ import re
|
|||
import sys
|
||||
import netaddr
|
||||
import time
|
||||
import functools
|
||||
import smtplib
|
||||
import random
|
||||
import string
|
||||
from unicodedata import normalize
|
||||
from crans_utils import format_tel, format_mac, mailexist, validate_name, ip4_of_rid, ip6_of_mac
|
||||
|
||||
|
@ -44,48 +48,67 @@ sys.path.append("/usr/scripts/gestion")
|
|||
import config
|
||||
import config.impression
|
||||
import annuaires_pg
|
||||
import smtplib
|
||||
import random
|
||||
import string
|
||||
|
||||
### SMTP
|
||||
#: Serveur SMTP
|
||||
smtpserv = "smtp.crans.org"
|
||||
|
||||
### Les droits
|
||||
# en cas de typo, l'appel d'une variable plante, on préfèrera donc les utiliser en lieu et place
|
||||
# des chaînes de caractères
|
||||
#: Chaine de caractère des droits nounou
|
||||
nounou = u"Nounou"
|
||||
#: Droit cableur
|
||||
cableur = u"Cableur"
|
||||
#: Droit apprenti
|
||||
apprenti = u"Apprenti"
|
||||
#: Droit trésorier
|
||||
tresorier = u"Tresorier"
|
||||
#: Droit bureau
|
||||
bureau = u"Bureau"
|
||||
#: Droit imprimeur
|
||||
imprimeur = u"Imprimeur"
|
||||
#: Droit modérateur
|
||||
moderateur = u"Moderateur"
|
||||
#: Droit multimachine
|
||||
multimachines = u"Multimachines"
|
||||
#: Droit Webmaster
|
||||
webmaster = u"Webmaster"
|
||||
#: Droit Webradio
|
||||
webradio = u"Webradio"
|
||||
#: On peut faire subir des choses à un objet si on est son parent
|
||||
parent = u"parent"
|
||||
#: On peut faire subir des choses à un objet si on est cet objet
|
||||
soi = u"soi"
|
||||
#: Le responsable d'un club peut lui faire subir des choses
|
||||
respo = u"responsable"
|
||||
|
||||
#: Liste de tous les droits
|
||||
TOUS_DROITS = [nounou, apprenti, bureau, tresorier, imprimeur, moderateur, multimachines, cableur, webmaster]
|
||||
#: Liste des droits forts
|
||||
DROITS_ELEVES = [nounou, bureau]
|
||||
#: Liste des droits intérmédiaires
|
||||
DROITS_MOYEN = [apprenti, moderateur]
|
||||
#: Liste des droits moins sensibles
|
||||
DROITS_FAIBLES = [cableur, imprimeur, multimachines]
|
||||
|
||||
#: Qui a le droit de modifier quels droits
|
||||
DROITS_SUPERVISEUR = { nounou : TOUS_DROITS,
|
||||
bureau : DROITS_FAIBLES + [bureau, tresorier],
|
||||
}
|
||||
|
||||
class SingleValueError(ValueError):
|
||||
"""Erreur levée si on essaye de multivaluer un champ monovalué."""
|
||||
pass
|
||||
|
||||
class UniquenessError(EnvironmentError):
|
||||
"""Erreur levée si on essaye de créer un objet dont le ``dn`` existe déjà."""
|
||||
pass
|
||||
|
||||
class OptionalError(EnvironmentError):
|
||||
"""Erreur levée si on essaye de créer un objet sans fournir un attribut obligatoire."""
|
||||
pass
|
||||
|
||||
|
||||
def attrify(val, attr, conn, Parent=None):
|
||||
"""Transforme un n'importe quoi en :py:class:`Attr`.
|
||||
|
||||
|
@ -98,7 +121,7 @@ def attrify(val, attr, conn, Parent=None):
|
|||
else:
|
||||
if not isinstance(val, unicode):
|
||||
val = val.decode('utf-8')
|
||||
return CRANS_ATTRIBUTES.get(attr, Attr)(val, conn, Parent)
|
||||
return AttributeFactory.get(attr, fallback=Attr)(val, conn, Parent)
|
||||
|
||||
|
||||
class AttrsDict(dict):
|
||||
|
@ -123,8 +146,8 @@ class AttrsDict(dict):
|
|||
if not isinstance(values, list):
|
||||
values = [ values ]
|
||||
if self._parent.mode in ['w', 'rw']:
|
||||
if CRANS_ATTRIBUTES.get(attr, Attr).singlevalue and len(values) > 1:
|
||||
raise SingleValueError("L'attribut %s doit être monovalué." % CRANS_ATTRIBUTES.get(attr, Attr).__name__)
|
||||
if AttributeFactory.get(attr, fallback=Attr).singlevalue and len(values) > 1:
|
||||
raise SingleValueError("L'attribut %s doit être monovalué." % (attr,))
|
||||
super(AttrsDict, self).__setitem__(attr, values)
|
||||
else:
|
||||
super(AttrsDict, self).__setitem__(attr, values)
|
||||
|
@ -151,6 +174,8 @@ class Attr(object):
|
|||
optional = True
|
||||
conn = None
|
||||
unique = False
|
||||
#: Le nom de l'attribut dans le schéma LDAP
|
||||
ldap_name = None
|
||||
|
||||
"""La liste des droits qui suffisent à avoir le droit de modifier la valeur"""
|
||||
can_modify = [nounou]
|
||||
|
@ -205,10 +230,44 @@ class Attr(object):
|
|||
"""
|
||||
return not set(liste_droits).isdisjoint(self.can_modify)
|
||||
|
||||
|
||||
class AttributeFactory(object):
|
||||
"""Utilisée pour enregistrer toutes les classes servant à instancier un attribut LDAP.
|
||||
Elle sert à les récupérer à partir de leur nom LDAP.
|
||||
|
||||
Cette classe n'est jamais instanciée.
|
||||
|
||||
"""
|
||||
_classes = {}
|
||||
|
||||
@classmethod
|
||||
def register(cls, name, classe):
|
||||
"""Enregistre l'association ``name`` -> ``classe``"""
|
||||
cls._classes[name] = classe
|
||||
|
||||
@classmethod
|
||||
def get(cls, name, fallback=Attr):
|
||||
"""Retourne la classe qui a ``name`` pour ``ldap_name``.
|
||||
|
||||
Si elle n'existe pas, renvoie :py:class:`Attr` (peut être override en précisant ``fallback``)
|
||||
|
||||
"""
|
||||
return cls._classes.get(name, fallback)
|
||||
|
||||
def crans_attribute(classe):
|
||||
"""Pour décorer les classes permettant d'instancier des attributs LDAP,
|
||||
afin de les enregistrer dans :py:class:`AttributeFactory`.
|
||||
|
||||
"""
|
||||
AttributeFactory.register(classe.ldap_name, classe)
|
||||
return classe
|
||||
|
||||
@crans_attribute
|
||||
class objectClass(Attr):
|
||||
singlevalue = False
|
||||
optional = False
|
||||
legend = "entité"
|
||||
ldap_name = "objectClass"
|
||||
|
||||
""" Personne ne doit modifier de classe """
|
||||
can_modify = []
|
||||
|
@ -249,12 +308,14 @@ class boolAttr(Attr):
|
|||
def __unicode__(self):
|
||||
return unicode(self.value).upper()
|
||||
|
||||
@crans_attribute
|
||||
class aid(intAttr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
legend = u"Identifiant de l'adhérent"
|
||||
category = 'id'
|
||||
unique = True
|
||||
ldap_name = "aid"
|
||||
|
||||
""" Personne ne devrait modifier un attribut d'identification """
|
||||
can_modify = []
|
||||
|
@ -264,19 +325,23 @@ class aid(intAttr):
|
|||
def parse_value(self, aid):
|
||||
self.value = int(aid)
|
||||
|
||||
@crans_attribute
|
||||
class uid(Attr):
|
||||
singlevalue = True
|
||||
option = False
|
||||
legend = u"L'identifiant canonique de l'adhérent"
|
||||
category = 'perso'
|
||||
unique = True
|
||||
ldap_name = "uid"
|
||||
|
||||
@crans_attribute
|
||||
class nom(Attr):
|
||||
singlevalue = True
|
||||
optional = False
|
||||
legend = "Nom"
|
||||
category = 'perso'
|
||||
can_modify = [nounou, cableur]
|
||||
ldap_name = "nom"
|
||||
|
||||
def parse_value(self, nom):
|
||||
if self.parent != None:
|
||||
|
@ -287,33 +352,39 @@ class nom(Attr):
|
|||
else:
|
||||
self.value = validate_name(nom)
|
||||
|
||||
@crans_attribute
|
||||
class prenom(Attr):
|
||||
singlevalue = True
|
||||
optional = False
|
||||
legend = u"Prénom"
|
||||
category = 'perso'
|
||||
can_modify = [nounou, cableur]
|
||||
ldap_name = "prenom"
|
||||
|
||||
def parse_value(self, prenom):
|
||||
self.value = validate_name(prenom)
|
||||
|
||||
@crans_attribute
|
||||
class compteWiki(Attr):
|
||||
singlevalue = False
|
||||
optional = True
|
||||
legend = u"Compte WiKi"
|
||||
category = 'perso'
|
||||
can_modify = [nounou, cableur, soi]
|
||||
ldap_name = "compteWiki"
|
||||
|
||||
def parse_value(self, compte):
|
||||
self.value = validate_name(compte)
|
||||
# TODO: validate with mdp for user definition here ?
|
||||
|
||||
@crans_attribute
|
||||
class tel(Attr):
|
||||
singlevalue = True
|
||||
optional = False
|
||||
legend = u"Téléphone"
|
||||
category = 'perso'
|
||||
can_modify = [soi, nounou, cableur]
|
||||
ldap_name = "tel"
|
||||
|
||||
def parse_value(self, tel):
|
||||
self.value = format_tel(tel)
|
||||
|
@ -330,20 +401,27 @@ class yearAttr(intAttr):
|
|||
raise ValueError("Année invalide (%r)" % annee)
|
||||
self.value = annee
|
||||
|
||||
@crans_attribute
|
||||
class paiement(yearAttr):
|
||||
legend = u"Paiement"
|
||||
can_modify = [cableur, nounou, tresorier]
|
||||
category = 'perso'
|
||||
ldap_name = "paiement"
|
||||
|
||||
@crans_attribute
|
||||
class carteEtudiant(yearAttr):
|
||||
legend = u"Carte d'étudiant"
|
||||
category = 'perso'
|
||||
can_modify = [cableur, nounou, tresorier]
|
||||
ldap_name = "carteEtudiant"
|
||||
|
||||
@crans_attribute
|
||||
class derniereConnexion(intAttr):
|
||||
legend = u"Dernière connexion"
|
||||
can_modify = []
|
||||
ldap_name = "derniereConnexion"
|
||||
|
||||
@crans_attribute
|
||||
class mail(Attr):
|
||||
singlevalue = False
|
||||
optional = False
|
||||
|
@ -351,6 +429,7 @@ class mail(Attr):
|
|||
legend = "Le mail de l'adhérent"
|
||||
can_modify = [soi, nounou, cableur]
|
||||
category = 'mail'
|
||||
ldap_name = "mail"
|
||||
|
||||
def check_uniqueness(self, liste_exclue):
|
||||
attr = self.__class__.__name__
|
||||
|
@ -380,12 +459,14 @@ class mail(Attr):
|
|||
self.value = mail
|
||||
|
||||
|
||||
@crans_attribute
|
||||
class canonicalAlias(mail):
|
||||
singlevalue = True
|
||||
optional = False
|
||||
unique = True
|
||||
legend = u"Alias mail canonique"
|
||||
category = 'mail'
|
||||
ldap_name = "canonicalAlias"
|
||||
|
||||
def parse_value(self, mail):
|
||||
mail = u".".join([ a.capitalize() for a in mail.split(u'.', 1) ])
|
||||
|
@ -393,6 +474,7 @@ class canonicalAlias(mail):
|
|||
raise ValueError("Alias mail invalide (%s)" % mail)
|
||||
self.value = mail
|
||||
|
||||
@crans_attribute
|
||||
class mailAlias(mail):
|
||||
singlevalue = False
|
||||
optional = True
|
||||
|
@ -400,6 +482,7 @@ class mailAlias(mail):
|
|||
legend = u"Alias mail"
|
||||
can_modify = [soi, cableur, nounou]
|
||||
category = 'mail'
|
||||
ldap_name = "mailAlias"
|
||||
|
||||
def parse_value(self, mail):
|
||||
mail = mail.lower()
|
||||
|
@ -407,6 +490,7 @@ class mailAlias(mail):
|
|||
raise ValueError("Alias mail invalide (%r)" % mail)
|
||||
self.value = mail
|
||||
|
||||
@crans_attribute
|
||||
class mailExt(mail):
|
||||
singlevalue = False
|
||||
optional = True
|
||||
|
@ -414,6 +498,7 @@ class mailExt(mail):
|
|||
legend = u"Mail externe"
|
||||
can_modify = [soi, cableur, nounou]
|
||||
category = 'mail'
|
||||
ldap_name = "mailExt"
|
||||
|
||||
def parse_value(self, mail):
|
||||
mail = mail.lower()
|
||||
|
@ -421,31 +506,38 @@ class mailExt(mail):
|
|||
raise ValueError("Mail externe invalide (%r)" % mail)
|
||||
self.value = mail
|
||||
|
||||
@crans_attribute
|
||||
class mailInvalide(boolAttr):
|
||||
optional = True
|
||||
legend = u"Mail invalide"
|
||||
can_modify = [bureau, nounou]
|
||||
ldap_name = "mailInvalide"
|
||||
|
||||
@crans_attribute
|
||||
class contourneGreylist(boolAttr):
|
||||
optionnal = True
|
||||
legend = u"Contourner la greylist"
|
||||
category = 'mail'
|
||||
can_modify = [soi]
|
||||
ldap_name = "contourneGreylist"
|
||||
|
||||
def __unicode__(self):
|
||||
return u"OK"
|
||||
|
||||
@crans_attribute
|
||||
class etudes(Attr):
|
||||
singlevalue = False
|
||||
optional = True
|
||||
legend = u"Études"
|
||||
can_modify = [soi, cableur, nounou]
|
||||
category = 'perso'
|
||||
ldap_name = "etudes"
|
||||
|
||||
def parse_value(self, etudes):
|
||||
# who cares
|
||||
self.value = etudes
|
||||
|
||||
@crans_attribute
|
||||
class chbre(Attr):
|
||||
singlevalue = True
|
||||
optional = False
|
||||
|
@ -453,6 +545,7 @@ class chbre(Attr):
|
|||
legend = u"Chambre sur le campus"
|
||||
can_modify = [soi, cableur, nounou]
|
||||
category = 'perso'
|
||||
ldap_name = "chbre"
|
||||
|
||||
def parse_value(self, chambre):
|
||||
if self.parent != None:
|
||||
|
@ -475,12 +568,14 @@ class chbre(Attr):
|
|||
|
||||
self.value = chambre
|
||||
|
||||
@crans_attribute
|
||||
class droits(Attr):
|
||||
singlevalue = False
|
||||
optional = True
|
||||
legend = u"Droits sur les serveurs"
|
||||
can_modify = [nounou, bureau] #ne sert à rien ici, mais c'est tout à fait exceptionnel
|
||||
category = 'perso'
|
||||
ldap_name = "droits"
|
||||
|
||||
def parse_value(self, droits):
|
||||
# if val.lower() not in [i.lower() for i in TOUS_DROITS]:
|
||||
|
@ -498,11 +593,13 @@ class droits(Attr):
|
|||
|
||||
return self.value in modifiables
|
||||
|
||||
@crans_attribute
|
||||
class solde(Attr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
legend = u"Solde d'impression"
|
||||
can_modify = [imprimeur, nounou, tresorier]
|
||||
ldap_name = "solde"
|
||||
|
||||
def parse_value(self, solde):
|
||||
# on évite les dépassements, sauf si on nous dit de ne pas vérifier
|
||||
|
@ -512,6 +609,7 @@ class solde(Attr):
|
|||
|
||||
class dnsAttr(Attr):
|
||||
category = 'dns'
|
||||
ldap_name = "dnsAttr"
|
||||
def parse_value(self, val):
|
||||
val = val.lower()
|
||||
names = val.split('.')
|
||||
|
@ -520,12 +618,14 @@ class dnsAttr(Attr):
|
|||
raise ValueError("Nom d'hote invalide %r" % val)
|
||||
self.value = val
|
||||
|
||||
@crans_attribute
|
||||
class host(dnsAttr):
|
||||
singlevalue = True
|
||||
optional = False
|
||||
hname = legend = u"Nom d'hôte"
|
||||
can_modify = [parent, nounou, cableur]
|
||||
category = 'base_tech'
|
||||
ldap_name = "host"
|
||||
|
||||
def check_uniqueness(self, liste_exclue):
|
||||
attr = self.__class__.__name__
|
||||
|
@ -536,14 +636,16 @@ class host(dnsAttr):
|
|||
if res:
|
||||
raise ValueError("Hôte déjà existant", [r.dn for r in res])
|
||||
|
||||
@crans_attribute
|
||||
class hostAlias(host):
|
||||
singlevalue = False
|
||||
unique = True
|
||||
optional = True
|
||||
legend = u'Alias de nom de machine'
|
||||
|
||||
can_modify = [nounou, cableur]
|
||||
ldap_name = "hostAlias"
|
||||
|
||||
@crans_attribute
|
||||
class macAddress(Attr):
|
||||
singlevalue = True
|
||||
optional = False
|
||||
|
@ -551,6 +653,7 @@ class macAddress(Attr):
|
|||
hname = "Adresse MAC"
|
||||
category = 'base_tech'
|
||||
can_modify = [parent, nounou, cableur]
|
||||
ldap_name = "macAddress"
|
||||
|
||||
def parse_value(self, mac):
|
||||
self.value = format_mac(mac)
|
||||
|
@ -559,6 +662,7 @@ class macAddress(Attr):
|
|||
def __unicode__(self):
|
||||
return unicode(self.value).lower()
|
||||
|
||||
@crans_attribute
|
||||
class ipHostNumber(Attr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
|
@ -567,6 +671,7 @@ class ipHostNumber(Attr):
|
|||
hname = "IPv4"
|
||||
category = 'base_tech'
|
||||
can_modify = [nounou]
|
||||
ldap_name = "ipHostNumber"
|
||||
|
||||
def parse_value(self, ip):
|
||||
if ip == '<automatique>':
|
||||
|
@ -576,6 +681,7 @@ class ipHostNumber(Attr):
|
|||
def __unicode__(self):
|
||||
return unicode(self.value)
|
||||
|
||||
@crans_attribute
|
||||
class ip6HostNumber(Attr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
|
@ -584,6 +690,7 @@ class ip6HostNumber(Attr):
|
|||
hname = "IPv6"
|
||||
category = 'base_tech'
|
||||
can_modify = [nounou]
|
||||
ldap_name = "ip6HostNumber"
|
||||
|
||||
def parse_value(self, ip6):
|
||||
ip = ip6_of_mac(str(self.parent['macAddress'][0]), int(str(self.parent['rid'][0])))
|
||||
|
@ -592,12 +699,14 @@ class ip6HostNumber(Attr):
|
|||
def __unicode__(self):
|
||||
return unicode(self.value)
|
||||
|
||||
@crans_attribute
|
||||
class mid(Attr):
|
||||
singlevalue = True
|
||||
optional = False
|
||||
unique = True
|
||||
legend = u"Identifiant de machine"
|
||||
category = 'id'
|
||||
ldap_name = "mid"
|
||||
|
||||
def parse_value(self, mid):
|
||||
self.value = int(mid)
|
||||
|
@ -605,6 +714,7 @@ class mid(Attr):
|
|||
def __unicode__(self):
|
||||
return unicode(self.value)
|
||||
|
||||
@crans_attribute
|
||||
class rid(Attr):
|
||||
singlevalue = True
|
||||
optional = False
|
||||
|
@ -612,6 +722,7 @@ class rid(Attr):
|
|||
legend = u"Identifiant réseau de machine"
|
||||
category = 'id'
|
||||
can_modify = [nounou]
|
||||
ldap_name = "rid"
|
||||
|
||||
def parse_value(self, rid):
|
||||
rid = int(rid)
|
||||
|
@ -635,11 +746,13 @@ class rid(Attr):
|
|||
def __unicode__(self):
|
||||
return unicode(self.value)
|
||||
|
||||
@crans_attribute
|
||||
class ipsec(Attr):
|
||||
singlevalue = False
|
||||
optional = True
|
||||
legend = u'Clef wifi'
|
||||
category = 'wifi'
|
||||
ldap_name = "ipsec"
|
||||
|
||||
def parse_value(self, val):
|
||||
if len(val) in [10, 22]:
|
||||
|
@ -649,41 +762,51 @@ class ipsec(Attr):
|
|||
if val == u"auto":
|
||||
self.value = u''.join( random.choice(filter(lambda x: x != 'l' and x != 'o', string.lowercase) + filter(lambda x: x != '1' and x != '0', string.digits)) for i in range(10))
|
||||
|
||||
@crans_attribute
|
||||
class puissance(Attr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
legend = u"puissance d'émission pour les bornes wifi"
|
||||
category = 'wifi'
|
||||
can_modify = [nounou]
|
||||
ldap_name = "puissance"
|
||||
|
||||
@crans_attribute
|
||||
class canal(intAttr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
legend = u'Canal d\'émission de la borne'
|
||||
category = 'wifi'
|
||||
can_modify = [nounou]
|
||||
ldap_name = "canal"
|
||||
|
||||
@crans_attribute
|
||||
class hotspot(boolAttr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
legend = u'Hotspot'
|
||||
category = 'wifi'
|
||||
can_modify = [nounou]
|
||||
ldap_name = "hotspot"
|
||||
|
||||
@crans_attribute
|
||||
class positionBorne(Attr):
|
||||
legend = u"Position de la borne"
|
||||
category = "wifi"
|
||||
can_modify = [nounou]
|
||||
singlevalue = True
|
||||
optional = True
|
||||
ldap_name = "positionBorne"
|
||||
|
||||
def parse_value(self, pos):
|
||||
self.value = unicode(pos)
|
||||
|
||||
@crans_attribute
|
||||
class nvram(Attr):
|
||||
legend = u"Configuration speciale"
|
||||
optional = True
|
||||
can_modify = [nounou]
|
||||
ldap_name = "nvram"
|
||||
|
||||
def parse_value(self, nvr):
|
||||
# XXX - on fait quoi ici ?
|
||||
|
@ -695,7 +818,7 @@ class portAttr(Attr):
|
|||
legend = u'Ouverture de port'
|
||||
category = 'firewall'
|
||||
can_modify = [nounou]
|
||||
|
||||
|
||||
def parse_value(self, port):
|
||||
if ":" in port:
|
||||
a,b = port.split(":", 1)
|
||||
|
@ -724,55 +847,73 @@ class portAttr(Attr):
|
|||
else:
|
||||
return unicode(self.value[0])
|
||||
|
||||
@crans_attribute
|
||||
class portTCPout(portAttr):
|
||||
legend = u'Port TCP ouvert vers l\'extérieur'
|
||||
ldap_name = "portTCPout"
|
||||
|
||||
@crans_attribute
|
||||
class portTCPin(portAttr):
|
||||
legend = u"Port TCP ouvert depuis l'extérieur"
|
||||
ldap_name = "portTCPin"
|
||||
|
||||
@crans_attribute
|
||||
class portUDPout(portAttr):
|
||||
legend = u"Port UDP ouvert vers l'extérieur"
|
||||
ldap_name = "portUDPout"
|
||||
|
||||
@crans_attribute
|
||||
class portUDPin(portAttr):
|
||||
legend = u"Port UDP ouvert depuis l'extérieur"
|
||||
ldap_name = "portUDPin"
|
||||
|
||||
@crans_attribute
|
||||
class exempt(Attr):
|
||||
legend = u"Exemption vers une IP"
|
||||
ldap_name = "exempt"
|
||||
|
||||
@crans_attribute
|
||||
class nombrePrises(intAttr):
|
||||
legend = u"Nombre de prises ethernet de la machine"
|
||||
singlevalue = True
|
||||
optional = True
|
||||
categoriy = 'base_tech'
|
||||
can_modify = [nounou]
|
||||
ldap_name = "nombrePrises"
|
||||
|
||||
@crans_attribute
|
||||
class prise(Attr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
legend = u"Prise sur laquelle est branchée la machine"
|
||||
category = 'base_tech'
|
||||
can_modify = [nounou]
|
||||
ldap_name = "prise"
|
||||
|
||||
def parse_value(self, prise):
|
||||
### Tu es Beau, je te fais confiance
|
||||
self.value = prise
|
||||
|
||||
@crans_attribute
|
||||
class cid(intAttr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
unique = True
|
||||
legend = u"Identifiant du club"
|
||||
category = 'id'
|
||||
ldap_name = "cid"
|
||||
|
||||
def parse_value(self, val):
|
||||
self.value = int(val)
|
||||
|
||||
@crans_attribute
|
||||
class responsable(Attr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
legend = u"Responsable du club"
|
||||
category = 'perso'
|
||||
can_modify = [cableur, nounou]
|
||||
ldap_name = "responsable"
|
||||
|
||||
def nonefunction(self, resp):
|
||||
"""
|
||||
|
@ -805,11 +946,13 @@ class responsable(Attr):
|
|||
def __unicode__(self):
|
||||
return self.__value
|
||||
|
||||
@crans_attribute
|
||||
class imprimeurClub(Attr):
|
||||
optional = True
|
||||
legend = u"Imprimeur du club"
|
||||
category = "perso"
|
||||
can_modify = [cableur, nounou]
|
||||
ldap_name = "imprimeurClub"
|
||||
|
||||
def nonefunction(self, imprimeur):
|
||||
"""
|
||||
|
@ -839,12 +982,14 @@ class imprimeurClub(Attr):
|
|||
def __unicode__(self):
|
||||
return unicode(self.value['aid'][0])
|
||||
|
||||
@crans_attribute
|
||||
class blacklist(Attr):
|
||||
singlevalue = False
|
||||
optional = True
|
||||
legend = u"Blackliste"
|
||||
category = 'info'
|
||||
can_modify = [nounou]
|
||||
ldap_name = "blacklist"
|
||||
|
||||
def parse_value(self, blacklist):
|
||||
bl_debut, bl_fin, bl_type, bl_comm = blacklist.split('$')
|
||||
|
@ -865,43 +1010,53 @@ class blacklist(Attr):
|
|||
def __unicode__(self):
|
||||
return u'%(debut)s$%(fin)s$%(type)s$%(comm)s' % self.value
|
||||
|
||||
@crans_attribute
|
||||
class historique(Attr):
|
||||
singlevalue = False
|
||||
optional = True
|
||||
legend = u"Historique de l'objet"
|
||||
category = 'info'
|
||||
ldap_name = "historique"
|
||||
|
||||
@crans_attribute
|
||||
class info(Attr):
|
||||
singlevalue = False
|
||||
optional = True
|
||||
legend = u"Quelques informations"
|
||||
category = 'info'
|
||||
can_modify = [nounou, cableur, bureau]
|
||||
ldap_name = "info"
|
||||
|
||||
@crans_attribute
|
||||
class homepageAlias(Attr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
legend = u'Un alias pour la page personnelle'
|
||||
can_modify = [nounou, cableur]
|
||||
category = 'webpage'
|
||||
ldap_name = "homepageAlias"
|
||||
|
||||
@crans_attribute
|
||||
class charteMA(Attr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
legend= "Signale si l'adhérent a signé la charte de membres actifs"
|
||||
can_modify = [nounou, bureau]
|
||||
category = 'perso'
|
||||
|
||||
ldap_name = "charteMA"
|
||||
|
||||
def parse_value(self, charteSignee):
|
||||
if charteSignee.upper() not in ["TRUE", "FALSE"]:
|
||||
raise ValueError("La charte MA est soit TRUE ou FALSE, pas %r" % charteSignee)
|
||||
self.value = charteSignee.upper()
|
||||
|
||||
@crans_attribute
|
||||
class homeDirectory(Attr):
|
||||
singlevalue=True
|
||||
optional = True
|
||||
unique = True
|
||||
legend="Le chemin du home de l'adhérent"
|
||||
ldap_name = "homeDirectory"
|
||||
|
||||
def parse_value(self, home):
|
||||
uid = str(self.parent['uid'][0])
|
||||
|
@ -911,12 +1066,14 @@ class homeDirectory(Attr):
|
|||
raise ValueError("Le répertoire personnel n'est pas bon: %r (devrait être %r ou %r)" % (home, '/home/%s' % self.parent['uid'][0], '/home/club/%s' % self.parent['uid'][0]))
|
||||
self.value = home
|
||||
|
||||
@crans_attribute
|
||||
class loginShell(Attr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
legend = "Le shell de l'adherent"
|
||||
can_modify = [soi, nounou, cableur]
|
||||
|
||||
ldap_name = "loginShell"
|
||||
|
||||
def parse_value(self, shell):
|
||||
#with open('/etc/shells') as f:
|
||||
# shells = [ l.strip() for l in f.readlines() if not l.startswith('#') ]
|
||||
|
@ -948,95 +1105,113 @@ class loginShell(Attr):
|
|||
raise ValueError("Shell %r invalide" % shell)
|
||||
self.value = shell
|
||||
|
||||
@crans_attribute
|
||||
class uidNumber(intAttr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
unique = True
|
||||
legend = "L'uid du compte de l'adherent"
|
||||
category = 'id'
|
||||
ldap_name = "uidNumber"
|
||||
|
||||
@crans_attribute
|
||||
class gidNumber(intAttr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
legend = "Le gid du compte de l'adhérent"
|
||||
category = 'id'
|
||||
ldap_name = "gidNumber"
|
||||
|
||||
@crans_attribute
|
||||
class gecos(Attr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
legend = "Le gecos"
|
||||
category = 'id'
|
||||
ldap_name = "gecos"
|
||||
|
||||
def parse_value(self, gecos):
|
||||
self.value = gecos
|
||||
|
||||
@crans_attribute
|
||||
class sshFingerprint(Attr):
|
||||
singlevalue = False
|
||||
optional = True
|
||||
legend = "Clef ssh de la machine"
|
||||
can_modify = [parent, nounou]
|
||||
ldap_name = "sshFingerprint"
|
||||
|
||||
@crans_attribute
|
||||
class gpgFingerprint(Attr):
|
||||
singlevalue = False
|
||||
optional = True
|
||||
unique = True
|
||||
legend = "Clef gpg d'un adhérent"
|
||||
can_modify = [soi, nounou]
|
||||
ldap_name = "gpgFingerprint"
|
||||
|
||||
@crans_attribute
|
||||
class cn(Attr):
|
||||
singlevalue = True
|
||||
optional = False
|
||||
category = 'id'
|
||||
ldap_name = "cn"
|
||||
|
||||
@crans_attribute
|
||||
class dn(Attr):
|
||||
singlevalue = True
|
||||
optional = False
|
||||
unique = True
|
||||
category = 'id'
|
||||
ldap_name = "dn"
|
||||
|
||||
@crans_attribute
|
||||
class postalAddress(Attr):
|
||||
singlevalue = False
|
||||
optional = True
|
||||
can_modify = [soi, cableur, nounou, bureau]
|
||||
legend = u"Adresse"
|
||||
category = 'perso'
|
||||
ldap_name = "postalAddress"
|
||||
|
||||
@crans_attribute
|
||||
class controle(Attr):
|
||||
singlevalue = True
|
||||
optional = True
|
||||
legend = u"Contrôle"
|
||||
can_modify = [tresorier, nounou]
|
||||
category = 'perso'
|
||||
|
||||
ldap_name = "controle"
|
||||
|
||||
def parse_value(self, ctrl):
|
||||
if ctrl not in [u"", u"c", u"p", u"cp", u"pc"]:
|
||||
raise ValueError("control peut prendre les valeurs [c][p]")
|
||||
self.value = ctrl
|
||||
|
||||
@crans_attribute
|
||||
class fid(intAttr):
|
||||
legend = u"Id de facture"
|
||||
category = 'factures'
|
||||
optional = False
|
||||
singlevalue = True
|
||||
ldap_name = "fid"
|
||||
|
||||
@crans_attribute
|
||||
class modePaiement(Attr):
|
||||
legend = u"Mode de paiement"
|
||||
category = 'factures'
|
||||
optional = False
|
||||
singlevalue = True
|
||||
ldap_name = "modePaiement"
|
||||
|
||||
@crans_attribute
|
||||
class recuPaiement(Attr):
|
||||
pass
|
||||
ldap_name = "recuPaiement"
|
||||
|
||||
@crans_attribute
|
||||
class dnsIpv6(boolAttr):
|
||||
pass
|
||||
ldap_name = "dnsIpv6"
|
||||
|
||||
@crans_attribute
|
||||
class machineAlias(boolAttr):
|
||||
pass
|
||||
|
||||
## Penser à remplacer ça par un dictionnaire en compréhension quand on sera sous wheezy partout
|
||||
#: Dictionnaire mappant "nom de l'atttribut" -> classe permettant de l'instancier
|
||||
CRANS_ATTRIBUTES = {}
|
||||
for (k, v) in locals().items():
|
||||
if type(v) == type and issubclass(v, Attr):
|
||||
CRANS_ATTRIBUTES[k] = v
|
||||
ldap_name = "machineAlias"
|
||||
|
|
70
lc_ldap.py
70
lc_ldap.py
|
@ -53,9 +53,10 @@ try:
|
|||
from Levenshtein import jaro
|
||||
except ImportError:
|
||||
def jaro(a, b): return 0
|
||||
sys.path.append('/usr/scripts/gestion')
|
||||
|
||||
sys.path.append('/usr/scripts/gestion')
|
||||
import config
|
||||
|
||||
import crans_utils
|
||||
import attributs
|
||||
import ldap_locks
|
||||
|
@ -71,9 +72,9 @@ created = 'created'
|
|||
modified = 'modified'
|
||||
deleted = 'deleted'
|
||||
|
||||
# Pour enregistrer dans l'historique, on a besoin de savoir qui exécute le script
|
||||
# Si le script a été exécuté via un sudo, la variable SUDO_USER (l'utilisateur qui a effectué le sudo)
|
||||
# est plus pertinente que USER (qui sera root)
|
||||
#: Pour enregistrer dans l'historique, on a besoin de savoir qui exécute le script
|
||||
#: Si le script a été exécuté via un sudo, la variable SUDO_USER (l'utilisateur qui a effectué le sudo)
|
||||
#: est plus pertinente que USER (qui sera root)
|
||||
current_user = os.getenv("SUDO_USER") or os.getenv("USER")
|
||||
|
||||
# Quand on a besoin du fichier de secrets
|
||||
|
@ -84,7 +85,7 @@ def import_secrets():
|
|||
import secrets
|
||||
return secrets
|
||||
|
||||
# Champs à ignorer dans l'historique
|
||||
#: Champs à ignorer dans l'historique
|
||||
HIST_IGNORE_FIELDS = ["modifiersName", "entryCSN", "modifyTimestamp", "historique"]
|
||||
|
||||
def escape(chaine):
|
||||
|
@ -453,9 +454,9 @@ class lc_ldap_local(lc_ldap):
|
|||
|
||||
|
||||
def new_cransldapobject(conn, dn, mode='ro', ldif = None):
|
||||
"""Crée un objet :py:class:`CransLdap` en utilisant la classe correspondant à
|
||||
"""Crée un objet :py:class:`CransLdapObject` en utilisant la classe correspondant à
|
||||
l'``objectClass`` du ``ldif``
|
||||
--pour usage interne à la libraire uniquement !"""
|
||||
--pour usage interne à la librairie uniquement !"""
|
||||
|
||||
classe = None
|
||||
|
||||
|
@ -464,13 +465,13 @@ def new_cransldapobject(conn, dn, mode='ro', ldif = None):
|
|||
elif dn == invite_dn:
|
||||
classe = BaseInvites
|
||||
elif ldif:
|
||||
classe = globals()[ldif['objectClass'][0]]
|
||||
classe = ObjectFactory.get(ldif['objectClass'][0])
|
||||
else:
|
||||
res = conn.search_s(dn, 0)
|
||||
if not res:
|
||||
raise ValueError ('objet inexistant: %s' % dn)
|
||||
_, attrs = res[0]
|
||||
classe = globals()[attrs['objectClass'][0]]
|
||||
classe = ObjectFactory.get(attrs['objectClass'][0])
|
||||
|
||||
return classe(conn, dn, mode, ldif)
|
||||
|
||||
|
@ -793,6 +794,36 @@ class CransLdapObject(object):
|
|||
|
||||
self._modifs.setdefault('blacklist', []).append(bl)
|
||||
|
||||
class ObjectFactory(object):
|
||||
"""Utilisée pour enregistrer toutes les classes servant à instancier un objet LDAP.
|
||||
Elle sert à les récupérer à partir de leur nom LDAP.
|
||||
|
||||
Cette classe n'est jamais instanciée.
|
||||
|
||||
"""
|
||||
_classes = {}
|
||||
|
||||
@classmethod
|
||||
def register(cls, name, classe):
|
||||
"""Enregistre l'association ``name`` -> ``classe``"""
|
||||
cls._classes[name] = classe
|
||||
|
||||
@classmethod
|
||||
def get(cls, name):
|
||||
"""Retourne la classe qui a ``name`` pour ``ldap_name``.
|
||||
|
||||
Pas de fallback, on ne veut pas instancier des objets de manière hasardeuse.
|
||||
"""
|
||||
return cls._classes.get(name)
|
||||
|
||||
def crans_object(classe):
|
||||
"""Pour décorer les classes permettant d'instancier des attributs LDAP,
|
||||
afin de les enregistrer dans :py:class:`ObjectFactory`.
|
||||
|
||||
"""
|
||||
ObjectFactory.register(classe.ldap_name, classe)
|
||||
return classe
|
||||
|
||||
|
||||
class proprio(CransLdapObject):
|
||||
u""" Un propriétaire de machine (adhérent, club…) """
|
||||
|
@ -944,6 +975,7 @@ class BaseInvites(proprio):
|
|||
pass
|
||||
|
||||
|
||||
@crans_object
|
||||
class adherent(proprio):
|
||||
u"""Adhérent crans."""
|
||||
attribs = proprio.attribs + [attributs.aid, attributs.prenom, attributs.tel,
|
||||
|
@ -951,6 +983,7 @@ class adherent(proprio):
|
|||
attributs.derniereConnexion, attributs.gpgFingerprint,
|
||||
attributs.carteEtudiant, attributs.droits, attributs.etudes,
|
||||
attributs.postalAddress, attributs.mailExt, attributs.compteWiki]
|
||||
ldap_name = "adherent"
|
||||
|
||||
def __init__(self, conn, dn, mode='ro', ldif = None):
|
||||
super(adherent, self).__init__(conn, dn, mode, ldif)
|
||||
|
@ -1028,17 +1061,22 @@ class adherent(proprio):
|
|||
raise EnvironmentError("L'adhérent n'a pas de compte crans")
|
||||
|
||||
|
||||
@crans_object
|
||||
class club(proprio):
|
||||
u"""Club crans"""
|
||||
attribs = proprio.attribs + [attributs.cid, attributs.responsable, attributs.imprimeurClub]
|
||||
ldap_name = "club"
|
||||
|
||||
@crans_object
|
||||
class machineFixe(machine):
|
||||
u"""Machine fixe"""
|
||||
pass
|
||||
ldap_name = "machineFixe"
|
||||
|
||||
@crans_object
|
||||
class machineWifi(machine):
|
||||
u"""Machine wifi"""
|
||||
attribs = machine.attribs + [attributs.ipsec]
|
||||
ldap_name = "machineWifi"
|
||||
|
||||
def set_ipv4(self, login=None):
|
||||
u"""Définie une ipv4 à la machine si elle n'est possède pas déjà une."""
|
||||
|
@ -1053,13 +1091,16 @@ class machineWifi(machine):
|
|||
dhcp=dydhcp()
|
||||
dhcp.add_host(str(self['ipHostNumber'][0]), str(self['macAddress'][0]), str(self['host'][0]))
|
||||
|
||||
@crans_object
|
||||
class machineCrans(machine):
|
||||
can_be_by = { created: [attributs.nounou],
|
||||
modified: [attributs.nounou],
|
||||
deleted: [attributs.nounou],
|
||||
}
|
||||
attribs = machine.attribs + [attributs.prise, attributs.nombrePrises]
|
||||
ldap_name = "machineCrans"
|
||||
|
||||
@crans_object
|
||||
class borneWifi(machine):
|
||||
can_be_by = { created: [attributs.nounou],
|
||||
modified: [attributs.nounou],
|
||||
|
@ -1067,16 +1108,21 @@ class borneWifi(machine):
|
|||
}
|
||||
attribs = machine.attribs + [attributs.canal, attributs.puissance, attributs.hotspot,
|
||||
attributs.prise, attributs.positionBorne, attributs.nvram]
|
||||
ldap_name = "borneWifi"
|
||||
|
||||
@crans_object
|
||||
class facture(CransLdapObject):
|
||||
can_be_by = { created: [attributs.nounou, attributs.bureau, attributs.cableur],
|
||||
modified: [attributs.nounou, attributs.bureau, attributs.cableur],
|
||||
deleted: [attributs.nounou, attributs.bureau, attributs.cableur],
|
||||
}
|
||||
attribs = [attributs.fid, attributs.modePaiement, attributs.recuPaiement]
|
||||
ldap_name = "facture"
|
||||
|
||||
@crans_object
|
||||
class service(CransLdapObject):
|
||||
pass
|
||||
ldap_name = "service"
|
||||
|
||||
@crans_object
|
||||
class lock(CransLdapObject):
|
||||
pass
|
||||
ldap_name = "lock"
|
||||
|
|
272
services.py
272
services.py
|
@ -69,162 +69,162 @@ def preattr(val):
|
|||
|
||||
# Presque identique à celle dans ldap_crans.py
|
||||
def service_to_restart(conn, new=None, args=[], start=0):
|
||||
"""
|
||||
start indique la date (en secondes depuis epoch) à partir du
|
||||
moment où cette action sera effectuée.
|
||||
"""
|
||||
start indique la date (en secondes depuis epoch) à partir du
|
||||
moment où cette action sera effectuée.
|
||||
|
||||
Si new = None retourne la liste des services à redémarrer.
|
||||
Si new = None retourne la liste des services à redémarrer.
|
||||
|
||||
Si new est fourni, mais ne commence pas par '-', on ajoute
|
||||
le service à la liste avec les arguments args (args doit être
|
||||
une liste).
|
||||
Si new est fourni, mais ne commence pas par '-', on ajoute
|
||||
le service à la liste avec les arguments args (args doit être
|
||||
une liste).
|
||||
|
||||
Si new commence par '-', on supprime le service si son start
|
||||
est dans le futur.
|
||||
Si new commence par '-', on supprime le service si son start
|
||||
est dans le futur.
|
||||
|
||||
Si new commence par '--', on supprime le service sans condition.
|
||||
"""
|
||||
if new: new = preattr(new)[1]
|
||||
Si new commence par '--', on supprime le service sans condition.
|
||||
"""
|
||||
if new: new = preattr(new)[1]
|
||||
|
||||
# Quels services sont déjà à redémarrer ?
|
||||
serv = {} # { service: [ arguments ] }
|
||||
serv_dates = {} # { service: [ dates de restart ] }
|
||||
services = []
|
||||
for s in conn.search_s(services_dn, 1, 'objectClass=service'):
|
||||
s = s[1]
|
||||
serv[s['cn'][0]] = s.get('args', [])
|
||||
serv_dates[s['cn'][0]] = s.get('start', [])
|
||||
services.append(Service(s['cn'][0], s.get('args', []), s.get('start', [])))
|
||||
# Quels services sont déjà à redémarrer ?
|
||||
serv = {} # { service: [ arguments ] }
|
||||
serv_dates = {} # { service: [ dates de restart ] }
|
||||
services = []
|
||||
for s in conn.search_s(services_dn, 1, 'objectClass=service'):
|
||||
s = s[1]
|
||||
serv[s['cn'][0]] = s.get('args', [])
|
||||
serv_dates[s['cn'][0]] = s.get('start', [])
|
||||
services.append(Service(s['cn'][0], s.get('args', []), s.get('start', [])))
|
||||
|
||||
# Retourne la liste des services à redémarrer
|
||||
if not new: return services
|
||||
# Retourne la liste des services à redémarrer
|
||||
if not new: return services
|
||||
|
||||
# Effacement d'un service
|
||||
if new[0] == '-':
|
||||
if new[1] == '-':
|
||||
# Double -- on enlève quelque soit la date
|
||||
remove_dn = 'cn=%s,%s' % (new[2:], services_dn)
|
||||
else:
|
||||
# On enlève uniquement si la date est passée
|
||||
remove_dn = 'cn=%s,%s' % (new[1:], services_dn)
|
||||
if not serv.has_key(new[1:]):
|
||||
# Existe pas => rien à faire
|
||||
return
|
||||
keep_date = []
|
||||
for date in serv_dates[new[1:]]:
|
||||
if time.time() < int(date):
|
||||
keep_date.append(date)
|
||||
if keep_date:
|
||||
mods = [{'start': serv_dates[new[1:]]}, { 'start': keep_date }]
|
||||
conn.modify_s(remove_dn, ldap.modlist.modifyModlist(*mods))
|
||||
remove_dn = None
|
||||
|
||||
if remove_dn:
|
||||
# Suppression
|
||||
try: conn.delete_s(remove_dn)
|
||||
except: pass
|
||||
# Si n'existe pas => Erreur mais le résultat est là.
|
||||
return
|
||||
|
||||
serv_dn = 'cn=%s,%s' % (new, services_dn)
|
||||
|
||||
# Conversion avant stockage dans la base
|
||||
if isinstance(args, basestring):
|
||||
args = [args]
|
||||
args = map(lambda x:preattr(x)[1], args)
|
||||
try:
|
||||
start = [int(start)]
|
||||
except TypeError:
|
||||
pass
|
||||
start = map(lambda x:preattr(x)[1], start)
|
||||
|
||||
if new in serv.keys():
|
||||
modlist = []
|
||||
|
||||
new_args = []
|
||||
# Nouveaux arguments ?
|
||||
for arg in args:
|
||||
if arg not in serv[new]:
|
||||
new_args.append(arg)
|
||||
if new_args:
|
||||
modlist += ldap.modlist.modifyModlist({'args': serv[new]},
|
||||
{'args': serv[new] + new_args})
|
||||
|
||||
new_date = []
|
||||
# Nouvelle date ?
|
||||
for date in start:
|
||||
if date not in serv_dates[new]:
|
||||
new_date.append(date)
|
||||
if new_date:
|
||||
modlist += ldap.modlist.modifyModlist({'start': serv_dates[new]},
|
||||
{'start': serv_dates[new] + new_date})
|
||||
|
||||
if modlist:
|
||||
try:
|
||||
conn.modify_s(serv_dn, modlist)
|
||||
except ldap.TYPE_OR_VALUE_EXISTS:
|
||||
# Pas grave
|
||||
pass
|
||||
# else rien à faire
|
||||
# Effacement d'un service
|
||||
if new[0] == '-':
|
||||
if new[1] == '-':
|
||||
# Double -- on enlève quelque soit la date
|
||||
remove_dn = 'cn=%s,%s' % (new[2:], services_dn)
|
||||
else:
|
||||
# Entrée non présente -> ajout
|
||||
modlist = ldap.modlist.addModlist({ 'objectClass': 'service',
|
||||
'cn': new,
|
||||
'args': args,
|
||||
'start': start })
|
||||
# On enlève uniquement si la date est passée
|
||||
remove_dn = 'cn=%s,%s' % (new[1:], services_dn)
|
||||
if not serv.has_key(new[1:]):
|
||||
# Existe pas => rien à faire
|
||||
return
|
||||
keep_date = []
|
||||
for date in serv_dates[new[1:]]:
|
||||
if time.time() < int(date):
|
||||
keep_date.append(date)
|
||||
if keep_date:
|
||||
mods = [{'start': serv_dates[new[1:]]}, { 'start': keep_date }]
|
||||
conn.modify_s(remove_dn, ldap.modlist.modifyModlist(*mods))
|
||||
remove_dn = None
|
||||
|
||||
if remove_dn:
|
||||
# Suppression
|
||||
try: conn.delete_s(remove_dn)
|
||||
except: pass
|
||||
# Si n'existe pas => Erreur mais le résultat est là.
|
||||
return
|
||||
|
||||
serv_dn = 'cn=%s,%s' % (new, services_dn)
|
||||
|
||||
# Conversion avant stockage dans la base
|
||||
if isinstance(args, basestring):
|
||||
args = [args]
|
||||
args = map(lambda x:preattr(x)[1], args)
|
||||
try:
|
||||
start = [int(start)]
|
||||
except TypeError:
|
||||
pass
|
||||
start = map(lambda x:preattr(x)[1], start)
|
||||
|
||||
if new in serv.keys():
|
||||
modlist = []
|
||||
|
||||
new_args = []
|
||||
# Nouveaux arguments ?
|
||||
for arg in args:
|
||||
if arg not in serv[new]:
|
||||
new_args.append(arg)
|
||||
if new_args:
|
||||
modlist += ldap.modlist.modifyModlist({'args': serv[new]},
|
||||
{'args': serv[new] + new_args})
|
||||
|
||||
new_date = []
|
||||
# Nouvelle date ?
|
||||
for date in start:
|
||||
if date not in serv_dates[new]:
|
||||
new_date.append(date)
|
||||
if new_date:
|
||||
modlist += ldap.modlist.modifyModlist({'start': serv_dates[new]},
|
||||
{'start': serv_dates[new] + new_date})
|
||||
|
||||
if modlist:
|
||||
try:
|
||||
conn.add_s(serv_dn, modlist)
|
||||
except ldap.ALREADY_EXISTS:
|
||||
# Existe déja => rien à faire
|
||||
conn.modify_s(serv_dn, modlist)
|
||||
except ldap.TYPE_OR_VALUE_EXISTS:
|
||||
# Pas grave
|
||||
pass
|
||||
# else rien à faire
|
||||
else:
|
||||
# Entrée non présente -> ajout
|
||||
modlist = ldap.modlist.addModlist({ 'objectClass': 'service',
|
||||
'cn': new,
|
||||
'args': args,
|
||||
'start': start })
|
||||
try:
|
||||
conn.add_s(serv_dn, modlist)
|
||||
except ldap.ALREADY_EXISTS:
|
||||
# Existe déja => rien à faire
|
||||
pass
|
||||
|
||||
def services_to_restart(conn, old_attrs={}, new_attrs={}):
|
||||
"""Détermine quels sont les services à reconfigurer"""
|
||||
old_attrs_c = dict((attributs.CRANS_ATTRIBUTES[key], value) for key,value in old_attrs.items() if key in attributs.CRANS_ATTRIBUTES.keys() and value)
|
||||
new_attrs_c = dict((attributs.CRANS_ATTRIBUTES[key], value) for key,value in new_attrs.items() if key in attributs.CRANS_ATTRIBUTES.keys() and value)
|
||||
"""Détermine quels sont les services à reconfigurer"""
|
||||
old_attrs_c = dict((attributs.AttributeFactory.get(key), value) for key,value in old_attrs.items() if attributs.AttributeFactory.get(key, fallback=None) != None and value)
|
||||
new_attrs_c = dict((attributs.AttributeFactory.get(key), value) for key,value in new_attrs.items() if attributs.AttributeFactory.get(key, fallback=None) != None and value)
|
||||
|
||||
created_attr = [ attr for name in new_attrs_c.keys() if not name in old_attrs_c.keys() for attr in new_attrs_c[name]]
|
||||
deleted_attr = [ attr for name in old_attrs_c.keys() if not name in new_attrs_c.keys() for attr in old_attrs_c[name]]
|
||||
updated_attr = [ (old_attrs_c[name], new_attrs_c[name],
|
||||
created_attr = [ attr for name in new_attrs_c.keys() if not name in old_attrs_c.keys() for attr in new_attrs_c[name]]
|
||||
deleted_attr = [ attr for name in old_attrs_c.keys() if not name in new_attrs_c.keys() for attr in old_attrs_c[name]]
|
||||
updated_attr = [ (old_attrs_c[name], new_attrs_c[name],
|
||||
[ i for i in old_attrs_c[name] if i.value not in [ j.value for j in new_attrs_c[name]]],
|
||||
[ i for i in new_attrs_c[name] if i.value not in [ j.value for j in old_attrs_c[name]]],
|
||||
) for name in set(new_attrs_c.keys()).intersection(old_attrs_c.keys()) if old_attrs_c[name][-1].value != new_attrs_c[name][-1].value ]
|
||||
updated_attr_new = [ i for j in updated_attr for i in j[3]]
|
||||
updated_attr_old = [ i for j in updated_attr for i in j[2]]
|
||||
) for name in set(new_attrs_c.keys()).intersection(old_attrs_c.keys()) if old_attrs_c[name][-1].value != new_attrs_c[name][-1].value ]
|
||||
updated_attr_new = [ i for j in updated_attr for i in j[3]]
|
||||
updated_attr_old = [ i for j in updated_attr for i in j[2]]
|
||||
|
||||
services_to_restart = {}
|
||||
for attr in [ attr for l in [created_attr, deleted_attr, updated_attr_new ] for attr in l]:
|
||||
for service in attrs_to_services.get(attr.__class__, []):
|
||||
services_to_restart[service] = services_to_restart.get(service, []) + [attr]
|
||||
services_to_restart = {}
|
||||
for attr in [ attr for l in [created_attr, deleted_attr, updated_attr_new ] for attr in l]:
|
||||
for service in attrs_to_services.get(attr.__class__, []):
|
||||
services_to_restart[service] = services_to_restart.get(service, []) + [attr]
|
||||
|
||||
for service in services_to_restart.keys():
|
||||
for attr in services_to_restart[service]:
|
||||
start = 0
|
||||
arg = set()
|
||||
if service in services_to_args.keys():
|
||||
arg = arg.union(services_to_args[service](attr))
|
||||
if attr in updated_attr_new:
|
||||
for old_attr in updated_attr_old:
|
||||
if attr.__class__ == old_attr.__class__:
|
||||
arg = arg.union(services_to_args[service](old_attr))
|
||||
for service in services_to_restart.keys():
|
||||
for attr in services_to_restart[service]:
|
||||
start = 0
|
||||
arg = set()
|
||||
if service in services_to_args.keys():
|
||||
arg = arg.union(services_to_args[service](attr))
|
||||
if attr in updated_attr_new:
|
||||
for old_attr in updated_attr_old:
|
||||
if attr.__class__ == old_attr.__class__:
|
||||
arg = arg.union(services_to_args[service](old_attr))
|
||||
|
||||
# Cas du dhcp
|
||||
if attr.__class__ in services_to_attrs['dhcp']:
|
||||
dhcp=dydhcp()
|
||||
if old_attrs.get('ipHostNumber', []) and old_attrs.get('macAddress', []):
|
||||
if new_attrs.get('ipHostNumber', []) and new_attrs.get('macAddress', []):
|
||||
if str(old_attrs['ipHostNumber'][0]) != str(new_attrs['ipHostNumber'][0]) or str(old_attrs['macAddress'][0]) != str(new_attrs['macAddress'][0]):
|
||||
dhcp.del_host(str(old_attrs['ipHostNumber'][0]), str(old_attrs['macAddress'][0]))
|
||||
dhcp.add_host(str(new_attrs['ipHostNumber'][0]), str(new_attrs['macAddress'][0]), str(new_attrs['host'][0]))
|
||||
else:
|
||||
# Cas du dhcp
|
||||
if attr.__class__ in services_to_attrs['dhcp']:
|
||||
dhcp=dydhcp()
|
||||
if old_attrs.get('ipHostNumber', []) and old_attrs.get('macAddress', []):
|
||||
if new_attrs.get('ipHostNumber', []) and new_attrs.get('macAddress', []):
|
||||
if str(old_attrs['ipHostNumber'][0]) != str(new_attrs['ipHostNumber'][0]) or str(old_attrs['macAddress'][0]) != str(new_attrs['macAddress'][0]):
|
||||
dhcp.del_host(str(old_attrs['ipHostNumber'][0]), str(old_attrs['macAddress'][0]))
|
||||
elif new_attrs.get('ipHostNumber', []) and new_attrs.get('macAddress', []):
|
||||
dhcp.add_host(str(new_attrs['ipHostNumber'][0]), str(new_attrs['macAddress'][0]), str(new_attrs['host'][0]))
|
||||
dhcp.add_host(str(new_attrs['ipHostNumber'][0]), str(new_attrs['macAddress'][0]), str(new_attrs['host'][0]))
|
||||
else:
|
||||
dhcp.del_host(str(old_attrs['ipHostNumber'][0]), str(old_attrs['macAddress'][0]))
|
||||
elif new_attrs.get('ipHostNumber', []) and new_attrs.get('macAddress', []):
|
||||
dhcp.add_host(str(new_attrs['ipHostNumber'][0]), str(new_attrs['macAddress'][0]), str(new_attrs['host'][0]))
|
||||
|
||||
if service in services_to_time.keys():
|
||||
start = services_to_time[service](attr)
|
||||
#print "%s,%s,%s" % (service, arg, start)
|
||||
service_to_restart(conn, service, list(arg), start)
|
||||
if service in services_to_time.keys():
|
||||
start = services_to_time[service](attr)
|
||||
#print "%s,%s,%s" % (service, arg, start)
|
||||
service_to_restart(conn, service, list(arg), start)
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue