diff --git a/gestion/ldap_crans.py b/gestion/ldap_crans.py index 1cba9cb2..d4cb07f9 100755 --- a/gestion/ldap_crans.py +++ b/gestion/ldap_crans.py @@ -18,9 +18,9 @@ from chgpass import chgpass from affich_tools import coul, prompt from time import sleep,localtime -try : +try: from secrets import ldap_password, ldap_auth_dn -except : +except: sys.stdout.write(coul('Warning : impossible de lire le fichier de secret !','jaune')) sleep(2) ldap_password = '' @@ -32,18 +32,18 @@ if hostname == "vert": anon_bind = 1 # Anonyme pour lecture seule uri = 'ldapi://%2fvar%2frun%2fldapi/' rw_uri = uri -elif hostname in [ 'sila' , 'pegase' ] : +elif hostname in [ 'sila' , 'pegase' ]: anon_bind = 1 # Anonyme pour lecture seule uri = 'ldapi://%2fvar%2frun%2fldapi/' rw_uri = 'ldap://ldap.adm.crans.org/' -elif hostname == 'egon' and not '/usr/scripts/gestion/' in sys.argv[0] : +elif hostname == 'egon' and not '/usr/scripts/gestion/' in sys.argv[0]: # pour les tests, les séminaires... sur egon anon_bind = 1 # Anonyme pour lecture seule uri = 'ldapi://%2fvar%2frun%2fldapi/' rw_uri = uri ldap_auth_dn='cn=admin,dc=crans,dc=org' ldap_password='75bdb64f32' -else : +else: anon_bind = 0 uri = 'ldap://ldap.adm.crans.org/' rw_uri = uri @@ -74,13 +74,13 @@ script_utilisateur = user_tests.getuser() ################################################################################## ### Fonctions utiles -def decode(s) : +def decode(s): """ Retourne un unicode à partir de s s doit être en utf-8 """ return s.decode('utf-8','ignore') # On ignore les erreurs accents = "êëèéÉÈÀÙâäàûüôöÖÔîïÎÏ'çÇÿßæÆøØ" # Si modif ici modifier aussi la fonction -def strip_accents(a) : +def strip_accents(a): """ Supression des accents de la chaîne fournie """ a = a.replace(u'ê','e').replace(u'ë','e').replace(u'è','e').replace(u'é','e').replace(u'É','e').replace(u'È','e') a = a.replace(u'â','a').replace(u'ä','a').replace(u'à','a').replace(u'À','a') @@ -91,22 +91,22 @@ def strip_accents(a) : a = a.replace(u'ÿ','y').replace(u'ß','ss').replace(u'æ','ae').replace(u'Æ','ae').replace(u'ø','o').replace(u'Ø','o') return a -def mailexist(mail) : +def mailexist(mail): """ Vérifie si un mail existe ou non grace à la commande vrfy du serveur mail """ - try : + try: s=smtplib.SMTP(smtpserv) r = s.vrfy(mail) s.close() - except : + except: raise ValueError(u'Serveur de mail injoignable') - if r[0] in [250, 252] : + if r[0] in [250, 252]: return True - else : + else: return False -def preattr(val) : +def preattr(val): """ val est : * un entier @@ -119,39 +119,39 @@ def preattr(val) : t = type(val) - if t==list and len(val)==1 : + if t==list and len(val)==1: return preattr(val[0]) - elif t==str or t==int : + elif t==str or t==int: val = str(val).strip() # On passe tout en utf-8 pour ne pas avoir de problèmes # d'accents dans la base return [ len(val) , unicode(val,'iso-8859-1').encode('utf-8') ] - elif t==unicode : + elif t==unicode: val = val.strip() return [ len(val) , val.encode('utf-8') ] - else : + else: raise TypeError -def is_actif(sanction) : +def is_actif(sanction): """ Retourne True ou False suivant si la sanction founie (chaine venant de blacklist) est active ou non """ bl = sanction.split(',') - try : + try: now = time.time() debut = time.mktime( time.strptime(bl[0],date_format) ) - if bl[1]=='-' : + if bl[1]=='-': fin = now + 1 - else : + else: fin = time.mktime( time.strptime(bl[1],date_format) ) return debut < now and fin > now - except : + except: return False -def format_mac(mac) : +def format_mac(mac): """ Formatage des adresses mac Transforme une adresse pour obtenir la forme xx:xx:xx:xx:xx:xx @@ -166,12 +166,12 @@ def format_mac(mac) : mac = ":".join(map(lambda x: x.replace(' ', '0'), map(lambda x: "%02s" % x, mac.split(":")))) mac= mac.replace(':','').lower() - if len(mac)!=12 : + if len(mac)!=12: raise ValueError(u'Longueur adresse mac incorrecte.') - for c in mac[:] : - if c not in string.hexdigits : + for c in mac[:]: + if c not in string.hexdigits: raise ValueError(u"Caractère interdit '%s' dans adresse mac." % c) - if mac=='000000000000' : + if mac=='000000000000': raise ValueError(u"MAC nulle interdite\nIl doit être possible de modifier l'adresse de la carte.") # Formatage @@ -182,9 +182,9 @@ def format_mac(mac) : ################################################################################## ### Définition des classes -class service : +class service: """ Défini un service à redémarrer """ - def __init__(self,nom,args=[],start=[]) : + def __init__(self,nom,args=[],start=[]): """ nom du service liste des arguments liste d'horaires de démarages """ @@ -192,12 +192,12 @@ class service : self.args=args self.start=map(int,start) - def __str__(self) : + def __str__(self): return "%s(%s) à partir du %s" % (self.nom, \ ','.join(self.args), \ ' et '.join(map(lambda t:time.strftime(date_format,time.gmtime(t)), self.start))) -class crans_ldap : +class crans_ldap: """ Classe de connexion à la base LDAP du crans. """ @@ -208,52 +208,52 @@ class crans_ldap : ### Configuration de la recheche # Dictionnaire de tranformation des champs - trans = { 'prénom' : 'prenom' , - 'chambre' : 'chbre', - 'login' : 'mail' , - 'hostname' : 'host', - 'mac' : 'macAddress', - 'ip' : 'ipHostNumber' , - 'telephone' : 'tel' } + trans = { 'prénom': 'prenom' , + 'chambre': 'chbre', + 'login': 'mail' , + 'hostname': 'host', + 'mac': 'macAddress', + 'ip': 'ipHostNumber' , + 'telephone': 'tel' } # Champs de recherche pour la recherche automatique - auto_search_champs = { 'adherent' : [ 'nom', 'prenom', 'tel', 'mail', 'chbre', 'mailAlias', 'cannonicalAlias' ], \ - 'machine' : [ 'macAddress', 'host', 'ipHostNumber', 'hostAlias'] , - 'club' : [ 'nom', 'chbre' ] } + auto_search_champs = { 'adherent': [ 'nom', 'prenom', 'tel', 'mail', 'chbre', 'mailAlias', 'cannonicalAlias' ], \ + 'machine': [ 'macAddress', 'host', 'ipHostNumber', 'hostAlias'] , + 'club': [ 'nom', 'chbre' ] } # Champs de recherche pour la recherche manuelle (en plus de la recherche auto) - non_auto_search_champs = { 'adherent' : [ 'etudes', 'paiement', 'carteEtudiant', 'aid' , 'postalAddress', 'historique' ,'blacklist', 'droits', 'uidNumber', 'uid', 'info', 'solde' ], \ - 'machine' : [ 'mid' , 'ipsec', 'historique', 'blacklist' , 'puissance', 'canal', 'portTCPin', 'portTCPout', 'portUDPin', 'portUDPout', 'prise' , 'info', 'exempt' ] , - 'club' : [ 'cid' , 'responsable', 'paiement', 'historique', 'blacklist', 'mailAlias', 'info'] } + non_auto_search_champs = { 'adherent': [ 'etudes', 'paiement', 'carteEtudiant', 'aid' , 'postalAddress', 'historique' ,'blacklist', 'droits', 'uidNumber', 'uid', 'info', 'solde' ], \ + 'machine': [ 'mid' , 'ipsec', 'historique', 'blacklist' , 'puissance', 'canal', 'portTCPin', 'portTCPout', 'portUDPin', 'portUDPout', 'prise' , 'info', 'exempt' ] , + 'club': [ 'cid' , 'responsable', 'paiement', 'historique', 'blacklist', 'mailAlias', 'info'] } # Scope des différentes recherches - scope = { 'adherent' : 1 , 'machine' : 2 , 'club' : 1 } + scope = { 'adherent': 1 , 'machine': 2 , 'club': 1 } - def __init__(self) : + def __init__(self): self.connect() - def __del__(self) : + def __del__(self): # Destruction des locks résiduels - if hasattr(self,'_locks') : - for lock in self._locks : + if hasattr(self,'_locks'): + for lock in self._locks: self.remove_lock(lock) def connect(self): """ Initialisation des connexion vers le serveur LDAP """ - def bind(conn,anon_bind=0) : + def bind(conn,anon_bind=0): """ Authentification auprès du serveur ldap """ nbessais = 0 ok = False while not ok: try: - if anon_bind : + if anon_bind: conn.bind_s('','',ldap.AUTH_SIMPLE) - else : + else: conn.bind_s(ldap_auth_dn,ldap_password,ldap.AUTH_SIMPLE) ok = True - except ldap.SERVER_DOWN : + except ldap.SERVER_DOWN: nbessais += 1 if nbessais > 2: sys.stderr.write("ERREUR : serveur LDAP injoignable\n") @@ -261,22 +261,22 @@ class crans_ldap : else: sleep(0.3) - def select_conn(methode_base, methode_alternative) : + def select_conn(methode_base, methode_alternative): """ Retoune une fonction qui : 1) bind sur la connection self.conn si necessaire 2) fait ce que ferai methode_base 3) si échoue bind sur la connexion self.rw_conn 4) fait ce que ferai methode_alternative """ - def new_methode(*args) : - try : - if not self.__conn_binded : + def new_methode(*args): + try: + if not self.__conn_binded: bind(self.conn,anon_bind) self.__conn_binded = True return methode_base(*args) - except ldap.STRONG_AUTH_REQUIRED : + except ldap.STRONG_AUTH_REQUIRED: # On a pas les droits necessaires ici - if not self.__rw_conn_binded : + if not self.__rw_conn_binded: bind(self.rw_conn) self.__rw_conn_binded = True return methode_alternative(*args) @@ -296,7 +296,7 @@ class crans_ldap : self.conn.modify_s = select_conn(self.conn.modify_s,self.rw_conn.modify_s) self.conn.delete_s = select_conn(self.conn.delete_s,self.rw_conn.delete_s) - def exist(self,arg) : + def exist(self,arg): """ Vérifie l'existence d'une entrée dans la base et que cette entrée n'appartient pas à l'objet en cours, prend en compte les locks @@ -307,38 +307,38 @@ class crans_ldap : """ r=[] - # Premier test : dans les objets déja inscrits + # Premier test: dans les objets déja inscrits ret = self.conn.search_s(self.base_dn,2,arg) - for res in ret : + for res in ret: # C'est peut être l'objet courant - try : # Si ce n'est pas une classe fille avec l'attribu dn => erreur - if res[0] == self.dn : + try: # Si ce n'est pas une classe fille avec l'attribu dn => erreur + if res[0] == self.dn: continue - except : + except: pass r.append(res[0]) # Deuxième test : lock ? ret = self.conn.search_s(self.base_lock,1,arg) lockid = '%s-%s' % (hostname, os.getpid() ) - for res in ret : + for res in ret: # Lock encore actif ? l = res[1]['lockid'][0] - if l == lockid : continue + if l == lockid: continue # C'est locké par un autre process que le notre # il tourne encore ? - try : - if l.split('-')[0] == hostname and os.system('ps %s > /dev/null 2>&1' % l.split('-')[1] ) : + try: + if l.split('-')[0] == hostname and os.system('ps %s > /dev/null 2>&1' % l.split('-')[1] ): # Il ne tourne plus self.remove_lock(res[0]) # delock continue - except : + except: pass r.append(res[0]) return r - def lock(self,item,valeur) : + def lock(self,item,valeur): """ Lock un item avec la valeur valeur, les items possibles peuvent être : aid $ chbre $ mail $ mailAlias $ cannonicalAlias $ mid $ macAddress $ host $ hostAlias $ ipHostNumber @@ -347,59 +347,59 @@ class crans_ldap : valeur = valeur.encode('utf-8') - if not valeur : + if not valeur: # On le lock pas un truc vide return True lock_dn = '%s=%s,%s' % ( item, valeur, self.base_lock ) lockid = '%s-%s' % (hostname, os.getpid() ) modlist = ldap.modlist.addModlist({ 'objectClass' : 'lock' , - 'lockid' : lockid , - item : valeur } ) + 'lockid': lockid , + item: valeur } ) - try : + try: self.conn.add_s(lock_dn,modlist) - except ldap.ALREADY_EXISTS : + except ldap.ALREADY_EXISTS: # Pas de chance, le lock est déja pris - try : + try: res = self.conn.search_s(lock_dn,2,'objectClass=lock')[0] l = res[1]['lockid'][0] - except : l = '%s-1' % hostname - if l != lockid : + except: l = '%s-1' % hostname + if l != lockid: # C'est locké par un autre process que le notre # il tourne encore ? - if l.split('-')[0] == hostname and os.system('ps %s > /dev/null 2>&1' % l.split('-')[1] ) : + if l.split('-')[0] == hostname and os.system('ps %s > /dev/null 2>&1' % l.split('-')[1] ): # Il ne tourne plus self.remove_lock(res[0]) # delock return self.lock(item,valeur) # relock raise EnvironmentError(u'Objet (%s=%s) locké, patienter.' % (item, valeur), l) - else : - if not hasattr(self,'_locks') : + else: + if not hasattr(self,'_locks'): self._locks = [lock_dn] - else : + else: self._locks.append(lock_dn) - def remove_lock(self,lockdn) : + def remove_lock(self,lockdn): """ Destruction d'un lock Destruction de tous les locks si lockdn=*""" # Mettre des verifs ? - if lockdn!='*' : + if lockdn!='*': self.conn.delete_s(lockdn) try: self._locks.remove(lockdn) except: # Pas grave si ca foire, le lock n'y est plus pass - else : + else: locks = self.list_locks() - for l in locks : + for l in locks: self.conn.delete_s(l[0]) - def list_locks(self) : + def list_locks(self): """ Liste les locks """ return self.conn.search_s(self.base_lock,1,'objectClass=lock') - def services_to_restart(self,new=None,args=[],start=0) : + def services_to_restart(self,new=None,args=[],start=0): """ Si new = None retourne la liste des services à redémarrer Si new est fourni et ne commence pas par - ajoute le service à la liste avec les arguments args (args doit être une liste). @@ -408,94 +408,94 @@ class crans_ldap : Si new commence par - supprime le service si son start est plus vieux que maintenant Si new commence par -- supprime dans condition. """ - if new : new = preattr(new)[1] + if new: new = preattr(new)[1] # Quels services sont déjà à redémarrer ? - serv = {} # { service : [ arguments ] } - serv_dates = {} # { service : [ dates de restart ] } + serv = {} # { service: [ arguments ] } + serv_dates = {} # { service: [ dates de restart ] } services = [] - for s in self.conn.search_s(self.base_services,1,'objectClass=service') : + for s in self.conn.search_s(self.base_services,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 + if not new: return services # Effacement d'un service - if new[0] == '-' : - if new[1] == '-' : + if new[0] == '-': + if new[1] == '-': # Double -- on enlève quelque soit la date remove_dn='cn=%s,%s' % ( new[2:], self.base_services ) - else : + else: # On enlève uniquement si la date est passée remove_dn='cn=%s,%s' % ( new[1:], self.base_services ) - if not serv.has_key(new[1:]) : + 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) : + for date in serv_dates[new[1:]]: + if time.time() < int(date): keep_date.append(date) - if keep_date : - self.conn.modify_s(remove_dn,ldap.modlist.modifyModlist({'start' : serv_dates[new[1:]]}, { 'start' : keep_date })) + if keep_date: + self.conn.modify_s(remove_dn,ldap.modlist.modifyModlist({'start': serv_dates[new[1:]]}, { 'start': keep_date })) remove_dn=None - if remove_dn : + if remove_dn: # Supression - try : self.conn.delete_s(remove_dn) - except : pass + try: self.conn.delete_s(remove_dn) + except: pass # Si n'existe pas => Erreur mais le résultat est la. return serv_dn = 'cn=%s,%s' % ( new, self.base_services ) # Petite fonction à appliquer aux arguments - if type(args) == str : args = [ args ] + if type(args) == str: args = [ args ] args=map(lambda x:preattr(x)[1] ,args) - if type(start) == int : start = [ start ] + if type(start) == int: start = [ start ] start=map(lambda x:preattr(x)[1] ,start) - if new in serv.keys() : + if new in serv.keys(): modlist = [] new_args = [] # Nouveaux arguments ? - for arg in args : - if arg not in serv[new] : + 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 }) + 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] : + 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 new_date: + modlist += ldap.modlist.modifyModlist({'start': serv_dates[new]}, { 'start': serv_dates[new] + new_date }) - if modlist : - try : + if modlist: + try: self.conn.modify_s(serv_dn,modlist) - except ldap.TYPE_OR_VALUE_EXISTS : + except ldap.TYPE_OR_VALUE_EXISTS: # Pas grave pass # else rien à faire - else : + else: # Entrée non présente -> ajout - modlist = ldap.modlist.addModlist({ 'objectClass' : 'service' , - 'cn' : new , - 'args' : args , - 'start' : start } ) - try : + modlist = ldap.modlist.addModlist({ 'objectClass': 'service' , + 'cn': new , + 'args': args , + 'start': start } ) + try: self.conn.add_s(serv_dn,modlist) - except ldap.ALREADY_EXISTS : + except ldap.ALREADY_EXISTS: # Existe déja => rien à faire pass - def search(self,expression,mode='') : + def search(self,expression,mode=''): """ Recherche dans la base LDAP, expression est une chaîne : une expression : champ1=expr1 champ2=expr2 champ3!=expr3.... @@ -503,39 +503,39 @@ class crans_ldap : Si mode ='w' les instances crées seront en mode d'écriture """ - if type(expression)==str : + if type(expression)==str: # Transformation de l'expression en utf-8 expression = unicode(expression,'iso-8859-15').encode('utf-8') - elif type(expression)==unicode : + elif type(expression)==unicode: expression = expression.encode('utf-8') - else : + else: raise TypeError(u'Chaine attendue') - if not expression : + if not expression: return [] # Il faut un filtre par type d'objet de la base filtres = self.auto_search_champs.keys() - result={'adherent' : [], 'machine' : [], 'club' : []} + result={'adherent': [], 'machine': [], 'club': []} # Fonction utile - def build_filtre(champ,expr,neg=0) : + def build_filtre(champ,expr,neg=0): """ Retourne une chaine pour recherche dans la base LDAP du style (champ=expr) en adaptant les valeurs de expr au champ - si neg = 1 : retourne le négatif : (!(champ=expr))""" + si neg = 1: retourne le négatif : (!(champ=expr))""" el = '' - if champ in [ 'host', 'hostAlias' ] : - if expr[-1] == '*' : + if champ in [ 'host', 'hostAlias' ]: + if expr[-1] == '*': el = '(%s=%s)' % (champ, expr) - elif expr.find('.')==-1 : + elif expr.find('.')==-1: el = '(%s=%s.*)' % ( champ, expr) - else : + else: el = '(%s=%s*)' % ( champ, expr) - elif champ == 'macAddress' : + elif champ == 'macAddress': # Formatage adresse mac try: el = '(macAddress=%s)' % format_mac(expr) - except : pass - elif champ == 'paiement' and expr == 'ok' : + except: pass + elif champ == 'paiement' and expr == 'ok': # Paiement donnant droit à une connexion maintenant ? # il doit avoir payé pour # l'année en cours ou pour l'année précédente @@ -544,21 +544,21 @@ class crans_ldap : # Dans tous les cas, pour un adhérent, le paiement est considéré non ok # s'il n'a pas fourni sa carte d'etudiant alors que l'on est desormais # en periode de bloquage definifif (cf config.py). - if localtime()[1] == 9 : + if localtime()[1] == 9: # Pour septembre paiement année précédente ok el = "(|(paiement=%s)(paiement=%s))" % (int(ann_scol), int(ann_scol)-1) - else : + else: el = "(paiement=%s)" % (int(ann_scol),) # Doit-on bloquer en cas de manque de la carte d'etudiant ? if config.bl_carte_et_definitif: el = "(&(|(carteEtudiant=%s)(objectClass=club))%s)" % (int(ann_scol), el) - else : + else: # Cas général el = '(%s=%s)' % (champ, expr) - if neg : el = '(!%s)' % el + if neg: el = '(!%s)' % el return el - if expression.find('=')!=-1 : + if expression.find('=')!=-1: #### Recherche avec conditions explicites ## Construction des filtres @@ -567,126 +567,126 @@ class crans_ldap : filtre_cond={} # Stokage si filtre avec condition (ne comporte pas que des *) filtre_tout=1 # Passse à 0 si au moins une condition - for i in filtres : + for i in filtres: filtre[i]='(&' filtre_cond[i] = 0 conds = expression.split('&') # Test de l'expression de recherche et classement par filtres - for cond in conds : + for cond in conds: neg = 0 - try : + try: champ, expr = cond.strip().split('=') - if champ[-1] == '!' : + if champ[-1] == '!': # Négation pour se champ champ = champ[:-1] neg = 1 - except : + except: raise ValueError(u'Syntaxe de recherche invalide.') # transformation de certains champs champ = self.trans.get(champ,champ) - if expr=='' : expr='*' + if expr=='': expr='*' ok = 0 # Construction du filtre - for i in filtres : - if champ in self.auto_search_champs[i] + self.non_auto_search_champs[i] : + for i in filtres: + if champ in self.auto_search_champs[i] + self.non_auto_search_champs[i]: filtre[i] += build_filtre(champ,expr,neg) ok = 1 - if expr!='*' or neg : + if expr!='*' or neg: filtre_cond[i] = 1 filtre_tout=0 - if not ok : + if not ok: raise ValueError(u'Champ de recherche inconnu (%s)'% champ ) ## Recherche avec chacun des filtres r={} # contiendra les réponses par filtre - for i in filtres : - if (filtre_tout and filtre[i]!='(&' ) or filtre_cond[i] : + for i in filtres: + if (filtre_tout and filtre[i]!='(&' ) or filtre_cond[i]: # Filtre valide #filtre[i] += ')' filtre[i] += '(objectClass=%s))' % i r[i] = self.conn.search_s(self.base_dn,self.scope[i],filtre[i]) - else : + else: r[i] = None ## On a alors une liste de résultats - ## r = { categorie1 : [ (result1), (result2), ...] , ... } + ## r = { categorie1: [ (result1), (result2), ...] , ... } # Traitement - if not r['machine'] and not r['adherent'] and not r['club'] : + if not r['machine'] and not r['adherent'] and not r['club']: # Pas de réponses return result - elif len(conds) == 1 : + elif len(conds) == 1: # Filtre sur un seul champ # => on retourne tout - for i in filtres : - if not r[i] : continue - for res in r[i] : + for i in filtres: + if not r[i]: continue + for res in r[i]: result[i].append(globals()[i](res,mode,self.conn)) - elif not r['adherent'] and not r['club'] : + elif not r['adherent'] and not r['club']: # Il n'y avait seulement un filtre machine # => on retourne uniquement les machines trouvées - for m in r['machine'] : + for m in r['machine']: result['machine'].append(machine(m,mode,self.conn) ) - elif not r['machine'] : + elif not r['machine']: # Il n'y avait pas de filtre machine # => on retourne uniquement les adhérents - if r['adherent'] : - for a in r['adherent'] : + if r['adherent']: + for a in r['adherent']: result['adherent'].append(adherent(a,mode,self.conn) ) - if r['club'] : - for a in r['club'] : + if r['club']: + for a in r['club']: result['club'].append(club(a,mode,self.conn) ) - else : + else: # Il faut croiser les résultats machine et propriétaire # Traitement des machines mach_adh = [] # liste de dn d'adhérents et de clubs - for res in r['machine'] : + for res in r['machine']: dn = string.join(res[0].split(',')[-4:],',') - if dn[:3] != 'aid' and dn[:3] != 'cid' : continue - if dn not in mach_adh : + if dn[:3] != 'aid' and dn[:3] != 'cid': continue + if dn not in mach_adh: mach_adh.append(dn) # Croisement bons_dn = [] # liste des dn d'adhérents qui correspondent aux critères - if r['adherent'] : - for a in r['adherent'] : - if a[0] in mach_adh and not a[0] in bons_dn : + if r['adherent']: + for a in r['adherent']: + if a[0] in mach_adh and not a[0] in bons_dn: bons_dn.append(a[0]) result['adherent'].append(adherent(a,mode,self.conn) ) - if r['club'] : - for a in r['club'] : - if a[0] in mach_adh and not a[0] in bons_dn : + if r['club']: + for a in r['club']: + if a[0] in mach_adh and not a[0] in bons_dn: bons_dn.append(a[0]) result['club'].append(club(a,mode,self.conn) ) # Maintenant c'est au tour des bonnes machines bons_dn2 = [] - for a in r['machine'] : + for a in r['machine']: dn = string.join(a[0].split(',')[-4:],',') - if dn in bons_dn and not a[0] in bons_dn2 : + if dn in bons_dn and not a[0] in bons_dn2: bons_dn2.append(dn) result['machine'].append(machine(a,mode,self.conn) ) - else : + else: ### Recherche d'une chaine sur tous les champs - conv = { 'machine' : machine , 'club' : club, 'adherent' : adherent } + conv = { 'machine': machine , 'club': club, 'adherent': adherent } - for i in filtres : + for i in filtres: cl = conv[i] # Construction du filtre filtre = '(&(|' - for champ in self.auto_search_champs[i] : + for champ in self.auto_search_champs[i]: filtre += build_filtre(champ,expression) filtre+=')(objectClass=%s))' %i # Recherche - for r in self.conn.search_s(self.base_dn,self.scope[i],filtre) : + for r in self.conn.search_s(self.base_dn,self.scope[i],filtre): result[i].append( cl(r,mode,self.conn) ) return result @@ -697,7 +697,7 @@ class crans_ldap : Cela affiche des trucs et des bidules si graphic est à True.""" if graphic: from affich_tools import anim, cprint, OK - if not self.__machines : + if not self.__machines: # Récolte des données if graphic: cprint('Lecture base LDAP','gras') # Machines de l'assoce @@ -708,10 +708,10 @@ class crans_ldap : base = self.search('paiement=ok') base = base['adherent'] + base['club'] if graphic: a = anim('\ttri machines',len(base)) - for adh in base : + for adh in base: if graphic: a.cycle() # Adhérent ayant payé l'année en cours - if 'bloq' in adh.blacklist_actif() : + if 'bloq' in adh.blacklist_actif(): # Adhérent ignoré continue self.__machines += adh.machines() @@ -722,19 +722,19 @@ class crans_ldap : ############################################################################# -class base_classes_crans(crans_ldap) : +class base_classes_crans(crans_ldap): """ Méthodes de base des classes machines, et base_proprietaire """ def id(self): """ Retourne la valeur de l'attribu caractéristique de la classe (aid,mid,cid)""" - try : + try: s = self.dn.split(',')[0].split('=') - if s[0] == self.idn : + if s[0] == self.idn: return s[1] - except : + except: return '' - def blacklist_actif(self) : + def blacklist_actif(self): """ Vérifie si l'instance courante est blacklistée. Retourne les sanctions en cours (liste) @@ -742,7 +742,7 @@ class base_classes_crans(crans_ldap) : """ return self.blacklist_all()[0].keys() - def blacklist_all(self) : + def blacklist_all(self): """ Vérifie si l'instance courante est blacklistée ou a été blacklistée. Retourne les sanctions en cours sous forme de dictionnaire avec comme clef @@ -753,7 +753,7 @@ class base_classes_crans(crans_ldap) : """ bl_liste = self._data.get('blacklist',[]) - if 'machine' in self._data['objectClass'] : + if 'machine' in self._data['objectClass']: # Il faut aussi regarder la blackliste du propriétaire p = self.proprietaire() bl_liste += p.blacklist() @@ -761,9 +761,9 @@ class base_classes_crans(crans_ldap) : actifs = {} inactifs = {} - for sanction in bl_liste : + for sanction in bl_liste: s = sanction.split(',')[2] - if is_actif(sanction) : + if is_actif(sanction): if not s in actifs: actifs[s] = [] actifs[s].append((sanction.split(',')[0], @@ -775,10 +775,10 @@ class base_classes_crans(crans_ldap) : sanction.split(',')[1])) return (actifs, inactifs) - def blacklist(self,new=None) : + def blacklist(self,new=None): """ Blacklistage de la ou de toutes la machines du propriétaire - new est une liste de 4 termes : + new est une liste de 4 termes: [ debut_sanction , fin_sanction, sanction, commentaire ] début et fin doivent être sous la forme donnée par date_format pour un début ou fin immédiate mettre now @@ -788,43 +788,43 @@ class base_classes_crans(crans_ldap) : ( index dans blacklist à modifier , nouvelle liste ) l'index est celui obtenu dans la liste retournée par blacklist() """ - if not self._data.has_key('blacklist') : + if not self._data.has_key('blacklist'): self._data['blacklist']=[] liste = list(self._data['blacklist']) - if new==None : return map(decode,liste) + if new==None: return map(decode,liste) - if type(new)==tuple : + if type(new)==tuple: # Modif index = new[0] new = new[1] - if new=='' : + if new=='': liste.pop(index) self._set('blacklist',liste) return liste - else : + else: index = -1 - if type(new)!=list or len(new)!=4 : + if type(new)!=list or len(new)!=4: raise TypeError # Verif que les dates sont OK - if new[0] == 'now' : + if new[0] == 'now': new[0] = time.strftime(date_format) debut=0 - else : - try : debut=int(time.mktime(time.strptime(new[0],date_format))) - except : raise ValueError(u'Date de début blacklist invalide') + else: + try: debut=int(time.mktime(time.strptime(new[0],date_format))) + except: raise ValueError(u'Date de début blacklist invalide') - if new[1] == 'now' : + if new[1] == 'now': new[1] = time.strftime(date_format) fin=0 - elif new[1]!='-' : - try : fin=int(time.mktime(time.strptime(new[1],date_format))) - except : raise ValueError(u'Date de fin blacklist invalide') - else : + elif new[1]!='-': + try: fin=int(time.mktime(time.strptime(new[1],date_format))) + except: raise ValueError(u'Date de fin blacklist invalide') + else: fin = -1 - if debut == fin : + if debut == fin: raise ValueError(u'Dates de début et fin identiques') # On d-Aépasse la fin de sanction d'1min pour être sur quelle périmé.-b @@ -833,86 +833,86 @@ class base_classes_crans(crans_ldap) : new_c = ','.join(new) new_c = preattr(new_c)[1] - if index!=-1 : + if index!=-1: liste[index] = new_c - else : + else: liste = liste + [ new_c ] - if self._data['blacklist'] != liste : + if self._data['blacklist'] != liste: self._data['blacklist']=liste self.modifs.append('blacklist_' + new[2]) - if not hasattr(self,"_blacklist_restart") : + if not hasattr(self,"_blacklist_restart"): self._blacklist_restart={} - if not self._blacklist_restart.has_key(new[2]) : + if not self._blacklist_restart.has_key(new[2]): self._blacklist_restart[new[2]] = [ debut, fin ] - else : - if debut not in self._blacklist_restart[new[2]] : + else: + if debut not in self._blacklist_restart[new[2]]: self._blacklist_restart[new[2]].append(debut) - if fin!=-1 and fin not in self._blacklist_restart[new[2]] : + if fin!=-1 and fin not in self._blacklist_restart[new[2]]: self._blacklist_restart[new[2]].append(fin) return liste - def restore(self) : + def restore(self): """ Restore les données à l'état initial """ self._data = self._init_data.copy() self.modifs=[] - def historique(self) : + def historique(self): """ Retourne l'historique de l'objet """ return map(decode,self._data.get('historique',[])) - def info(self,new=None) : + def info(self,new=None): """ Pour ajouter une remarque new doit être la chaîne représentant la remarque à ajouter - Pour modifier new doit être une liste de la forme : + Pour modifier new doit être une liste de la forme: [ index de la remarque à modifier , nouvelle remarque ] l'index est celui obtenu dans la liste retournée par info() """ - if not self._data.has_key('info') : + if not self._data.has_key('info'): self._data['info']=[] liste = list(self._data['info']) - if new==None : return map(decode,liste) + if new==None: return map(decode,liste) - if type(new)==list : + if type(new)==list: # Modif index = new[0] l, new = preattr(new[1]) - if not new : + if not new: # Supression remarque liste.pop(index) - else : + else: # Modif remarque liste[index]=new - elif type(new)==str : + elif type(new)==str: # Remarque supplémentaire l, new = preattr(new) - if not new : + if not new: # On ajoute pas de remarque vide return liste # Ajout à la liste liste = liste + [ new ] - else : + else: raise TypeError self._set('info',liste) return liste - def _save(self) : + def _save(self): """ Sauvegarde dans la base LDAP """ - if not self.modifs : + if not self.modifs: # Rien à faire return [] - if not self.dn : + if not self.dn: # Enregistrement à placer en tête de base self.dn = self.base_dn # Construction de l'historique - if not self._init_data : + if not self._init_data: modif='inscription' - else : + else: ### ON NE TOUCHE PAS A SELF.MODIFS, IL EST UTILISÉ PLUS LOIN !!!!!!! modif=', '.join(self.modifs) if "chbre" in self.modifs: @@ -921,9 +921,9 @@ class base_classes_crans(crans_ldap) : if "solde" in self.modifs: diff = float(self._init_data.get('solde',[0])[0]) - float(self._data.get('solde',[0])[0]) - if diff > 0 : + if diff > 0: modif = modif.replace("solde", "debit %s Euros" % str(diff) ) - else : + else: modif = modif.replace("solde", "credit %s Euros" % str(-diff) ) if 'droits' in self.modifs: @@ -947,13 +947,13 @@ class base_classes_crans(crans_ldap) : # Suffit-t-il d'ajouter un item au dernier élément de l'historique ? try: - dern = self._data['historique'][-1].split(' : ',2) - if dern[0] == hist : + dern = self._data['historique'][-1].split(': ',2) + if dern[0] == hist: # Même date et même cableur - if modif not in dern[1].split(', ') : + if modif not in dern[1].split(', '): # Qqch de plus de modifié self._data['historique'][-1] = self._data['historique'][-1] + ', ' +modif - else : + else: # Nouvelle entrée # NE PAS UTILISER L'OPERATEUR += ICI sinon self._init_data aussi modififié self._data['historique'] = self._data['historique'] + [ preattr("%s : %s" % ( hist, modif ))[1] ] @@ -961,20 +961,20 @@ class base_classes_crans(crans_ldap) : # Nouvelle inscription self._data['historique'] = [ "%s : %s" % ( hist, modif ) ] - if not self._init_data : + if not self._init_data: ### Nouvel enregistrement # Génération du dn res = self.conn.search_s(self.base_dn,2,'objectClass=%s' % self._data['objectClass'][0],['']) vidn=1 vidns=[] # Liste des dn pris - for r in res : + for r in res: # r=( dn, {} ) r = r[0].split(',')[0] - if r[:4] != '%s=' % self.idn : continue + if r[:4] != '%s=' % self.idn: continue vidns.append(int(r[4:])) # On prend le premier libre - while vidn in vidns : + while vidn in vidns: vidn += 1 self.dn='%s=%s,%s' % (self.idn, vidn, self.dn) @@ -983,27 +983,27 @@ class base_classes_crans(crans_ldap) : # Ecriture modlist = ldap.modlist.addModlist(self._data) self.conn.add_s(self.dn,modlist) - else : + else: ### Modification entrée - if not self._modifiable : + if not self._modifiable: raise RuntimeError(u'Objet non modifiable') modlist = ldap.modlist.modifyModlist(self._init_data,self._data) - try : + try: self.conn.modify_s(self.dn,modlist) - except ldap.TYPE_OR_VALUE_EXISTS , c : + except ldap.TYPE_OR_VALUE_EXISTS , c: champ = c.args[0]['info'].split(':')[0] raise RuntimeError(u'Entrée en double dans le champ %s' % champ) ### Génération de la liste de services à redémarrer # Quasiement tout est traité dans les classes filles. - if hasattr(self,"_blacklist_restart") : - for n,t in self._blacklist_restart.items() : + if hasattr(self,"_blacklist_restart"): + for n,t in self._blacklist_restart.items(): self.services_to_restart("blacklist_%s"%n,[],t) # Reinitialisation self._init_data = self._data.copy() - def _delete(self,dn,comment='') : + def _delete(self,dn,comment=''): """ Sauvegarde puis destruction du dn (et des sous-dn) fourni """ # Commentaires comment = preattr(comment)[1] @@ -1024,29 +1024,29 @@ class base_classes_crans(crans_ldap) : data = self.conn.search_s(dn,2) data.reverse() # Necessaire pour détruire d'abord les sous-dn - for r in data : + for r in data: self.conn.delete_s(r[0]) - try : + try: log = open(config.cimetiere + '/index','a') log.write(index) log.close() - except : + except: pass - def _set(self,champ,val) : + def _set(self,champ,val): """ Met à jour les données de data et modifie modifs si besoin """ if not self._data.has_key(champ) \ - or self._data.has_key(champ) and self._data[champ]!=val : + or self._data.has_key(champ) and self._data[champ]!=val: self._data[champ]=val - if champ not in self.modifs : + if champ not in self.modifs: self.modifs.append(champ) ############################################################################# -class base_proprietaire(base_classes_crans) : +class base_proprietaire(base_classes_crans): """ Méthodes de bases pour les classes adherent et club """ - def __init__(self,data=(),mode='',conn=None) : + def __init__(self,data=(),mode='',conn=None): """ Si data est fourni initialise l'adhérent avec les valeurs données Format de data : tuple comme retourné par une recherche dans la base ldap: @@ -1059,82 +1059,82 @@ class base_proprietaire(base_classes_crans) : conn est une instance de la classe de connexion à la base LDAP """ self.conn = conn - if not self.conn : self.connect() + if not self.conn: self.connect() - if type(data) != tuple : + if type(data) != tuple: raise TypeError self.modifs=[] - if data : + if data: self.dn=data[0] - if mode == 'w' : - try : + if mode == 'w': + try: self.lock(self.idn, self.id()) self._modifiable = 'w' except EnvironmentError , c: self._modifiable = 0 - else : + else: self._modifiable = 0 # Utile pour construire l'instruction LDAP de modif self._init_data = data[1].copy() self._data = data[1] - else : + else: # Propriétaire vide self.dn='' # Génération du reste au moment de l'écriture - self._data={ 'objectClass' : [ self.objectClass ] } + self._data={ 'objectClass': [ self.objectClass ] } self._init_data={} self._modifiable = 'w' - def chsh(self,new=None) : + def chsh(self,new=None): """ Retourne ou change le shell de l'adhérent """ - if new == None : - try : return decode(self._data.get('loginShell',[''])[0]) - except : return '' - else : + if new == None: + try: return decode(self._data.get('loginShell',[''])[0]) + except: return '' + else : new = preattr(new)[1] self._set('loginShell',[new]) return new - def alias(self,new=None) : + def alias(self,new=None): """ Création ou visualisation des alias mail Même sytème d'argument que la méthode info. """ - if not self._data.has_key('mailAlias') : + if not self._data.has_key('mailAlias'): self._data['mailAlias']=[] liste = list(self._data['mailAlias']) - if new==None : + if new==None: return map(decode,liste) - if type(new)==list : + if type(new)==list: # Modif index = new[0] new = new[1] - if new=='' : + if new=='': # Supression alias liste.pop(index) self._set('mailAlias',liste) return liste - else : + else: new = new.replace('@crans.org','') index=-1 # Tests l, new = preattr(new) new = new.lower() - if l<2 : + if l<2: raise ValueError(u"Alias trop court.") for c in new[:]: - if not c in (string.letters + string.digits + '-_.') : + if not c in (string.letters + string.digits + '-_.'): raise ValueError(u"Alias : seuls les caractères alphanumériques, le -, le _ et le . sont autorisés." ) - if new[0] not in string.letters : + if new[0] not in string.letters: raise ValueError(u"Le premier caractère de l'alias doit être alphabétique.") - if mailexist(new) : + if mailexist(new): raise ValueError(u"Alias existant ou correspondand à un compte.") - if index!=-1 : + if index!=-1: liste[index]=new - else : + else: liste = liste + [ new ] # Lock de mailAlias @@ -1143,17 +1143,17 @@ class base_proprietaire(base_classes_crans) : self._set('mailAlias',liste) return liste - def machines(self) : + def machines(self): """ Retourne les machines (instances) appartenant à la classe """ - if self.id() : + if self.id(): res = [] - try : - for r in self.conn.search_s('%s=%s,%s' % ( self.idn,self.id() , self.base_dn ),1,'objectClass=machine') : + try: + for r in self.conn.search_s('%s=%s,%s' % ( self.idn,self.id() , self.base_dn ),1,'objectClass=machine'): res.append(machine(r, self._modifiable,self.conn) ) return res - except : + except: return [] - else : + else: return [] def machines_fixes(self): @@ -1164,30 +1164,30 @@ class base_proprietaire(base_classes_crans) : """ Retourne les machines wifi appartenant à l'instance """ return filter(lambda x: x.ipsec(), self.machines()) - def solde(self, operation=None) : + def solde(self, operation=None): """ Retourne ou modifie le solde d'un propriétaire operation doit être un nombre positif ou négatif (string ou int ou float) """ solde = float(self._data.get('solde',[0])[0]) - if operation==None : + if operation==None: return solde # On effectue une opération - try : + try: new = solde + float(str(operation).replace(',','.')) - except ValueError : + except ValueError: raise ValueError(u"Il faut donner un nombre en argument.") # découvert accepté - if new < config.impression.decouvert : + if new < config.impression.decouvert: raise ValueError(u"Solde minimal atteind, opération non effectuée.") self._set('solde',[str(new)]) return new - def paiement(self,action=None) : + def paiement(self,action=None): """ Action est un entier représentant une année si positif ajoute l'année à la liste @@ -1195,122 +1195,122 @@ class base_proprietaire(base_classes_crans) : """ return self._an('paiement',action) - def delete(self,comment='') : + def delete(self,comment=''): """Destruction du proprietaire""" - for m in self.machines() : + for m in self.machines(): # Destruction machines m.delete(comment) self._delete(self.dn,comment) - try : - if self.compte() : + try: + if self.compte(): args = self._data['uid'][0] + ',' args+= self._data['homeDirectory'][0] self.services_to_restart('del_user',[ args ] ) - except : + except: # Si ne peux avoir de compte pass - def save(self) : + def save(self): """ Enregistre l'adhérent ou le club courant dans la base LDAP Ajoute le mail de bienvenue à la liste des services à redémarrer Retourne une chaîne indiquant les opération effectuées. """ - # Note : un peu trop de fonctions pour un club mais ce n'est pas génant + # Note: un peu trop de fonctions pour un club mais ce n'est pas génant ret ='' - if self._init_data : + if self._init_data: nouveau =0 # Reconfiguration switch si changement de chambre et si machine fixe - if 'chbre' in self.modifs : - for m in self.machines() : - if not m.ipsec() : + if 'chbre' in self.modifs: + for m in self.machines(): + if not m.ipsec(): self.services_to_restart('switch',[self._data['chbre'][0]]) self.services_to_restart('switch',[self._init_data.get('chbre','')[0]]) break - else : + else: nouveau = 1 - if 'chbre' in self.modifs and '????' in [ self._init_data.get("chbre",[''])[0] , self._init_data.get("chbre",[''])[0] ] : + if 'chbre' in self.modifs and '????' in [ self._init_data.get("chbre",[''])[0] , self._init_data.get("chbre",[''])[0] ]: self.services_to_restart('bl_chbre_invalide') # Enregistrement self._save() # Message de sortie - if nouveau : + if nouveau: ret += coul(u"%s inscrit avec succès." % self.Nom(), 'vert') if self.idn !='cid' and self.etudes(1) != "Pers": # Mail de bienvenue self.services_to_restart('mail_bienvenue',[self.mail().encode('iso-8859-15')]) - else : + else: ret += coul(u"Modification %s effectuée avec succès." % self.Nom(), 'vert') # Changements administratifs test_carte = 'carteEtudiant+%s' % ann_scol in self.modifs \ or 'carteEtudiant-%s' % ann_scol in self.modifs - if test_carte and self.machines() : + if test_carte and self.machines(): self.services_to_restart('bl_carte_etudiant') if 'paiement+%s' % ann_scol in self.modifs \ or 'paiement-%s' % ann_scol in self.modifs \ - or ( config.bl_carte_et_definitif and test_carte ) : - for m in self.machines() : + or ( config.bl_carte_et_definitif and test_carte ): + for m in self.machines(): self.services_to_restart('macip',[m.ip()] ) self.services_to_restart('dns') - if m.ipsec() : + if m.ipsec(): self.services_to_restart('conf_wifi_ng') self.services_to_restart('nectaris-dhcp') - else : + else: self.services_to_restart('switch',[self.chbre()]) self.services_to_restart('rouge-dhcp') # Vérification si changement de bât, ce qui obligerai un changement d'IP - if 'chbre' in self.modifs and self.chbre()!='????' : + if 'chbre' in self.modifs and self.chbre()!='????': # Verif si machines avec bonnes ip err = 0 - for m in self.machines() : - if m.ipsec() : + for m in self.machines(): + if m.ipsec(): # Machine Wifi continue # Machine fixe ip = m.ip() - try : + try: # Tentative de changement d'IP de la machine m.ip(ip) except ValueError: # IP invalide, on la change ret += "\nChangement d'IP machine %s : " % m.nom() - try : + try: ret += "%s -> %s" % ( ip, m.ip('') ) m.save() - except Exception, c : + except Exception, c: ret += coul(u'ERREUR : %s' % c.args[0], rouge) err = 1 - if err : ret += '\nEssayer de corriger les erreurs machines en éditant celles-ci.\n' + if err: ret += '\nEssayer de corriger les erreurs machines en éditant celles-ci.\n' # Faut-il créer un compte sur vert ? - if 'compte' in self.modifs : + if 'compte' in self.modifs: ret += u'\nUn compte a été créé :\n login : %s\n' % self.compte() args = self._data['homeDirectory'][0] + ',' args+= self._data['uidNumber'][0] + ',' args+= self._data['uid'][0] self.services_to_restart('home',[ args ]) r = prompt("Attribuer tout de suite un mot de passe ? [O/N]","O") - if r=='O' or r=='o' : + if r=='O' or r=='o': chgpass(self.dn) - else : + else: ret += coul(u' Il faudra penser à attribuer un mot de passe\n','jaune') # Modif des droits ? - if 'droits' in self.modifs : + if 'droits' in self.modifs: self.services_to_restart('droits') self.services_to_restart('mail_modif',['uid=%s' % self._data['uid'][0]]) @@ -1319,38 +1319,38 @@ class base_proprietaire(base_classes_crans) : return ret - def _an(self,champ,action) : + def _an(self,champ,action): """ Champ est un champ contenant une liste d'entiers Action est un entier représentant une année si positif ajoute l'année à la liste si négatif le supprime """ - if not self._data.has_key(champ) : + if not self._data.has_key(champ): trans=[] - else : + else: # On va travailler sur une liste d'entiers trans = map(int,self._data[champ]) - if action==None : + if action==None: return trans - if type(action)!=int : raise TypeError + if type(action)!=int: raise TypeError - if action>0 and action not in trans : + if action>0 and action not in trans: trans.append(action) act = '%s+%d' % (champ,action) - if act not in self.modifs : + if act not in self.modifs: self.modifs.append(act) - elif action<0 and -action in trans : + elif action<0 and -action in trans: trans.remove(-action) act = '%s%s' % (champ,action) - if act not in self.modifs : + if act not in self.modifs: self.modifs.append(act) trans.sort() new=[] - for an in trans : + for an in trans: new.append('%d' % an ) self._data[champ] = new @@ -1359,73 +1359,73 @@ class base_proprietaire(base_classes_crans) : ############################################################################# -class adherent(base_proprietaire) : +class adherent(base_proprietaire): """ Classe de définition d'un adhérent """ objectClass = 'adherent' idn = 'aid' ### Méthodes Nom utilisée lors de l'affichage des propriétés ### (commune avec les classes crans et club) - def Nom(self) : + def Nom(self): """ Retourne prenom nom """ return "%s %s" % ( self.prenom() , self.nom() ) - def nom(self,new=None) : + def nom(self,new=None): return self.__nom_prenom('nom',new) - def prenom(self,new=None) : + def prenom(self,new=None): return self.__nom_prenom('prenom',new) - def __nom_prenom(self,champ,new) : - if new==None : + def __nom_prenom(self,champ,new): + if new==None: return decode(self._data.get(champ,[''])[0]) l, new = preattr(new) new = new.capitalize() - for c in new[:] : - if c not in (string.letters + '- ' + preattr(accents)[1] ) : + for c in new[:]: + if c not in (string.letters + '- ' + preattr(accents)[1] ): raise ValueError(u"Seuls les caractères alphabétiques, l'espace et le - sont permis dans %s." % champ.replace(u'e',u'é') ) - if l<2 : + if l<2: raise ValueError(u"%s trop court." % champ.capitalize().replace(u'e',u'é')) - if new[0] not in string.letters : + if new[0] not in string.letters: raise ValueError(u"Le premier caractère du %s doit être une lettre" % champ.replace(u'e',u'é') ) self._set(champ,[new]) return new - def tel(self,new=None) : - if new==None : + def tel(self,new=None): + if new==None: return self._data.get('tel',[''])[0] - if new != 'inconnu' : + if new != 'inconnu': l, new = preattr(new) - if not new.isdigit() or l<6 or l>15 : + if not new.isdigit() or l<6 or l>15: raise ValueError(u"Numéro de téléphone incorrect (il doit comporter uniquement des chiffres).") self._set('tel',[new]) return new - def chbre(self,new=None) : + def chbre(self,new=None): """ Défini la chambre d'un adhérent, EXT pour personne extérieure au campus """ - if new==None : + if new==None: return decode(self._data.get('chbre',[''])[0]) l, new = preattr(new) - if l==0 : + if l==0: raise ValueError(u"Chambre incorrecte.") - if new.upper() == 'EXT' : + if new.upper() == 'EXT': # N'est pas ou plus sur le campus # Machine fixe ? - # for m in self.machines() : - # if not m.ipsec() : + # for m in self.machines(): + # if not m.ipsec(): # raise ValueError(u'Un adhérent en dehors du campus ne doit pas avoir de machine fixe.') self._set('chbre',['EXT']) return 'EXT' - elif new.upper() == '????' : + elif new.upper() == '????': # On ne sait pas ou est l'adhérent self._set('chbre',['????']) return '????' @@ -1433,38 +1433,38 @@ class adherent(base_proprietaire) : new = new.capitalize() bat = new[0].lower() - if bat in annuaires.chbre_prises.keys() : + if bat in annuaires.chbre_prises.keys(): # On a la liste des chambres chbres = annuaires.chbre_prises[bat].keys() - if new[1:] not in chbres or len(new)<4 or not new[1:4].isdigit() : + if new[1:] not in chbres or len(new)<4 or not new[1:4].isdigit(): chbres.sort() aide = u"Chambre inconnue dans le batiment, les chambres valides sont :" a=0 - for c in chbres : - if len(c)>=3 and not c[:3].isdigit() : + for c in chbres: + if len(c)>=3 and not c[:3].isdigit(): # C'est un local club continue - if int(a/14)>int((a-1)/14) : aide += '\n ' - if c[0]!='X' : + if int(a/14)>int((a-1)/14): aide += '\n ' + if c[0]!='X': aide += c.ljust(5) a=a+1 aide += u'\n' aide += u" " + annuaires.aide.get(bat,'') raise ValueError(aide) - else : + else: raise ValueError(u'Bâtiment inconnu.') # La chambre est valide, est-elle déja occupée ? test = self.exist('chbre=%s' % new) - if test : + if test: search = test[0].split(',')[0] - if search.split('=')[0]!='aid' : + if search.split('=')[0]!='aid': raise ValueError(u'Chambre déjà occupée.') adh = self.search(search,self._modifiable)['adherent'] - if len(adh) != 1 : + if len(adh) != 1: raise ValueError(u'Chambre déjà occupée.') - else : + else: raise ValueError(u'Chambre déjà occupée.',adh[0]) # Lock de la chambre @@ -1477,33 +1477,33 @@ class adherent(base_proprietaire) : """ Défini l'adresse pour les personnes extérieures (dont la chambre = EXT) L'adresse est une liste de 4 éléments : numero, rue, code postal, ville """ - if new==None : - if self.chbre() != 'EXT' : + if new==None: + if self.chbre() != 'EXT': # Personne sur le campus return [u'',u'',u'',u''] - else : + else: addr = self._data.get('postalAddress', ['','','',''])[:4] if len(addr) < 4: addr = addr + ['']*(4-len(addr)) return map(decode,addr) - if type(new)!=list and len(new)!=4 : + if type(new)!=list and len(new)!=4: raise TypeError l_min = [ 2, 0, 5, 2 ] - for i in range(0,4) : + for i in range(0,4): l, new[i] = preattr(new[i]) - if l < l_min[i] : raise ValueError(u"Adresse incorrecte.") + if l < l_min[i]: raise ValueError(u"Adresse incorrecte.") # Correction si necessaire - if not new[1] : + if not new[1]: new[1] = ' ' self._set('postalAddress',new) return new - def mail(self,new=None) : - if new==None : + def mail(self,new=None): + if new==None: return decode(self._data.get('mail',[''])[0]) l, new = preattr(new) @@ -1520,16 +1520,16 @@ class adherent(base_proprietaire) : # @ pas en premier ni juste avant le dernier . if new.count('@')!=1 \ or not ( l-b==4 or l-b==3) \ - or a<1 or b-a<2 : + or a<1 or b-a<2: raise ValueError(u"Adresse mail incorrecte.") # Pas de caractèrs bizarres for l in new[:]: - if not l in (string.lowercase + string.digits + '-_.@') : + if not l in (string.lowercase + string.digits + '-_.@'): raise ValueError(u"Caractère interdits dans l'adresse mail (%s)." % l) # Pour les vicieux - if sre.match('.*crans.(org|ens-cachan.fr)$',new) : + if sre.match('.*crans.(org|ens-cachan.fr)$',new): raise ValueError(u"Adresse mail @crans interdite ici") self._set('mail',[new]) @@ -1537,36 +1537,36 @@ class adherent(base_proprietaire) : # Il ne doit pas y avoir de compte self._data['objectClass'] = [ 'adherent' ] - for c in [ 'uid', 'cn', 'shadowLastChange', 'shadowMax', 'shadowWarning', 'loginShell', 'userPassword', 'uidNumber', 'gidNumber', 'homeDirectory', 'gecos', 'droits','mailAlias', 'cannonicalAlias' ] : + for c in [ 'uid', 'cn', 'shadowLastChange', 'shadowMax', 'shadowWarning', 'loginShell', 'userPassword', 'uidNumber', 'gidNumber', 'homeDirectory', 'gecos', 'droits','mailAlias', 'cannonicalAlias' ]: try: self._data.pop(c) - except : pass + except: pass return new - def etudes(self,index_or_new) : + def etudes(self,index_or_new): """ Retourne l'un des 3 champs études (selon index_or_new si entier) """ - if type(index_or_new)==int : + if type(index_or_new)==int: if self._data.has_key('etudes'): return decode(self._data['etudes'][index_or_new]) else: return '' - if type(index_or_new)!=list : + if type(index_or_new)!=list: raise TypeError - if not self._data.has_key('etudes') : + if not self._data.has_key('etudes'): self._data['etudes']=['','',''] # Pas grand chose à faire à part vérifier que ce sont bien des chaines - if len(index_or_new)!=3 : + if len(index_or_new)!=3: raise ValueError(u"Format études non valides.") new = ['','',''] - for i in range(0,3) : + for i in range(0,3): n = preattr(index_or_new[i])[1] - if n in new or n=='' : + if n in new or n=='': raise ValueError(u"Etudes non valides.") new[i] = n @@ -1574,7 +1574,7 @@ class adherent(base_proprietaire) : return new - def carteEtudiant(self,action=None) : + def carteEtudiant(self,action=None): """ Action est un entier représentant une année si positif ajoute l'année à la liste @@ -1582,7 +1582,7 @@ class adherent(base_proprietaire) : """ return self._an('carteEtudiant',action) - def checkPassword(self, password) : + def checkPassword(self, password): """Vérifie le mot de passe de l'adhérent""" anon = ldap.initialize(uri) try: @@ -1595,16 +1595,16 @@ class adherent(base_proprietaire) : return True - def compte(self,login=None,uidNumber=0,hash_pass='',shell=config.login_shell) : + def compte(self,login=None,uidNumber=0,hash_pass='',shell=config.login_shell): """ Création d'un compte à un adhérent (la création se fait après l'écriture dans la base par la méthode save) Si login = None, retourne le compte de l'adhérent """ - if not login : - if self.mail().find('@') != -1 : + if not login: + if self.mail().find('@') != -1: return '' - else : + else: return self.mail() # Supression des accents et espaces @@ -1613,39 +1613,39 @@ class adherent(base_proprietaire) : l, login = preattr(login) login = login.lower() - if 'posixAccount' in self._data['objectClass'] : - if login != self._data['uid'] : + if 'posixAccount' in self._data['objectClass']: + if login != self._data['uid']: # A déja un compte raise ValueError(u"L'adhérent à déjà un compte. Login : %s" % self._data['uid'][0]) - else : + else: return login for c in login[:]: - if not c in (string.letters + '-') : + if not c in (string.letters + '-'): raise ValueError(u"Seuls les caractères alphabétiques non accentués et le - sont autorisés dans le login.") - if l<2 : + if l<2: raise ValueError(u"Login trop court.") - if l>config.maxlen_login : + if l>config.maxlen_login: raise ValueError(u"Login trop long.") - if login[0]=='-' : + if login[0]=='-': raise ValueError(u"- interdit en première position.") - if mailexist(login) : + if mailexist(login): raise ValueError(u"Login existant ou correspondant à un alias mail.",1) home = '/home/' + login - if os.path.exists(home) : + if os.path.exists(home): raise ValueError(u'Création du compte impossible : home existant',1) # Lock du mail self.lock('mail',login) self._data['mail']= [ login ] - if not 'compte' in self.modifs : + if not 'compte' in self.modifs: self.modifs.append('compte') # Création de l'alias cannonique - if self.nom() and self.prenom() : + if self.nom() and self.prenom(): a = '%s.%s' % (self.prenom().capitalize(), self.nom().capitalize()) self.cannonical_alias(a) @@ -1656,19 +1656,19 @@ class adherent(base_proprietaire) : #self._data['shadowMax'] = [ '99999'] #self._data['shadowWarning'] = [ '7' ] self._data['loginShell' ] = [ shell ] - if hash_pass : + if hash_pass: self._data['userPassword'] = [ hash_pass ] - if uidNumber : - if self.exist('(uidNumber=%s)' % uidNumber) : + if uidNumber: + if self.exist('(uidNumber=%s)' % uidNumber): raise ValueError(u'uidNumber pris') - else : + else: uidNumber = 1000 - while self.exist('(uidNumber=%s)' % uidNumber) : + while self.exist('(uidNumber=%s)' % uidNumber): uidNumber += 1 - try : + try: self.lock('uidNumber',str(uidNumber)) - except : + except: # Quelqu'un nous a piqué l'uid que l'on venait de choisir ! return self.compte(login,uidNumber,hash_pass,shell) @@ -1680,16 +1680,16 @@ class adherent(base_proprietaire) : return decode(login) - def cannonical_alias(self,new=None) : + def cannonical_alias(self,new=None): """ Retourne ou défini l'alias canonique""" - if new == None : - try : return decode(self._data['cannonicalAlias'][0]) - except : return '' - else : + if new == None: + try: return decode(self._data['cannonicalAlias'][0]) + except: return '' + else : a = strip_accents(new) a = preattr(a)[1] - if not mailexist(a) : + if not mailexist(a): # Attribution de l'alias, sinon on passe # Lock de cannonicalAlias @@ -1699,128 +1699,128 @@ class adherent(base_proprietaire) : self._set('cannonicalAlias',[a]) return a - def droits(self,droits=None) : + def droits(self,droits=None): """ droits est la liste des droits à donner à l'utilisateur """ - if droits==None : + if droits==None: return map(decode,self._data.get('droits',[])) - if not isadm : + if not isadm: raise EnvironmentError(u'Il faut être administrateur pour effectuer cette opération.') - if type(droits)!=list : + if type(droits)!=list: raise TypeError(u'Une liste est attendue') new = [] - for droit in droits : - if droit == '' : continue + for droit in droits: + if droit == '': continue droit = unicode(droit.strip(),'iso-8859-15') - if droit not in droits_possibles : + if droit not in droits_possibles: raise ValueError(u'Droit %s incorrect' % droit) new.append(droit.encode('utf-8')) - if new != self._data.get('droits',[]) : + if new != self._data.get('droits',[]): self._set('droits',new) return new -class club(base_proprietaire) : +class club(base_proprietaire): """ Classe de définition d'un club """ idn = 'cid' objectClass = 'club' - def Nom(self,new=None) : + def Nom(self,new=None): """ Défini ou retourne le nom du club """ - if new==None : + if new==None: return decode(self._data.get('nom',[''])[0]) l, new = preattr(new) new = new.capitalize() - if l<2 : + if l<2: raise ValueError(u"Nom trop court.") self._set('nom',[new]) return new - def etudes(*args) : + def etudes(*args): """ Etudes bidon pour club """ return u'N/A' - def nom(self) : + def nom(self): """ Retourne le nom du club, utilisé lors de la destruction """ return strip_accents(self.Nom()) - def carteEtudiant(self,pd=None) : + def carteEtudiant(self,pd=None): return [ ann_scol ] - def responsable(self,adher=None) : + def responsable(self,adher=None): """ Responsable du club, adher doit être une instance de la classe adhérent """ - if adher==None : + if adher==None: aid = decode(self._data.get('responsable',[''])[0]) - if aid : + if aid: return self.search('aid=%s' % aid)['adherent'][0] - else : return '' + else: return '' - if adher.__class__ != adherent : + if adher.__class__ != adherent: raise ValueError - if not adher.id() : + if not adher.id(): raise AttributeError(u'Adhérent invalide') self._set('responsable',[adher.id()]) return adher - def chbre(self,new=None) : + def chbre(self,new=None): """ Défini le local du club new doit être une des clefs de l'annuaire locaux_clubs""" - if new==None : + if new==None: return decode(self._data.get('chbre',[''])[0]) annu = annuaires.locaux_clubs() - if new not in annu.keys() : + if new not in annu.keys(): raise ValueError(u'Local invalide',annu) self._set('chbre',[new]) return new - def local(self) : + def local(self): """ Retourne le local à partir de la chambre enregistrée et de la conversion avec l'annuaire locaux_clubs """ annu = annuaires.locaux_clubs() return decode(annu.get(self.chbre(),'')) - def compte(self,login=None) : + def compte(self,login=None): """ Créé un compte au club sur vert""" - if login==None : + if login==None: return self._data.get('uid',[''])[0] # Génération du login : club- login = login.lower() - if not sre.match('^club-', login) : + if not sre.match('^club-', login): login = 'club-' + login - for l in login : + for l in login: if l not in string.letters + '-': raise ValueError('Caractère %s interdit dans le login.' % l) login = preattr(login)[1] - if 'posixAccount' in self._data['objectClass'] : - if login != self._data['uid'] : + if 'posixAccount' in self._data['objectClass']: + if login != self._data['uid']: # A déja un compte raise ValueError(u"Le club à déjà un compte. Login : %s" % self._data['uid'][0]) - else : + else: return login - if mailexist(login) and not os.system('/usr/sbin/list_lists | grep -qi %s' % login) : + if mailexist(login) and not os.system('/usr/sbin/list_lists | grep -qi %s' % login): # la 2ème vérif est pour vérifier que ce n'est pas la ML du club raise ValueError(u"Login existant ou correspondant à un alias mail.",1) home = '/home/' + login.replace('-','/',1) - if os.path.exists(home) : + if os.path.exists(home): raise ValueError(u'Création du compte impossible : home existant',1) # Lock du mail self.lock('mail',login) - if not 'compte' in self.modifs : + if not 'compte' in self.modifs: self.modifs.append('compte') self._data['objectClass'] = [ 'club', 'posixAccount', 'shadowAccount' ] @@ -1830,11 +1830,11 @@ class club(base_proprietaire) : # Détermination de l'uid uidNumber = 1000 - while self.exist('(uidNumber=%s)' % uidNumber) : + while self.exist('(uidNumber=%s)' % uidNumber): uidNumber += 1 try: self.lock('uidNumber',str(uidNumber)) - except : + except: # Quelqu'un nous a piqué l'uid que l'on venait de choisir ! return self.compte(login) @@ -1844,11 +1844,11 @@ class club(base_proprietaire) : return decode(login) -class machine(base_classes_crans) : +class machine(base_classes_crans): """ Classe de définition d'une machine """ idn = 'mid' - def __init__(self,parent_or_tuple,typ='fixe',conn=None) : + def __init__(self,parent_or_tuple,typ='fixe',conn=None): """ parent_or_tuple est : *soit une instance d'une classe pouvant posséder une machine @@ -1865,40 +1865,40 @@ class machine(base_classes_crans) : conn est une instance de la classe de connexion à la base LDAP """ self.conn = conn - if not self.conn : self.connect() + if not self.conn: self.connect() self.modifs=[] t = parent_or_tuple.__class__ - if t == tuple : + if t == tuple: # Initialisation avec données fournies self.dn = parent_or_tuple[0] - if typ == 'w' : - try : + if typ == 'w': + try: self.lock(self.idn, self.id()) self._modifiable = 'w' except EnvironmentError , c: self._modifiable = 0 - else : + else: self._modifiable = 0 self._init_data = parent_or_tuple[1].copy() # Utile pour construire l'instruction LDAP de modif self._data = parent_or_tuple[1] # Type de machine - if self._init_data.has_key('ipsec') : + if self._init_data.has_key('ipsec'): self.__typ = 'wifi' - elif self._init_data.has_key('puissance') : + elif self._init_data.has_key('puissance'): self.__typ = 'borne' - else : + else: self.__typ = 'fixe' # Propriéraire inconnu mais ce n'est pas grave self.__proprietaire = None - elif t in [ adherent, club, crans, invite ] and typ in [ 'fixe' , 'wifi' , 'borne' ] : + elif t in [ adherent, club, crans, invite ] and typ in [ 'fixe' , 'wifi' , 'borne' ]: # Machine vide self.__proprietaire = parent_or_tuple self.dn = parent_or_tuple.dn - self._data={ 'objectClass' : [ 'machine' ] } - if typ == 'borne' : + self._data={ 'objectClass': [ 'machine' ] } + if typ == 'borne': # Valeurs par défaut self._data['canal'] = [ '2047' ] self._data['puissance'] = [ '60' ] @@ -1907,40 +1907,40 @@ class machine(base_classes_crans) : self._modifiable = 'w' chbre = self.__proprietaire.chbre() - # if chbre == 'EXT' and typ == 'fixe' : + # if chbre == 'EXT' and typ == 'fixe': # raise ValueError(u'Il faut une chambre pour pouvoir posséder une machine fixe') - if chbre == '????' : - raise ValueError(u'ERREUR : la chambre du propriétaire est inconnue') + if chbre == '????': + raise ValueError(u'ERREUR: la chambre du propriétaire est inconnue') - if typ == 'wifi' : + if typ == 'wifi': # Génération de la clef IPsec self.ipsec(1) - else : + else: raise TypeError(u'Arguments invalides') - def Nom(self) : + def Nom(self): """ Retourne le nom de la machine """ return self.nom() - def mac(self,mac=None,multi_ok=0) : + def mac(self,mac=None,multi_ok=0): """ Défini ou retourne l'adresse mac de la machine - Adresse valide si : + Adresse valide si: 12 caractères hexa avec - ou : comme séparateurs non nulle Stoque l'adresse sous la forme xx:xx:xx:xx:xx:xx Si multi_ok = 1 permet d'avoir plusieur fois la même mac sur le réseau """ - if mac==None : + if mac==None: return decode(self._data.get('macAddress',[''])[0]) mac = format_mac(mac) # La mac serait-elle déjà connue ? - if not multi_ok and self.exist('macAddress=%s' % mac) : + if not multi_ok and self.exist('macAddress=%s' % mac): raise ValueError(u'Mac déja utilisée sur le réseau.',1) # La MAC serait-elle une MAC à la con ? @@ -1953,15 +1953,15 @@ class machine(base_classes_crans) : prefix=mac[:8].upper() + ' ' vendor = '' try: - for line in open('/usr/scripts/gestion/ethercodes.dat').readlines() : - if line.startswith(prefix) : + for line in open('/usr/scripts/gestion/ethercodes.dat').readlines(): + if line.startswith(prefix): vendor = line.replace(prefix,'').strip() break except IOError: # Le fichier existe pas, on sors raise RuntimeError(u"Fichier de fabiquants de MAC non trouvé !") - if not vendor : + if not vendor: raise ValueError(u"Le constructeur correspondant à cette adresse MAC ne peut être trouvé.\nL'adresse MAC correspond peut-être à un pont réseau, désactivez ce pont réseau.\nContactez nounou si la MAC est bien celle d'une carte.",2) # Lock de la mac @@ -1976,7 +1976,7 @@ class machine(base_classes_crans) : mac[-1] = "%0.2x" % (int(mac[-1], 16) + 2) return ":".join(mac) - def __host_alias(self,champ,new) : + def __host_alias(self,champ,new): """ Vérification de la validité d'un nom de machine """ # Supression des accents new = strip_accents(unicode(new,'iso-8859-15')) @@ -1985,30 +1985,30 @@ class machine(base_classes_crans) : new = new.lower() l = len(new.split('.')[0]) - if l<2 : + if l<2: raise ValueError(u"%s trop court." % champ.capitalize()) - if self.proprietaire().__class__ != crans : + if self.proprietaire().__class__ != crans: new = new.split('.',1)[0] for c in new[:]: - if not c in (string.letters + string.digits + '-') : + if not c in (string.letters + string.digits + '-'): raise ValueError(u"Seuls les caractères alphabétiques minuscules et les - sont autorisés pour %s" % champ) - if l>17 : + if l>17: raise ValueError(u"%s trop long." % champ.capitalize()) - if not new[0].isalnum() : + if not new[0].isalnum(): raise ValueError(u"Le premier caractère du champ %s doit être alphanumérique" % champ) # Ajout du domaine si necessaire - if new.find('.')==-1 : - try : + if new.find('.')==-1: + try: new += '.' + config.domains[self.__typ] - except : + except: raise RuntimeError(u"%s : domaine non trouvé" % champ.capitalize() ) # Pas déja pris ? - if self.exist('(|(host=%s)(hostAlias=%s))' % (new,new)) : + if self.exist('(|(host=%s)(hostAlias=%s))' % (new,new)): raise ValueError(u"%s : nom déjà pris" % champ.capitalize()) # Lock host @@ -2016,132 +2016,132 @@ class machine(base_classes_crans) : return new - def nom(self,new=None) : + def nom(self,new=None): """ Défini ou retourne le nom de machine. Un nom de machine valide ne comporte que des caractères alphabétiques minuscules et le - """ - if new==None : + if new==None: return decode(self._data.get('host',[''])[0]) new = self.__host_alias('nom de machine',new) self._set('host',[new]) return new.split('.')[0] - def prise(self,new=None) : + def prise(self,new=None): """ Retourne ou défini la prise associée à la machine La définition n'est possible que si la machine est une machine de l'assoce. Si la prise est inconne retourne N/A """ - if new == None : - if self.proprietaire().__class__ == crans : + if new == None: + if self.proprietaire().__class__ == crans: return decode(self._data.get('prise',['N/A'])[0]) - else : + else: chbre = self.proprietaire().chbre() - if chbre and chbre[0].lower() in annuaires.chbre_prises.keys() : - try : + if chbre and chbre[0].lower() in annuaires.chbre_prises.keys(): + try: return annuaires.chbre_prises[chbre[0].lower()][chbre[1:]] - except : + except: return 'N/A' # Attribution de la prise new=preattr(new)[1] - if new == 'N/A' : + if new == 'N/A': self._set('prise',[]) self._data.pop('prise') return - if not sre.match('^[a-cg-jmp][0-6][0-5][0-9]$',new.lower()) : + if not sre.match('^[a-cg-jmp][0-6][0-5][0-9]$',new.lower()): raise ValueError('Prise incorrecte') self._set('prise',[new.upper()]) return new - def alias(self,new=None) : + def alias(self,new=None): """ Création ou visualisation des alias d'une machine. Même sytème d'argument que la méthode info. """ - if not self._data.has_key('hostAlias') : + if not self._data.has_key('hostAlias'): self._data['hostAlias']=[] liste = list(self._data['hostAlias']) - if new==None : return map(decode,liste) + if new==None: return map(decode,liste) - if type(new)==list : + if type(new)==list: # Modif index = new[0] new = new[1] - if new=='' : + if new=='': liste.pop(index) self._set('hostAlias',liste) return liste - else : + else: index=-1 # Test si valide new = self.__host_alias('alias',new) - if index!=-1 : + if index!=-1: liste[index] = new - else : + else: liste = liste + [ new ] self._set('hostAlias',liste) return liste - def ip(self,ip=None) : + def ip(self,ip=None): """ Défini ou retourne l'IP de la machine. Les IP sont stoquées sous forme xxx.xxx.xxx.xxx et doivent être fournies ainsi. Si l'IP n'est pas définie retourne . Si ip= attribue la permière IP libre du sous réseau. """ - if ip==None : - if self._data.has_key('ipHostNumber') : + if ip==None: + if self._data.has_key('ipHostNumber'): return decode(self._data['ipHostNumber'][0]) elif self.proprietaire().__class__ == crans and self.__typ != 'borne': return '' - else : + else: return '' l, ip = preattr(ip) # Dans quel réseau la machine doit-elle être placée ? - if self.__typ == 'wifi' : - if self.proprietaire().__class__ == invite : + if self.__typ == 'wifi': + if self.proprietaire().__class__ == invite: net = config.NETs['wifi-invite'] elif self.proprietaire().etudes(0) == "ENS" and self.proprietaire().etudes(1) == "Pers": # Personnel ENS net = config.NETs['wifi-ens'] - else : + else: net = config.NETs['wifi'] - elif self.__typ == 'borne' : + elif self.__typ == 'borne': net = config.NETs['bornes'] - elif self.proprietaire().__class__ == crans : + elif self.proprietaire().__class__ == crans: net = [ '0.0.0.0/0' ] - else : - try : + else: + try: net = config.NETs[self.proprietaire().chbre()[0].lower()] - except : + except: raise RuntimeError(u'Impossible de trouver le réseau où placer la machine.') - if ip=='' : + if ip=='': pool_ip = [] # Pool d'IP à tester - for ne in net : + for ne in net: ip = ne.split('/')[0] ip = ip.split('.') n=[] - for i in ip : + for i in ip: n.append(int(i)) - while 1 : - if n[3] < 255 : + while 1: + if n[3] < 255: n[3] += 1 - else : + else: n[2] += 1 n[3] = 0 - if n[2]==255 : break + if n[2]==255: break ip = "%d.%d.%d.%d" % tuple(n) if not iptools.AddrInNet(ip,ne): # On est allé trop loin @@ -2153,23 +2153,23 @@ class machine(base_classes_crans) : random.shuffle(pool_ip) while len(pool_ip) > 0: ip = pool_ip.pop() # On choisit une IP - if not self.exist('ipHostNumber=%s' % ip) : + if not self.exist('ipHostNumber=%s' % ip): # On a trouvé la première ip libre break - if ip =='' : + if ip =='': raise RuntimeError(u'Plus d\'IP libres dans %s.' % string.join(net,' et ') ) - else : + else: # L'ip est elle dans le bon sous réseau ? # (accessoirement teste si l'IP est valide et ne correspond pas # à l'adresse de broadcast ou de réseau) - if not iptools.AddrInNet(ip,net) : + if not iptools.AddrInNet(ip,net): raise ValueError(u'IP invalide ou en dehors du sous réseau alloué.',1) # Reformatage ip = iptools.DecToQuad(iptools.QuadToDec(ip)) # L'ip est-elle déja allouée ? - if self.exist('ipHostNumber=%s' % ip) : + if self.exist('ipHostNumber=%s' % ip): raise ValueError(u'IP déjà prise.') # Lock ip @@ -2178,7 +2178,7 @@ class machine(base_classes_crans) : self._set('ipHostNumber',[ip]) return ip - def exempt(self,new=None) : + def exempt(self,new=None): """ Liste des réseaux vers lesquels on ne compte pas l'upload Cette liste est transférée dans la base postgres de komaz @@ -2188,65 +2188,65 @@ class machine(base_classes_crans) : [ index du nouveau réseau , nouveau réseau ] l'index est celui obtenu dans la liste retournée par exempt() """ - if not self._data.has_key('exempt') : + if not self._data.has_key('exempt'): self._data['exempt']=[] liste = list(self._data['exempt']) - if new==None : return map(decode,liste) + if new==None: return map(decode,liste) - if type(new)==list : + if type(new)==list: # Modif index = new[0] l, new = preattr(new[1]) - if not new : + if not new: # Supression réseau liste.pop(index) - else : + else: # Modif remarque liste[index]=new - elif type(new)==str : + elif type(new)==str: # Réseau supplémentaire l, new = preattr(new) - if not new : + if not new: # On ajoute pas de réseau vide return liste # Ajout à la liste liste = liste + [ new ] - else : + else: raise TypeError self._set('exempt',liste) return liste - def proprietaire(self) : + def proprietaire(self): """ retroune le propriétaire de la machine (classe adherent, club ou crans ou invite) """ - if not self.__proprietaire : + if not self.__proprietaire: res = self.conn.search_s(','.join(self.dn.split(',')[1:]),0) - if 'adherent' in res[0][1]['objectClass'] : + if 'adherent' in res[0][1]['objectClass'] : self.__proprietaire = adherent(res[0],self._modifiable,self.conn) - elif 'club' in res[0][1]['objectClass'] : + elif 'club' in res[0][1]['objectClass'] : self.__proprietaire = club(res[0],self._modifiable,self.conn) - elif 'invite' in res[0][0] : + elif 'invite' in res[0][0]: self.__proprietaire = invite() - else : + else: self.__proprietaire = crans() return self.__proprietaire - def ipsec(self,clef=0) : + def ipsec(self,clef=0): """ Génération (clef=1) ou affichage de la clef IPsec de la machine - Si clef!=1 : prend la clef fournie. + Si clef!=1: prend la clef fournie. """ - if self.__typ != 'wifi' : return None + if self.__typ != 'wifi': return None - if not clef : + if not clef: return decode(self._data.get('ipsec',[''])[0]) - if clef == 1 : + if clef == 1: # Génération clef = '' - for i in range(22) : + for i in range(22): clef += random.choice(filter(lambda x: x != 'l' and x != 'o', string.lowercase) + filter(lambda x: x != '1' and x != '0', string.digits)) @@ -2254,9 +2254,9 @@ class machine(base_classes_crans) : return clef - def canal(self,new=None,raw=False) : + def canal(self,new=None,raw=False): """ Attribution ou visualisation du canal d'une borne wifi """ - if self.__typ != 'borne' : return None + if self.__typ != 'borne': return None if not new: canaux = self._data.get('canal',[''])[0] if raw: @@ -2289,10 +2289,10 @@ class machine(base_classes_crans) : return ",".join(lcanal3) - try : + try: new = int(new) - if new < 0 or new > 13 : raise - except : + if new < 0 or new > 13: raise + except: # Nouveau système, il doit s'agir d'une liste de canaux try: lcanal3 = str(new).split(",") @@ -2315,40 +2315,40 @@ class machine(base_classes_crans) : self._set('canal',[str(new)]) return new - def puissance(self,new=None) : + def puissance(self,new=None): """ Attribution ou visualisation de la puissance d'une borne wifi """ - if self.__typ != 'borne' : return None - if not new : + if self.__typ != 'borne': return None + if not new: return self._data.get('puissance',[''])[0] - try : + try: new = int(new) - if new < -99 or new > 99 : raise - except : + if new < -99 or new > 99: raise + except: raise ValueError(u'Puissance invalide : doit être entre -99 et 99') self._set('puissance',[str(new)]) return new - def save(self) : + def save(self): """ Enregistre la machine courante dans la base LDAP Retourne une chaîne indiquant les opération effectuées. """ - if self.proprietaire().__class__ == crans and not ( isadm or user_tests.getuser() == 'www-data' ) : + if self.proprietaire().__class__ == crans and not ( isadm or user_tests.getuser() == 'www-data' ): raise EnvironmentError(u'Il faut être administrateur pour effectuer cette opération.') - if not self._init_data : + if not self._init_data: # Nouvelle machine => configuration prise self.services_to_restart('switch',[self.proprietaire().chbre()]) ret ='' # Besoin de redémarrer les firewalls ? - if 'ipHostNumber' in self.modifs or 'macAddress' in self.modifs : + if 'ipHostNumber' in self.modifs or 'macAddress' in self.modifs: reconf_ip = self._init_data.get('ipHostNumber',[]) reconf_ip += self._data.get('ipHostNumber',[]) - else : + else: reconf_ip = [] # On vire les doublons dans reconf_ip @@ -2358,46 +2358,46 @@ class machine(base_classes_crans) : self._save() # Clef IPsec - if 'ipsec' in self.modifs : + if 'ipsec' in self.modifs: ret += coul(u'Clef IPsec de la machine : %s\n' % self.ipsec(),'cyan') self.services_to_restart('conf_wifi_ng') # Reconfiguration firewalls et dhcps - if reconf_ip : + if reconf_ip: self.services_to_restart('macip',reconf_ip ) - if self.__typ == 'wifi' : + if self.__typ == 'wifi' : self.services_to_restart('nectaris-dhcp') else: self.services_to_restart('rouge-dhcp') - if 'ports' in self.modifs : + if 'ports' in self.modifs: self.services_to_restart('komaz-ports', [ self.ip() ] ) self.services_to_restart('mail_modif',['ip=%s' % self.ip()]) # Reconfiguration DNS ? - if 'host' in self.modifs or 'ipHostNumber' in self.modifs or 'hostAlias' in self.modifs : + if 'host' in self.modifs or 'ipHostNumber' in self.modifs or 'hostAlias' in self.modifs: self.services_to_restart('dns') # Reconfiguration bornes wifi ? - if 'canal' in self.modifs or 'puissance' in self.modifs : + if 'canal' in self.modifs or 'puissance' in self.modifs: self.services_to_restart('conf_wifi_ng') # Reconfiguration clients wifi ? - if self.__typ in ('wifi','borne') and ( 'ipHostNumber' in self.modifs or 'host' in self.modifs or 'macAddress' in self.modifs ) : + if self.__typ in ('wifi','borne') and ( 'ipHostNumber' in self.modifs or 'host' in self.modifs or 'macAddress' in self.modifs ): self.services_to_restart('conf_wifi_ng') # Regénération blackliste nécessaire ? bl = self.blacklist_actif() if bl and ( 'ipHostNumber' in self.modifs or 'host' in self.modifs ): - for s in bl : + for s in bl: self.services_to_restart(s,[ self.ip() ] ) # Regénération de l'autostatus et mail de changmement ? - if self.proprietaire().__class__ == crans : + if self.proprietaire().__class__ == crans: self.services_to_restart('autostatus') self.services_to_restart('mail_modif',['ip=%s' % self.ip()]) # Synchronisation avec la base pgsql pour les exemptions - if 'exempt' in self.modifs or 'ipHostNumber' in self.modifs : + if 'exempt' in self.modifs or 'ipHostNumber' in self.modifs: self.services_to_restart('exemptions') # Remise à zéro @@ -2408,9 +2408,9 @@ class machine(base_classes_crans) : return ret - def delete(self,comment='') : + def delete(self,comment=''): """ Destruction de la machines """ - if self.proprietaire().__class__ == crans and not isadm : + if self.proprietaire().__class__ == crans and not isadm: raise EnvironmentError(u'Il faut être administrateur pour effectuer cette opération.') @@ -2419,7 +2419,7 @@ class machine(base_classes_crans) : self._delete(self.dn,comment) # Services à redémarrer - if self.__typ == 'wifi' : + if self.__typ == 'wifi' : self.services_to_restart('conf_wifi_ng') self.services_to_restart('nectaris-dhcp') else: @@ -2428,97 +2428,97 @@ class machine(base_classes_crans) : self.services_to_restart('dns') self.services_to_restart('macip',[self.ip()] ) - def portTCPin(self,ports=None) : + def portTCPin(self,ports=None): """ Ports TCP ouverts depuis l'extérieur pour la machine """ return self.__port(ports,'portTCPin') - def portTCPout(self,ports=None) : + def portTCPout(self,ports=None): """ Ports TCP ouverts vers l'extérieur pour la machine """ return self.__port(ports,'portTCPout') - def portUDPin(self,ports=None) : + def portUDPin(self,ports=None): """ Ports UDP ouverts vers l'extérieur pour la machine """ return self.__port(ports,'portUDPin') - def portUDPout(self,ports=None) : + def portUDPout(self,ports=None): """ Ports UDP ouverts vers l'extérieur pour la machine """ return self.__port(ports,'portUDPout') def __port(self,ports,champ): - if ports == None : + if ports == None: return self._data.get(champ,[''])[0] ports = preattr(ports)[1] - if ports and self._data.get(champ)!=ports : + if ports and self._data.get(champ)!=ports: self._data[champ] = [ ports ] - if 'ports' not in self.modifs : + if 'ports' not in self.modifs: self.modifs.append('ports') - elif self._data.has_key(champ) : + elif self._data.has_key(champ): self._data.pop(champ) - if 'ports' not in self.modifs : + if 'ports' not in self.modifs: self.modifs.append('ports') -class _fake_proprio(crans_ldap) : +class _fake_proprio(crans_ldap): """ Définitions de base d'un propriétaire virtuel """ idn = '' def __init__(s,conn=None): s.conn = conn - if not s.conn : s.connect() + if not s.conn: s.connect() s.dn = s.base_dn - def id(s) : + def id(s): return '' - def blacklist(s) : + def blacklist(s): return [] - def paiement(s) : + def paiement(s): return [ ann_scol ] - def carteEtudiant(s) : + def carteEtudiant(s): return [ ann_scol ] - def blacklist_actif(s) : + def blacklist_actif(s): return [] - def mail(self,new=None) : + def mail(self,new=None): return 'roots@crans.org' - def machines(s) : + def machines(s): res = s.conn.search_s(s.dn,1,'objectClass=machine') m = [] - for r in res : + for r in res: m.append(machine(r,'',s.conn)) return m -class crans(_fake_proprio) : +class crans(_fake_proprio): """ Classe définissant l'assoce (pour affichage de ses machines) """ def __init__(s,conn=None): s.conn = conn - if not s.conn : s.connect() + if not s.conn: s.connect() s.dn = s.base_dn - def Nom(s) : + def Nom(s): return u"Crans" - def chbre(s) : + def chbre(s): return u"CRA" -class invite(_fake_proprio) : +class invite(_fake_proprio): """ Propriétaire des machines invité """ def __init__(s,conn=None): s.conn = conn - if not s.conn : s.connect() + if not s.conn: s.connect() s.dn = "ou=invites," + s.base_dn - def Nom(s) : + def Nom(s): return u"Invité" - def chbre(s) : + def chbre(s): return u"N/A" -if __name__ == '__main__' : +if __name__ == '__main__': import sys - if 'lock' in sys.argv : + if 'lock' in sys.argv: db = crans_ldap() - for lock in db.list_locks() : + for lock in db.list_locks(): print "%s\t %s" % (lock[1]["lockid"][0],lock[0].split(',')[0]) - if 'purgelock' in sys.argv : + if 'purgelock' in sys.argv: db = crans_ldap() db.remove_lock('*') - if 'menage' in sys.argv : + if 'menage' in sys.argv: print "Ménage des machines des adhérents partis..." db = crans_ldap() machines=db.search('paiement!=%s&host=*.crans.org' % ann_scol ,'w')['machine'] print "Destruction de %i machines" % len(machines) - for m in machines : + for m in machines: print 'Destruction de %s' % m.nom() m.delete('Ménage')