[debian/*.py] remove trailing whitespaces

Ignore-this: f62e84c258c847013d307d12acdf489e

darcs-hash:20090309212356-0445d-d8338d06f968f316fcd085446023123be87040f7.gz
This commit is contained in:
Stephane Glondu 2009-03-09 22:23:56 +01:00
parent cc31727b60
commit eae0d21f83
18 changed files with 352 additions and 352 deletions

View file

@ -1,5 +1,5 @@
#! /usr/bin/env python #! /usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Serveur SSL qui renvoie la MAC correspondant à une IP # Serveur SSL qui renvoie la MAC correspondant à une IP
# Ce serveur est utilisé sur Nectaris par les bornes wifi pour faire # Ce serveur est utilisé sur Nectaris par les bornes wifi pour faire
@ -57,15 +57,15 @@ class ARPProtocol(basic.LineReceiver):
return self.transport.write(str(m) + "\r\n") return self.transport.write(str(m) + "\r\n")
else: else:
return self.transport.write("unknown\r\n") return self.transport.write("unknown\r\n")
class ARPFactory(protocol.ServerFactory): class ARPFactory(protocol.ServerFactory):
"""Backend du serveur. Effectue la résolution IP/MAC.""" """Backend du serveur. Effectue la résolution IP/MAC."""
protocol = ARPProtocol protocol = ARPProtocol
def __init__(self, network='0.0.0.0/0'): def __init__(self, network='0.0.0.0/0'):
self.ldap = crans_ldap() self.ldap = crans_ldap()
self.network = network self.network = network
def getMac(self, IP): def getMac(self, IP):
return defer.succeed(self._getMac(IP)) return defer.succeed(self._getMac(IP))

View file

@ -5,7 +5,7 @@
Script de changement de mots de passe LDAP Script de changement de mots de passe LDAP
Utilisation : Utilisation :
* cas 1 : sans arguements par un utlisateur lambda : * cas 1 : sans arguements par un utlisateur lambda :
changement de son propre mdp changement de son propre mdp
* cas 2 : avec argument par un utilisateur ayant accès * cas 2 : avec argument par un utilisateur ayant accès
total à la base LDAP (respbats) mais PAS ROOT : total à la base LDAP (respbats) mais PAS ROOT :
@ -28,7 +28,7 @@ try :
except : except :
ldap_password = '' ldap_password = ''
ldap_auth_dn = '' ldap_auth_dn = ''
uri = 'ldap://ldap.adm.crans.org' uri = 'ldap://ldap.adm.crans.org'
syslog.openlog('chgpass',syslog.LOG_PID,syslog.LOG_AUTH) syslog.openlog('chgpass',syslog.LOG_PID,syslog.LOG_AUTH)
@ -45,14 +45,14 @@ Il ne doit pas être basé sur un mot du dictionnaire.""", 'jaune')
print "Il est conseillé d'utiliser une combinaison de minuscules, majuscules,\nde chiffres et d'au moins un caractère spécial." print "Il est conseillé d'utiliser une combinaison de minuscules, majuscules,\nde chiffres et d'au moins un caractère spécial."
print "Le mot de passe tapé ne sera pas écrit à l'écran." print "Le mot de passe tapé ne sera pas écrit à l'écran."
print "Taper Ctrl-D pour abandonner" print "Taper Ctrl-D pour abandonner"
try : try :
while 1 : while 1 :
mdp = getpass.getpass('Nouveau mot de passe : ') mdp = getpass.getpass('Nouveau mot de passe : ')
### Test du mdp ### Test du mdp
## 1 - Longueur ## 1 - Longueur
if len(mdp) < 6 : if len(mdp) < 6 :
cprint(u'Mot de passe trop court', 'rouge') cprint(u'Mot de passe trop court', 'rouge')
continue continue
@ -68,8 +68,8 @@ Il ne doit pas être basé sur un mot du dictionnaire.""", 'jaune')
if "'" in mdp: if "'" in mdp:
cprint(u'Les accents ou caractères bizarres ne sont pas autorisés (mais #!@*&%{}| le sont !)', cprint(u'Les accents ou caractères bizarres ne sont pas autorisés (mais #!@*&%{}| le sont !)',
'rouge') 'rouge')
continue continue
## 3 - assez de caractères de types différents ? ## 3 - assez de caractères de types différents ?
chiffres = 0 chiffres = 0
majuscules = 0 majuscules = 0
@ -89,33 +89,33 @@ Il ne doit pas être basé sur un mot du dictionnaire.""", 'jaune')
(not majuscules and not minuscules) : (not majuscules and not minuscules) :
cprint(u'Mot de passe trop simple.', 'rouge') cprint(u'Mot de passe trop simple.', 'rouge')
continue continue
## 4 - Cracklib ## 4 - Cracklib
test = commands.getoutput("echo '%s' | /usr/sbin/crack_testlib" % mdp) test = commands.getoutput("echo '%s' | /usr/sbin/crack_testlib" % mdp)
if test.split(':')[-1] != ' ok' : if test.split(':')[-1] != ' ok' :
commentaire = { commentaire = {
' it does not contain enough DIFFERENT characters': u'Il y a trop de caractères identiques.' , ' it does not contain enough DIFFERENT characters': u'Il y a trop de caractères identiques.' ,
' it is based on a dictionary word': u'Le mot de passe est basé sur un mot du dictionnaire' , ' it is based on a dictionary word': u'Le mot de passe est basé sur un mot du dictionnaire' ,
' it is too simplistic/systematic': u'Le mot de passe est trop simple/répétitif' ' it is too simplistic/systematic': u'Le mot de passe est trop simple/répétitif'
}.get(test.split(':')[-1],test.split(':')[-1]) }.get(test.split(':')[-1],test.split(':')[-1])
cprint(commentaire, 'rouge') cprint(commentaire, 'rouge')
continue continue
### On redemande le mot de passe ### On redemande le mot de passe
mdp1 = getpass.getpass('Retaper mot de passe : ') mdp1 = getpass.getpass('Retaper mot de passe : ')
if mdp != mdp1 : if mdp != mdp1 :
cprint(u'Les deux mots de passe entrés sont différents, réesayer', 'rouge') cprint(u'Les deux mots de passe entrés sont différents, réesayer', 'rouge')
continue continue
break break
# Changement mdp # Changement mdp
if os.system("/usr/bin/ldappasswd -H '%s' -x -D '%s' -w '%s' '%s' -s '%s' > /dev/null" % (uri, ldap_auth_dn, ldap_password, dn, mdp) ): if os.system("/usr/bin/ldappasswd -H '%s' -x -D '%s' -w '%s' '%s' -s '%s' > /dev/null" % (uri, ldap_auth_dn, ldap_password, dn, mdp) ):
cprint(u'Erreur lors du changement de mot de passe', 'rouge') cprint(u'Erreur lors du changement de mot de passe', 'rouge')
syslog.syslog("LDAP password changed for dn=%s" % dn) syslog.syslog("LDAP password changed for dn=%s" % dn)
else : else :
cprint(u'Changement effectué avec succès', u'vert') cprint(u'Changement effectué avec succès', u'vert')
except KeyboardInterrupt : except KeyboardInterrupt :
cprint(u'\nAbandon', 'rouge') cprint(u'\nAbandon', 'rouge')
pass pass
@ -130,7 +130,7 @@ if __name__ == '__main__' :
# Changement de son mot de passe # Changement de son mot de passe
login = getuser() login = getuser()
self_mode = True self_mode = True
elif '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) != 2 : elif '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) != 2 :
print "%s <login>" % sys.argv[0].split('/')[-1].split('.')[0] print "%s <login>" % sys.argv[0].split('/')[-1].split('.')[0]
print "Changement du mot de passe du compte choisi." print "Changement du mot de passe du compte choisi."
@ -143,11 +143,11 @@ if __name__ == '__main__' :
if not c.isalnum() and not c=='-' : if not c.isalnum() and not c=='-' :
cprint(u'Login incorrect', 'rouge') cprint(u'Login incorrect', 'rouge')
sys.exit(1) sys.exit(1)
if getuser() == login : if getuser() == login :
cprint(u'Utiliser passwd pour changer son propre mot de passe', 'rouge') cprint(u'Utiliser passwd pour changer son propre mot de passe', 'rouge')
sys.exit(2) sys.exit(2)
if self_mode : if self_mode :
s = commands.getoutput('sudo -u respbats ldap_whoami') s = commands.getoutput('sudo -u respbats ldap_whoami')
else : else :
@ -155,13 +155,13 @@ if __name__ == '__main__' :
if not s : if not s :
cprint(u'Login non trouvé dans la base LDAP', 'rouge') cprint(u'Login non trouvé dans la base LDAP', 'rouge')
sys.exit(3) sys.exit(3)
# Ca a l'air bon # Ca a l'air bon
if s.find('\n\n') != -1 : if s.find('\n\n') != -1 :
# Plusieurs trouvé : pas normal # Plusieurs trouvé : pas normal
cprint(u'Erreur lors de la recherche du login : plusieurs occurences !', 'rouge') cprint(u'Erreur lors de la recherche du login : plusieurs occurences !', 'rouge')
sys.exit(4) sys.exit(4)
s = s.split('\n') s = s.split('\n')
try : try :
dn = s[0].split()[1] dn = s[0].split()[1]
@ -172,13 +172,13 @@ if __name__ == '__main__' :
except : except :
cprint(u'Erreur lors de la recherche du login', 'rouge') cprint(u'Erreur lors de la recherche du login', 'rouge')
sys.exit(5) sys.exit(5)
if self_mode : if self_mode :
# Il faut vérifier l'ancien mot de passe # Il faut vérifier l'ancien mot de passe
ldap_auth_dn = dn ldap_auth_dn = dn
ldap_password = getpass.getpass('Mot de passe actuel : ') ldap_password = getpass.getpass('Mot de passe actuel : ')
s = commands.getoutput("/usr/bin/ldapwhoami -H '%s' -x -D '%s' -w '%s'" % ( uri, ldap_auth_dn, ldap_password ) ).strip() s = commands.getoutput("/usr/bin/ldapwhoami -H '%s' -x -D '%s' -w '%s'" % ( uri, ldap_auth_dn, ldap_password ) ).strip()
try : try :
resultat = s.split('\n')[0].split(':')[1].strip() resultat = s.split('\n')[0].split(':')[1].strip()
except : except :
cprint(u"Erreur lors de l'authentification", 'rouge') cprint(u"Erreur lors de l'authentification", 'rouge')
@ -186,7 +186,7 @@ if __name__ == '__main__' :
if resultat != dn : if resultat != dn :
cprint({ 'Invalid credentials (49)': u'Mot de passe invalide' }.get(resultat, resultat), 'rouge') cprint({ 'Invalid credentials (49)': u'Mot de passe invalide' }.get(resultat, resultat), 'rouge')
sys.exit(8) sys.exit(8)
elif len(s) > 3 and os.getuid()!=0 : elif len(s) > 3 and os.getuid()!=0 :
# Adhérent avec droits et on est pas root # Adhérent avec droits et on est pas root
From = 'roots@crans.org' From = 'roots@crans.org'

View file

@ -1,9 +1,9 @@
#! /usr/bin/env python #! /usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" Changement du shell de l'utilisateur lancant le programme """ Changement du shell de l'utilisateur lancant le programme
DOIT ETRE LANCE PAR SUDO DOIT ETRE LANCE PAR SUDO
Copyright (C) Frédéric Pauget Copyright (C) Frédéric Pauget
Licence : GPLv2 Licence : GPLv2
""" """
@ -31,7 +31,7 @@ adh = s['adherent']
if len(adh) != 1 : if len(adh) != 1 :
print 'Erreur fatale lors de la consultation de la base LDAP' print 'Erreur fatale lors de la consultation de la base LDAP'
sys.exit(3) sys.exit(3)
adh = adh[0] adh = adh[0]
shell = prompt(u'Nouveau shell :') shell = prompt(u'Nouveau shell :')
fd=open('/etc/shells') fd=open('/etc/shells')

View file

@ -171,7 +171,7 @@ Si tu as des questions, contacte disconnect@crans.org
NB : L'upload consiste en l'envoi de données vers des machines n'étant NB : L'upload consiste en l'envoi de données vers des machines n'étant
pas branchées sur le CRANS. pas branchées sur le CRANS.
-- --
Disconnect team""" Disconnect team"""
message_hard = u"""From: %(from)s message_hard = u"""From: %(from)s
@ -199,7 +199,7 @@ Si tu as des questions, contacte disconnect@crans.org
NB: L'upload consiste en l'envoi de données vers des machines n'étant NB: L'upload consiste en l'envoi de données vers des machines n'étant
pas branchées sur le CRANS. pas branchées sur le CRANS.
-- --
Disconnect team""" Disconnect team"""
@ -210,7 +210,7 @@ Content-Type: text/plain; charset="iso-8859-15"
%(proprio)s uploade actuellement %(upload)s Mo. %(proprio)s uploade actuellement %(upload)s Mo.
-- --
Message créé par deconnexion.py""" Message créé par deconnexion.py"""
message_disconnect_hard = u"""From: %(from)s message_disconnect_hard = u"""From: %(from)s
@ -220,7 +220,7 @@ Content-Type: text/plain; charset="iso-8859-15"
%(proprio)s a été déconnecté pour upload (%(upload)s Mo). %(proprio)s a été déconnecté pour upload (%(upload)s Mo).
-- --
Message créé par deconnexion.py""" Message créé par deconnexion.py"""
message_disconnect_multi = u"""From: %(from)s message_disconnect_multi = u"""From: %(from)s
@ -234,23 +234,23 @@ L'adhérent %(proprio)s a été déconnecté %(nbdeco)d fois pour upload en un m
Le PS a été généré et se trouve sur zamok : Le PS a été généré et se trouve sur zamok :
%(ps)s %(ps)s
-- --
Message créé par deconnexion.py""" Message créé par deconnexion.py"""
message_demenagement = u"""From: %(from)s message_demenagement = u"""From: %(from)s
To: %(to)s To: %(to)s
Subject: =?iso-8859-1?Q?D=E9m=E9nagement=20non=20d=E9clar=E9?= Subject: =?iso-8859-1?Q?D=E9m=E9nagement=20non=20d=E9clar=E9?=
Content-Type: text/plain; charset="iso-8859-15" Content-Type: text/plain; charset="iso-8859-15"
Bonjour, Bonjour,
Il semble que tu étais inscrit dans la chambre %(chambre), mais un Il semble que tu étais inscrit dans la chambre %(chambre), mais un
autre adhérent s'y est inscrit, ce qui suppose que tu n'y es plus. autre adhérent s'y est inscrit, ce qui suppose que tu n'y es plus.
Pourrais tu nous préciser ta nouvelle chambre ou adresse stp ? Pourrais tu nous préciser ta nouvelle chambre ou adresse stp ?
Si tu es parti du campus, souhaites-tu garder tes machines ? Si tu es parti du campus, souhaites-tu garder tes machines ?
-- --
Merci par avance, Merci par avance,
Les membres actifs du Crans""" Les membres actifs du Crans"""
@ -306,7 +306,7 @@ La machine %(hostname)s a été déconnectée pendant 24h pour
utilisation du protocole %(protocole)s. utilisation du protocole %(protocole)s.
Nombre de paquets : %(nb_paquets)s paquets depuis le %(datedebut)s. Nombre de paquets : %(nb_paquets)s paquets depuis le %(datedebut)s.
-- --
Message créé par deconnexion.py""" Message créé par deconnexion.py"""
deconnexion = u"""From: %(From)s deconnexion = u"""From: %(From)s
To: %(To)s To: %(To)s
@ -332,7 +332,7 @@ il pénalise l'ensemble des adhérents de l'association.
Tu seras donc déconnecté 24h. Tu seras donc déconnecté 24h.
-- --
Disconnect Team""" Disconnect Team"""
message_disconnect_multi = u"""From: %(from)s message_disconnect_multi = u"""From: %(from)s
@ -345,7 +345,7 @@ L'adhérent %(proprio)s a été déconnecté %(nbdeco)d fois pour p2p en un an !
Le PS a été généré et se trouve sur zamok : Le PS a été généré et se trouve sur zamok :
%(ps)s %(ps)s
-- --
Message créé par deconnexion.py""" Message créé par deconnexion.py"""
@ -449,7 +449,7 @@ Pour y avoir accés depuis l'extérieur il faut utiliser un mot de passe:
Sur ce, bienvenue au Cr@ns ! Sur ce, bienvenue au Cr@ns !
PS: Il t'est conseillé de conserver ce mail à toutes fin utiles PS: Il t'est conseillé de conserver ce mail à toutes fin utiles
-- --
Les membres actifs.""" Les membres actifs."""
@ -469,7 +469,7 @@ de les utiliser est disponible sur la page :
Si tu as des questions, n'hésite pas à les poser Si tu as des questions, n'hésite pas à les poser
à d'autres câbleurs ou aux nounous. à d'autres câbleurs ou aux nounous.
-- --
Les nounous""" Les nounous"""
pages_infos_droits = { "Cableur" : "https://wiki.crans.org/%C3%8AtreC%C3%A2bleur", pages_infos_droits = { "Cableur" : "https://wiki.crans.org/%C3%8AtreC%C3%A2bleur",
@ -496,7 +496,7 @@ https://wiki.crans.org/CransAdministratif?action=AttachFile&do=get&target=charte
Merci par avance, Merci par avance,
-- --
Le bureau du CRANS""" Le bureau du CRANS"""
txt_menage_cableurs = u"""From: Crans <%(From)s> txt_menage_cableurs = u"""From: Crans <%(From)s>
@ -515,5 +515,5 @@ heureux de te les remettre.
Cordialement, Cordialement,
-- --
Le bureau du CRANS""" Le bureau du CRANS"""

View file

@ -3,7 +3,7 @@
############################################################################### ###############################################################################
# config_mail : gestion du .forward et .procmailrc des adhérents # config_mail : gestion du .forward et .procmailrc des adhérents
############################################################################### ###############################################################################
# The authors of this code are # The authors of this code are
# Etienne Chové <etienne.chove@crans.org> # Etienne Chové <etienne.chove@crans.org>
# #
# Copyright (C) 2006 Etienne Chové # Copyright (C) 2006 Etienne Chové
@ -95,14 +95,14 @@ class MailConfigError(ReferenceError):
def _IsMail(mail): def _IsMail(mail):
""" """
Dit si la chaine fournie est une adresse mail valide Dit si la chaine fournie est une adresse mail valide
""" """
return bool(re.match('[a-z0-9_\.-]+@[a-z0-9_-]+(\.[a-z0-9_-]+)+',mail.lower())) return bool(re.match('[a-z0-9_\.-]+@[a-z0-9_-]+(\.[a-z0-9_-]+)+',mail.lower()))
def _Clean(texte): def _Clean(texte):
""" """
Nettoie une chaine de caractère/liste en supprimant les lignes vides/commentés, Nettoie une chaine de caractère/liste en supprimant les lignes vides/commentés,
et retourne une liste et retourne une liste
""" """
if type(texte) != list: if type(texte) != list:
texte = texte.split('\n') texte = texte.split('\n')
return [ x.strip() for x in texte if x.strip() and x[0]!='#' ] return [ x.strip() for x in texte if x.strip() and x[0]!='#' ]
@ -123,31 +123,31 @@ def _GetConfig():
# forward simple # forward simple
if _IsMail(fic_forward): if _IsMail(fic_forward):
return {'forward':fic_forward, 'spam':'accepte'} return {'forward':fic_forward, 'spam':'accepte'}
# utilisation de procmail # utilisation de procmail
if fic_forward != _Clean(forward_procmail)[0]: if fic_forward != _Clean(forward_procmail)[0]:
raise MailConfigError, 'Fichier forward non compréhensible' raise MailConfigError, 'Fichier forward non compréhensible'
## lecture du .procmailrc ## lecture du .procmailrc
fic_procmail = _Clean( open('%s/.procmailrc'%home).readlines() ) fic_procmail = _Clean( open('%s/.procmailrc'%home).readlines() )
# forward # forward
if _IsMail( fic_procmail[-1][1:].strip() ) and fic_procmail[-2] == ":0" : if _IsMail( fic_procmail[-1][1:].strip() ) and fic_procmail[-2] == ":0" :
forward = fic_procmail[-1][1:].strip() forward = fic_procmail[-1][1:].strip()
fic_procmail = fic_procmail[:-2] fic_procmail = fic_procmail[:-2]
else: else:
forward = '' forward = ''
# forward simple dans le procmailrc # forward simple dans le procmailrc
if not fic_procmail: if not fic_procmail:
return {'forward':forward, 'spam':'accepte'} return {'forward':forward, 'spam':'accepte'}
# marquage des spams # marquage des spams
tmp = _Clean( procmail_mark ) tmp = _Clean( procmail_mark )
if fic_procmail[:len(tmp)] != tmp: if fic_procmail[:len(tmp)] != tmp:
raise MailConfigError, 'Fichier de procmail non compréhensible' raise MailConfigError, 'Fichier de procmail non compréhensible'
fic_procmail = fic_procmail[len(tmp):] fic_procmail = fic_procmail[len(tmp):]
# suppression des spams ? # suppression des spams ?
if not fic_procmail: if not fic_procmail:
return {'forward':forward, 'spam':'marque'} return {'forward':forward, 'spam':'marque'}
@ -158,7 +158,7 @@ def _GetConfig():
def _SetConfig(forward = None, spam= None): def _SetConfig(forward = None, spam= None):
""" Modifie la configuration de l'utilisateur courant """ """ Modifie la configuration de l'utilisateur courant """
# variable new_spam # variable new_spam
if spam in ['accepte','supprime','marque']: if spam in ['accepte','supprime','marque']:
new_spam = spam new_spam = spam
@ -166,7 +166,7 @@ def _SetConfig(forward = None, spam= None):
new_spam = _GetConfig()['spam'] new_spam = _GetConfig()['spam']
else: else:
raise ValueError, 'Valeur interdite pour le paramètre spam' raise ValueError, 'Valeur interdite pour le paramètre spam'
# variable forward # variable forward
if forward == None: if forward == None:
new_forward = _GetConfig()['forward'] new_forward = _GetConfig()['forward']
@ -174,7 +174,7 @@ def _SetConfig(forward = None, spam= None):
new_forward = forward new_forward = forward
else: else:
raise ValueError, 'Adresse mail invalide' raise ValueError, 'Adresse mail invalide'
# génération des fichiers # génération des fichiers
if new_spam=='accepte': if new_spam=='accepte':
# suppression du .procmailrc # suppression du .procmailrc
@ -210,17 +210,17 @@ def _Sudo(uid, forward=None, spam=None):
c += " --forward=%s" % forward c += " --forward=%s" % forward
if spam!=None: if spam!=None:
c += " --spam=%s" % spam c += " --spam=%s" % spam
# execution de la commande # execution de la commande
status, output = getstatusoutput(c) status, output = getstatusoutput(c)
# code d'erreur # code d'erreur
if status: if status:
sys.stderr.write("Erreur sudo : %s\n"%c) sys.stderr.write("Erreur sudo : %s\n"%c)
sys.stderr.write(output) sys.stderr.write(output)
sys.stderr.flush() sys.stderr.flush()
sys.exit(status) sys.exit(status)
# valeurs de retour # valeurs de retour
res = {} res = {}
for line in output.split('\n'): for line in output.split('\n'):
@ -230,37 +230,37 @@ def _Sudo(uid, forward=None, spam=None):
## ##
############################################################################ ############################################################################
def MailConfig(uid=None, forward=None, spam=None): def MailConfig(uid=None, forward=None, spam=None):
""" Modifie ou retourne la configuration mail de l'utilisateur """ Modifie ou retourne la configuration mail de l'utilisateur
user = utilisateur à configurer, si None configure l'utilisateur courant user = utilisateur à configurer, si None configure l'utilisateur courant
forward = adresse vers laquelle rediriger les mails, chaine vide si pas de redirection forward = adresse vers laquelle rediriger les mails, chaine vide si pas de redirection
spam = action à effectuer sur les spams (accepte, supprime, marque) spam = action à effectuer sur les spams (accepte, supprime, marque)
Pour les champs forward et spam, la valeur None ne touche pas au champ. Pour les champs forward et spam, la valeur None ne touche pas au champ.
Retourne un dictionnaire { 'forward':'', 'spam':'' } Retourne un dictionnaire { 'forward':'', 'spam':'' }
""" """
## demande pour un autre utilisateur ## demande pour un autre utilisateur
if uid: if uid:
return _Sudo(uid=uid, forward=forward, spam=spam) return _Sudo(uid=uid, forward=forward, spam=spam)
## nettoyage des variables ## nettoyage des variables
cfg = _GetConfig() cfg = _GetConfig()
if forward == cfg['forward']: if forward == cfg['forward']:
forward = None forward = None
if spam == cfg['spam']: if spam == cfg['spam']:
spam = None spam = None
## modifications ## modifications
if forward!=None or spam!=None: if forward!=None or spam!=None:
_SetConfig(forward=forward, spam=spam) _SetConfig(forward=forward, spam=spam)
## on renvoie la configuration ## on renvoie la configuration
return _GetConfig() return _GetConfig()
if __name__=="__main__": if __name__=="__main__":
## parsage des arguments ## parsage des arguments
forward = None forward = None
@ -271,10 +271,10 @@ if __name__=="__main__":
forward = v forward = v
elif o == '--spam': elif o == '--spam':
spam = v spam = v
## execution de MailConfig ## execution de MailConfig
res = MailConfig(forward=forward, spam=spam) res = MailConfig(forward=forward, spam=spam)
## affichage des résultats ## affichage des résultats
for i in res.items(): for i in res.items():
print "%s=%s" % i print "%s=%s" % i

View file

@ -20,10 +20,10 @@ def format_sender(sender, header_charset='ISO-8859-15'):
""" """
from email.Header import Header from email.Header import Header
from email.Utils import parseaddr, formataddr from email.Utils import parseaddr, formataddr
# Split real name (which is optional) and email address parts # Split real name (which is optional) and email address parts
sender_name, sender_addr = parseaddr(sender) sender_name, sender_addr = parseaddr(sender)
# We must always pass Unicode strings to Header, otherwise it will # We must always pass Unicode strings to Header, otherwise it will
# use RFC 2047 encoding even on plain ASCII strings. # use RFC 2047 encoding even on plain ASCII strings.
sender_name = str(Header(unicode(sender_name), header_charset)) sender_name = str(Header(unicode(sender_name), header_charset))
@ -71,14 +71,14 @@ def send_email(sender, recipient, subject, body, server='localhost', cc=None, de
sender = format_sender(sender) sender = format_sender(sender)
recipient = format_sender(recipient) recipient = format_sender(recipient)
if cc: cc = format_sender(cc) if cc: cc = format_sender(cc)
# Create the message ('plain' stands for Content-Type: text/plain) # Create the message ('plain' stands for Content-Type: text/plain)
msg = MIMEText(body.encode(body_charset), 'plain', body_charset) msg = MIMEText(body.encode(body_charset), 'plain', body_charset)
msg['From'] = sender msg['From'] = sender
msg['To'] = recipient msg['To'] = recipient
msg['Subject'] = Header(unicode(subject), header_charset) msg['Subject'] = Header(unicode(subject), header_charset)
if cc: msg['Cc'] = cc if cc: msg['Cc'] = cc
if debug: if debug:
actual_recipient = [debug] actual_recipient = [debug]
else: else:
@ -89,7 +89,7 @@ def send_email(sender, recipient, subject, body, server='localhost', cc=None, de
actual_sender = format_sender(actual_sender) actual_sender = format_sender(actual_sender)
else: else:
actual_sender = sender actual_sender = sender
# Send the message # Send the message
if isinstance(server, SMTP): if isinstance(server, SMTP):
server.sendmail(actual_sender, actual_recipient, msg.as_string()) server.sendmail(actual_sender, actual_recipient, msg.as_string())
@ -113,23 +113,23 @@ def parse_mail_template(fichier):
""" """
if not isinstance(fichier, file): if not isinstance(fichier, file):
fichier = file(fichier) fichier = file(fichier)
encoding = fichier.readline() encoding = fichier.readline()
matched = re.search(r'^Encoding:\s*([^\r\n]*)', encoding) matched = re.search(r'^Encoding:\s*([^\r\n]*)', encoding)
if matched: if matched:
encoding = matched.group(1) encoding = matched.group(1)
else: else:
raise SyntaxError("Encoding manquant dans template") raise SyntaxError("Encoding manquant dans template")
subject = fichier.readline() subject = fichier.readline()
matched = re.search(r'^Subject:\s*([^\r\n]*)', subject) matched = re.search(r'^Subject:\s*([^\r\n]*)', subject)
if matched: if matched:
subject = matched.group(1).decode(encoding) subject = matched.group(1).decode(encoding)
else: else:
raise SyntaxError("Subject manquant dans template") raise SyntaxError("Subject manquant dans template")
if fichier.readline() not in ['\r\n', '\n']: if fichier.readline() not in ['\r\n', '\n']:
raise SyntaxError("le fichier n'a pas le bon format") raise SyntaxError("le fichier n'a pas le bon format")
body = fichier.read().decode(encoding) body = fichier.read().decode(encoding)
return subject, body return subject, body

View file

@ -1,10 +1,10 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
Fichier de base d'interface avec les switchs manageables. Fichier de base d'interface avec les switchs manageables.
Donne la classe switch qui permet d'effectuer les opérations Donne la classe switch qui permet d'effectuer les opérations
élémentaires sur les switchs manageable HP 26xx. élémentaires sur les switchs manageable HP 26xx.
Frédéric PAUGET Frédéric PAUGET
@ -52,7 +52,7 @@ import pexpect
class ssh : class ssh :
""" Ouverture d'une connexion ssh, envoi de commandes et récupération du résultat """ """ Ouverture d'une connexion ssh, envoi de commandes et récupération du résultat """
def __init__(self,host) : def __init__(self,host) :
""" Ouverture d'une connexion ssh vers le switch choisi """ """ Ouverture d'une connexion ssh vers le switch choisi """
self.switch = host.split('.')[0] # On garde pas le fqdn self.switch = host.split('.')[0] # On garde pas le fqdn
@ -68,14 +68,14 @@ class ssh :
traceback.print_exc() traceback.print_exc()
print "Contenu du buffer :" print "Contenu du buffer :"
print self.ssh.before print self.ssh.before
def __del__(self) : def __del__(self) :
"""Ferme la connexion : envoi logout et attend """ """Ferme la connexion : envoi logout et attend """
self.ssh.sendline("logout") self.ssh.sendline("logout")
self.ssh.send("y") self.ssh.send("y")
self.ssh.send("y") self.ssh.send("y")
self.ssh.close() self.ssh.close()
def send_cmd(self,cmd,timeout=15): def send_cmd(self,cmd,timeout=15):
""" Envoi une commande, attend le prompt et retourne la réponse """ """ Envoi une commande, attend le prompt et retourne la réponse """
# Envoi de la commande # Envoi de la commande
@ -89,7 +89,7 @@ class ssh :
'%s\(config\)# ' % self.switch, '%s\(config\)# ' % self.switch,
'quit: Control-C'], 'quit: Control-C'],
timeout=timeout) timeout=timeout)
self.__sshout = self.__sshout + self.ssh.before self.__sshout = self.__sshout + self.ssh.before
if index == 0: if index == 0:
# On répond oui # On répond oui
@ -100,7 +100,7 @@ class ssh :
elif index == 2: elif index == 2:
# On doit continuer, on envoie espace # On doit continuer, on envoie espace
self.ssh.send(" ") self.ssh.send(" ")
return self.__sshout return self.__sshout
except pexpect.TIMEOUT: except pexpect.TIMEOUT:
print "Timeout !" print "Timeout !"
@ -115,7 +115,7 @@ class snmp :
""" host doit être la machine sur laquelle se connecter """ host doit être la machine sur laquelle se connecter
version est la verion du protocole snmp à utiliser : 1, 2c ou 3 version est la verion du protocole snmp à utiliser : 1, 2c ou 3
le reste des données doit être ou non fourni suivant la version le reste des données doit être ou non fourni suivant la version
pour v1 et v2c seule la communauté est prise en compte pour v1 et v2c seule la communauté est prise en compte
pour v3 authentication_protocol, authentication_pass et username sont requis si accès en authNoPriv pour v3 authentication_protocol, authentication_pass et username sont requis si accès en authNoPriv
si privacy_pass est fourni accès en authPriv si privacy_pass est fourni accès en authPriv
@ -127,7 +127,7 @@ class snmp :
self._machine = cl.search("host=%(host)s" % {'host': host})["machineCrans"][0] self._machine = cl.search("host=%(host)s" % {'host': host})["machineCrans"][0]
except IndexError: except IndexError:
raise ValueError(u"Cette machine n'est pas un switch du Cr@ns") raise ValueError(u"Cette machine n'est pas un switch du Cr@ns")
# l'engineid du switch n'est que sa mac avec quelques fioritures autour... # l'engineid du switch n'est que sa mac avec quelques fioritures autour...
mac = self._machine.mac().replace(':', '') mac = self._machine.mac().replace(':', '')
self._engineid = '0000000b0000%(mac)s0' % {'mac': mac[:-1]} self._engineid = '0000000b0000%(mac)s0' % {'mac': mac[:-1]}
@ -136,25 +136,25 @@ class snmp :
self.options = "-v %s -c '%s' %s " % ( version, community, host ) self.options = "-v %s -c '%s' %s " % ( version, community, host )
elif version =='3' : elif version =='3' :
self.options = "-v 3 -e %s -u %s -a %s -A '%s' -l authNoPriv" % ( self._engineid, username, authentication_protocol, authentication_pass ) self.options = "-v 3 -e %s -u %s -a %s -A '%s' -l authNoPriv" % ( self._engineid, username, authentication_protocol, authentication_pass )
if privacy_pass : if privacy_pass :
self.options += " -x DES -X '%s' -l authPriv" % privacy_pass self.options += " -x DES -X '%s' -l authPriv" % privacy_pass
self.options += " %s " % host self.options += " %s " % host
else : else :
raise ValueError('Version incorrecte') raise ValueError('Version incorrecte')
def __exec(self,cmd) : def __exec(self,cmd) :
s, r = getstatusoutput(cmd) s, r = getstatusoutput(cmd)
if s : if s :
r=r.replace('snmpget: ','') r=r.replace('snmpget: ','')
raise ConversationError(r,cmd) raise ConversationError(r,cmd)
return r return r
def get(self,oid) : def get(self,oid) :
""" Retourne le résultat correspondant à l'oid demandé """ """ Retourne le résultat correspondant à l'oid demandé """
return self.__exec('snmpget -O vq %s %s ' % ( self.options, oid ) ) return self.__exec('snmpget -O vq %s %s ' % ( self.options, oid ) )
def get_string(self,oid) : def get_string(self,oid) :
""" Retourne le resultat convertit en String correspondant à l'oid demandé. Fonctionne avec les types de depart String, Integer, Hex-String. Raise ValueError sinon. """ """ Retourne le resultat convertit en String correspondant à l'oid demandé. Fonctionne avec les types de depart String, Integer, Hex-String. Raise ValueError sinon. """
s= self.__exec('snmpget -O v %s %s ' % ( self.options, oid ) ) s= self.__exec('snmpget -O v %s %s ' % ( self.options, oid ) )
if s=="\"\"": if s=="\"\"":
return "" return ""
@ -168,16 +168,16 @@ class snmp :
return unicode(var) return unicode(var)
else: else:
raise ValueError('Type inconnu') raise ValueError('Type inconnu')
def set(self,oid,typ,val) : def set(self,oid,typ,val) :
""" Change la valeur le l'oid donné. """ Change la valeur le l'oid donné.
type est le type de la valeur type est le type de la valeur
val est la valeur à écrire val est la valeur à écrire
""" """
return self.__exec('snmpset -O vq %s %s %s %s' % (self.options, oid, typ, val ) ) return self.__exec('snmpset -O vq %s %s %s %s' % (self.options, oid, typ, val ) )
def walk(self,base_oid) : def walk(self,base_oid) :
""" Retourne le résultat de snmpwalk """ Retourne le résultat de snmpwalk
le retour est un dictionnaire { oid : valeur } le retour est un dictionnaire { oid : valeur }
""" """
lignes = self.__exec('snmpwalk -O q %s %s' % (self.options, base_oid ) ).split('\n') lignes = self.__exec('snmpwalk -O q %s %s' % (self.options, base_oid ) ).split('\n')
@ -190,14 +190,14 @@ class snmp :
############################################################################################# #############################################################################################
### Gestion des switchs proprement dite ### Gestion des switchs proprement dite
class hpswitch : class hpswitch :
""" Classe pour l'administration des switchs HP. """ """ Classe pour l'administration des switchs HP. """
# Variables internes # Variables internes
__debug=0 __debug=0
__logDest=stderr __logDest=stderr
# Variables internes # Variables internes
switch = None # nom du switch switch = None # nom du switch
prise = '' prise = ''
@ -207,17 +207,17 @@ class hpswitch :
""" Switch doit être le nom du switch """ """ Switch doit être le nom du switch """
if self.__debug : self.__logDest.write("HP DEBUG : __init__(switch=%s)\n" % switch ) if self.__debug : self.__logDest.write("HP DEBUG : __init__(switch=%s)\n" % switch )
self.switch = switch.lower() self.switch = switch.lower()
# Config snmp # Config snmp
self.get, self.set, self.walk = config_snmp_secrete(snmp,switch) self.get, self.set, self.walk = config_snmp_secrete(snmp,switch)
def send_cmd(self,cmd,timout=15) : def send_cmd(self,cmd,timout=15) :
""" Envoi une commande par ssh au switch """ """ Envoi une commande par ssh au switch """
if not self.__conn_ssh : if not self.__conn_ssh :
self.__conn_ssh = ssh(self.switch) self.__conn_ssh = ssh(self.switch)
return self.__conn_ssh.send_cmd(cmd,timout) return self.__conn_ssh.send_cmd(cmd,timout)
def show_prise_mac(self,prise='') : def show_prise_mac(self,prise='') :
""" Retourne le(s) adresse(s) MAC présentes sur la prise.""" """ Retourne le(s) adresse(s) MAC présentes sur la prise."""
if not prise : prise = self.prise if not prise : prise = self.prise
@ -248,18 +248,18 @@ class hpswitch :
# On a rien trouvé # On a rien trouvé
return None return None
def __scp(self,destination,fichier) : def __scp(self,destination,fichier) :
if self.__debug : if self.__debug :
self.__logDest.write("HP DEBUG : scp(%s,%s,%s)\n" % (fichier, self.switch, destination)) self.__logDest.write("HP DEBUG : scp(%s,%s,%s)\n" % (fichier, self.switch, destination))
if exists(fichier): if exists(fichier):
system('scp %s %s:%s' % (fichier, self.switch, destination)) system('scp %s %s:%s' % (fichier, self.switch, destination))
def update(self,file=None) : def update(self,file=None) :
""" Upload le fichier de config fourni """ Upload le fichier de config fourni
Fait rebooter le switch """ Fait rebooter le switch """
self.__scp('cfg/startup-config',file) self.__scp('cfg/startup-config',file)
def upgrade(self,file=None) : def upgrade(self,file=None) :
""" Changement de firmware, """ Changement de firmware,
le firmware est dans le fichier fourni en argument le firmware est dans le fichier fourni en argument
@ -270,18 +270,18 @@ class hpswitch :
""" Ajoute la clef publique ssh aux clefs autorises """ Ajoute la clef publique ssh aux clefs autorises
par le switch """ par le switch """
self.scp('ssh/mgr_keys',file) self.scp('ssh/mgr_keys',file)
def multicast(self,ip='') : def multicast(self,ip='') :
""" Donne la liste des ports du swich inscrits au flux multicast donné """ Donne la liste des ports du swich inscrits au flux multicast donné
Si aucun flux donné teste tous les flux multicast possibles. Si aucun flux donné teste tous les flux multicast possibles.
Retourne un dictionnaire : { adresse du flux : [ ports inscrits ] } Retourne un dictionnaire : { adresse du flux : [ ports inscrits ] }
""" """
if self.__debug : self.__logDest.write("HP DEBUG : multicast(ip=%s)\n" % ip) if self.__debug : self.__logDest.write("HP DEBUG : multicast(ip=%s)\n" % ip)
if ip : if ip :
data = self.walk('STATISTICS-MIB::hpIgmpStatsPortIndex2.%s' % ip) data = self.walk('STATISTICS-MIB::hpIgmpStatsPortIndex2.%s' % ip)
return { ip : data.values() } return { ip : data.values() }
else : else :
data = self.walk('STATISTICS-MIB::hpIgmpStatsPortIndex2') data = self.walk('STATISTICS-MIB::hpIgmpStatsPortIndex2')
result = {} result = {}
@ -291,14 +291,14 @@ class hpswitch :
except : continue except : continue
result.setdefault(ip,[]) result.setdefault(ip,[])
result[ip].append(port) result[ip].append(port)
return result return result
def nb_prises(self) : def nb_prises(self) :
""" Retourne le nombre de prises du switch """ """ Retourne le nombre de prises du switch """
if self.__debug : self.__logDest.write("HP DEBUG : nb_prises()\n") if self.__debug : self.__logDest.write("HP DEBUG : nb_prises()\n")
return int(findall(r'Switch 26([0-9]{2})', self.version())[0]) return int(findall(r'Switch 26([0-9]{2})', self.version())[0])
def version(self) : def version(self) :
""" Retourne la version du firmware du switch """ """ Retourne la version du firmware du switch """
if self.__debug : self.__logDest.write("HP DEBUG : version()\n") if self.__debug : self.__logDest.write("HP DEBUG : version()\n")
@ -309,13 +309,13 @@ class hpswitch :
if not prise : prise = self.prise if not prise : prise = self.prise
if self.__debug : self.__logDest.write("HP DEBUG : enable(prise=%s)\n" % prise) if self.__debug : self.__logDest.write("HP DEBUG : enable(prise=%s)\n" % prise)
return self.set('IF-MIB::ifAdminStatus.%d' % int(prise), 'i', 1) return self.set('IF-MIB::ifAdminStatus.%d' % int(prise), 'i', 1)
def disable(self,prise=0) : def disable(self,prise=0) :
""" Désactive une prise """ """ Désactive une prise """
if not prise : prise = self.prise if not prise : prise = self.prise
if self.__debug : self.__logDest.write("HP DEBUG : disable(prise=%s)\n" % prise) if self.__debug : self.__logDest.write("HP DEBUG : disable(prise=%s)\n" % prise)
return self.set('IF-MIB::ifAdminStatus.%d' % int(prise), 'i', 2) return self.set('IF-MIB::ifAdminStatus.%d' % int(prise), 'i', 2)
def __is(self,oid,prise) : def __is(self,oid,prise) :
if not prise : prise = self.prise if not prise : prise = self.prise
prise = str(prise) prise = str(prise)
@ -328,7 +328,7 @@ class hpswitch :
return nb return nb
prise = prise.replace('-','') prise = prise.replace('-','')
return self.get(oid + '.' + prise) == 'up' return self.get(oid + '.' + prise) == 'up'
def is_enable(self,prise=0) : def is_enable(self,prise=0) :
""" Retoune True ou False suivant si la prise est activée ou non """ Retoune True ou False suivant si la prise est activée ou non
Si prise=all retourne le nombre de prises activées sur le switch """ Si prise=all retourne le nombre de prises activées sur le switch """
@ -340,7 +340,7 @@ class hpswitch :
Si prise=all retourne le nombre de prises up sur le switch """ Si prise=all retourne le nombre de prises up sur le switch """
if prise != 'all': prise = int(prise) if prise != 'all': prise = int(prise)
return self.__is('IF-MIB::ifOperStatus',prise) return self.__is('IF-MIB::ifOperStatus',prise)
def nom(self,nom=None,prise=0) : def nom(self,nom=None,prise=0) :
""" Retourne ou attribue le nom à la prise fournie """ """ Retourne ou attribue le nom à la prise fournie """
if not prise : prise = self.prise if not prise : prise = self.prise
@ -349,19 +349,19 @@ class hpswitch :
return self.get(oid) return self.get(oid)
else : else :
self.set(oid, 's' , nom) self.set(oid, 's' , nom)
def eth_mode(self,mode=None,prise=0) : def eth_mode(self,mode=None,prise=0) :
""" Fixe ou retourne le mode d'une prise """ Fixe ou retourne le mode d'une prise
mode est un tuple : (vitesse, duplex) ou simplement "auto" mode est un tuple : (vitesse, duplex) ou simplement "auto"
vitesse est : 10 100 ou 1000 vitesse est : 10 100 ou 1000
duplex est FD, HD ou auto duplex est FD, HD ou auto
""" """
if not prise : prise = self.prise if not prise : prise = self.prise
oid = 'CONFIG-MIB::hpSwitchPortFastEtherMode.%d' % int(prise) oid = 'CONFIG-MIB::hpSwitchPortFastEtherMode.%d' % int(prise)
if mode == None : if mode == None :
return self.get(oid) return self.get(oid)
# Conversion du mode # Conversion du mode
if mode == 'auto' : if mode == 'auto' :
code = 5 code = 5
@ -391,7 +391,7 @@ class hpswitch :
return result return result
class sw_chbre(hpswitch) : class sw_chbre(hpswitch) :
def __init__(self,chbre) : def __init__(self,chbre) :
# On retrouve la chbre dans l'annuaire # On retrouve la chbre dans l'annuaire
@ -410,20 +410,20 @@ class sw_chbre(hpswitch) :
self.prise10Mb = False self.prise10Mb = False
except : except :
raise ValueError('Chambre %s inconnue' % chbre) raise ValueError('Chambre %s inconnue' % chbre)
# Config snmp # Config snmp
self.get, self.set, self.walk = config_snmp_secrete(snmp,self.switch) self.get, self.set, self.walk = config_snmp_secrete(snmp,self.switch)
def reconfigure(self) : def reconfigure(self) :
""" Reconfigure la prise (nom et vitesse) """ """ Reconfigure la prise (nom et vitesse) """
in10 = self.eth_mode().find('10Mbits') != 1 in10 = self.eth_mode().find('10Mbits') != 1
if self.prise10Mb and not in10 : if self.prise10Mb and not in10 :
self.eth_mode(('10','auto')) self.eth_mode(('10','auto'))
elif not self.prise10Mb and in10 : elif not self.prise10Mb and in10 :
self.eth_mode('auto') self.eth_mode('auto')
nom = 'Chambre_%s' % self.chbre.capitalize() nom = 'Chambre_%s' % self.chbre.capitalize()
if nom != self.nom() : if nom != self.nom() :
self.nom(nom) self.nom(nom)
@ -448,13 +448,13 @@ class sw_prise(sw_chbre):
if __name__ == '__main__' : if __name__ == '__main__' :
import sys, getopt, sre import sys, getopt, sre
try : try :
options, arg = getopt.getopt(sys.argv[1:], 'U:hc:', [ 'help', 'snmp' ]) options, arg = getopt.getopt(sys.argv[1:], 'U:hc:', [ 'help', 'snmp' ])
except getopt.error, msg : except getopt.error, msg :
print msg print msg
sys.exit(1) sys.exit(1)
cmds = [] cmds = []
firmware='' firmware=''
wait=True wait=True
@ -466,17 +466,17 @@ if __name__ == '__main__' :
print "L'envoi de firmware ne fait pas rebooter le switch" print "L'envoi de firmware ne fait pas rebooter le switch"
print "L'option --snmp ajoute les commandes de reconfiguration snmp" print "L'option --snmp ajoute les commandes de reconfiguration snmp"
sys.exit(0) sys.exit(0)
elif opt=='-c' : elif opt=='-c' :
cmds.append(val) cmds.append(val)
elif opt=='-U' : elif opt=='-U' :
firmware=val firmware=val
elif opt=='--snmp' : elif opt=='--snmp' :
cmds.append(reconf_snmp) cmds.append(reconf_snmp)
cmds.append("write memory") cmds.append("write memory")
# Quels switchs ? # Quels switchs ?
switchs=[] switchs=[]
if arg : if arg :
@ -484,20 +484,20 @@ if __name__ == '__main__' :
for sw in all_switchs() : for sw in all_switchs() :
if re.match(sw) : if re.match(sw) :
switchs.append(sw) switchs.append(sw)
if not switchs : if not switchs :
print "Aucun switch trouvé" print "Aucun switch trouvé"
print "Note : il faut une _regex_ (!= wilcards au sens du shell)" print "Note : il faut une _regex_ (!= wilcards au sens du shell)"
sys.exit(3) sys.exit(3)
if not cmds and not firmware : if not cmds and not firmware :
cmds=map(str.strip,sys.stdin.readlines()) cmds=map(str.strip,sys.stdin.readlines())
# Ce que l'on va faire # Ce que l'on va faire
print "Commandes :\n\t", '\n\t'.join(cmds) print "Commandes :\n\t", '\n\t'.join(cmds)
print "\nSwitchs : ", ' '.join(switchs) print "\nSwitchs : ", ' '.join(switchs)
print print
try: try:
raw_input("Appuyer sur entrée pour continuer") raw_input("Appuyer sur entrée pour continuer")
except EOFError: except EOFError:
@ -511,8 +511,8 @@ if __name__ == '__main__' :
s = hpswitch(sw) s = hpswitch(sw)
if firmware : if firmware :
s.upgrade(firmware) s.upgrade(firmware)
for cmd in cmds : for cmd in cmds :
print s.send_cmd(cmd) print s.send_cmd(cmd)
except : except :
print 'ERREUR' print 'ERREUR'

View file

@ -14,7 +14,7 @@ from config import NETs_regexp
__QuadToDecDone = {} __QuadToDecDone = {}
def QuadToDec(ip) : def QuadToDec(ip) :
""" """
Retourne la représentation décimale d'une ip Retourne la représentation décimale d'une ip
ip est de la forme xxx.xxx.xxx.xxx ip est de la forme xxx.xxx.xxx.xxx
""" """
@ -33,9 +33,9 @@ def QuadToDec(ip) :
# Pour accélérer DecToQuad # Pour accélérer DecToQuad
__DecToQuadDone = {} __DecToQuadDone = {}
def DecToQuad(ip_dec) : def DecToQuad(ip_dec) :
""" """
Retourne la représentation habituelle d'une ip (xxx.xxx.xxx.xxx) Retourne la représentation habituelle d'une ip (xxx.xxx.xxx.xxx)
ip_dec est l'IP en base 10 ip_dec est l'IP en base 10
""" """
@ -62,7 +62,7 @@ def param(net, raw=False) :
'netmask' : yyy.yyy.yyy.yyy , 'netmask' : yyy.yyy.yyy.yyy ,
'broadcast' : zzz.zzz.zzz.zzz } 'broadcast' : zzz.zzz.zzz.zzz }
sinon retourne {} sinon retourne {}
Si raw = False, alors, on ne convertit pas les résultats sous forme pointée. Si raw = False, alors, on ne convertit pas les résultats sous forme pointée.
Ils restent sous forme d'un entier. Ils restent sous forme d'un entier.
""" """
@ -70,18 +70,18 @@ def param(net, raw=False) :
return __paramDone[net] return __paramDone[net]
reseau = {} reseau = {}
ip, mask = net.split('/') ip, mask = net.split('/')
try : try :
mask = int(mask) mask = int(mask)
dec_ip = QuadToDec(ip) dec_ip = QuadToDec(ip)
if dec_ip == -1 : raise if dec_ip == -1 : raise
except : except :
return {} return {}
# Calcul du netmask # Calcul du netmask
non_dec_netmask = netmask(mask, dec=False) non_dec_netmask = netmask(mask, dec=False)
dec_netmask = netmask(mask) dec_netmask = netmask(mask)
reseau = { 'netmask' : dec_netmask, reseau = { 'netmask' : dec_netmask,
'network' : dec_ip & dec_netmask, 'network' : dec_ip & dec_netmask,
'broadcast' : dec_ip | non_dec_netmask } 'broadcast' : dec_ip | non_dec_netmask }
@ -91,7 +91,7 @@ def param(net, raw=False) :
else: else:
__paramDone[net] = reseau __paramDone[net] = reseau
return reseau return reseau
def AddrInNet(ip,net) : def AddrInNet(ip,net) :
""" """
ip est de la forme xxx.xxx.xxx.xxx ip est de la forme xxx.xxx.xxx.xxx
@ -101,7 +101,7 @@ def AddrInNet(ip,net) :
Note : retourne False si l'IP est une adresse de réseau ou broadcast Note : retourne False si l'IP est une adresse de réseau ou broadcast
""" """
if type(net)==str : net = [ net ] if type(net)==str : net = [ net ]
r = False r = False
ip = QuadToDec(ip) ip = QuadToDec(ip)
for ne in net : for ne in net :
@ -109,11 +109,11 @@ def AddrInNet(ip,net) :
if ip == n['broadcast'] or ip == n['network'] : if ip == n['broadcast'] or ip == n['network'] :
return False return False
r = r or n['netmask'] & ip == n['network'] r = r or n['netmask'] & ip == n['network']
return r return r
def AddrInNets(ip,nets) : def AddrInNets(ip,nets) :
""" Vérifie si l'ip est au moins dans un des réseaux """ Vérifie si l'ip est au moins dans un des réseaux
de la liste nets (voir AddrInNet) """ de la liste nets (voir AddrInNet) """
for net in nets : for net in nets :
if AddrInNet(ip,net) : if AddrInNet(ip,net) :

View file

@ -3,7 +3,7 @@
# ldap_passwd.py : manipulation des mots de passes LDAP # ldap_passwd.py : manipulation des mots de passes LDAP
# $Id: ldap_passwd.py,v 1.7 2006-05-04 17:46:58 chove Exp $ # $Id: ldap_passwd.py,v 1.7 2006-05-04 17:46:58 chove Exp $
############################################################################### ###############################################################################
# The authors of this code are # The authors of this code are
# Bjorn Ove Grotan <bgrotan@grotan.com> # Bjorn Ove Grotan <bgrotan@grotan.com>
# Etienne Chové <etienne.chove@crans.org> # Etienne Chové <etienne.chove@crans.org>
# #
@ -27,19 +27,19 @@
############################################################################### ###############################################################################
# For extra strength passwords, we wanted SSHA in our LDAP-environment # For extra strength passwords, we wanted SSHA in our LDAP-environment
# as the standard python-module 'sha' does not support ssha, but this can # as the standard python-module 'sha' does not support ssha, but this can
# easily be implemented with a few extra functions. # easily be implemented with a few extra functions.
# #
# SSHA can be described as: # SSHA can be described as:
# the SHA1-digest of a password with a sequence of "salt" bytes, where # the SHA1-digest of a password with a sequence of "salt" bytes, where
# the bytes are randomly chosen - followed by the same salt bytes # the bytes are randomly chosen - followed by the same salt bytes
# For LDAP-use, the SHA1 and SSHA-digest has to be base64-encoded. # For LDAP-use, the SHA1 and SSHA-digest has to be base64-encoded.
# #
# Example-LDIF: # Example-LDIF:
# {SSHA}oaEG3PJ10sHxGcSxsDRRooTifL55/2NOdN3nU1VEV+NFzc9Q # {SSHA}oaEG3PJ10sHxGcSxsDRRooTifL55/2NOdN3nU1VEV+NFzc9Q
# #
# This package should now support passwords compatible with [1] Samba using the [2] # This package should now support passwords compatible with [1] Samba using the [2]
# smbpasswd module for [3] Python. The samba compability is added for use with Samba # smbpasswd module for [3] Python. The samba compability is added for use with Samba
# as PDC with storing user and host-information in LDAP. # as PDC with storing user and host-information in LDAP.
# #
# [1] http://www.samba.org # [1] http://www.samba.org
@ -70,7 +70,7 @@ if smb:
algos['lmpassword'] = 'lan man hash' algos['lmpassword'] = 'lan man hash'
algos['ntpassword'] = 'nt hash' algos['ntpassword'] = 'nt hash'
def getsalt(chars=string.letters+string.digits, length=16): def getsalt(chars=string.letters+string.digits, length=16):
''' Generate a random salt. Default length is 16 ''' ''' Generate a random salt. Default length is 16 '''
salt = '' salt = ''
@ -79,18 +79,18 @@ def getsalt(chars=string.letters+string.digits, length=16):
return salt return salt
def mkpasswd(pwd, sambaver=3, algo='SSHA', salt=None): def mkpasswd(pwd, sambaver=3, algo='SSHA', salt=None):
''' Make a given password cryptated, possibly with different ''' Make a given password cryptated, possibly with different
crypt-algorihtms. This module was written for use with crypt-algorihtms. This module was written for use with
LDAP - so default is seeded sha LDAP - so default is seeded sha
''' '''
if salt == None: if salt == None:
salt = getsalt() salt = getsalt()
algo = algo.lower() algo = algo.lower()
if algo not in algos.keys(): if algo not in algos.keys():
raise TypeError, 'Algorithm <%s> not supported in this version.' % algo raise TypeError, 'Algorithm <%s> not supported in this version.' % algo
if algo == 'ssha': if algo == 'ssha':
pwdhash = "{SSHA}" + base64.encodestring(sha.new(str(pwd) + salt).digest() + salt) pwdhash = "{SSHA}" + base64.encodestring(sha.new(str(pwd) + salt).digest() + salt)
elif algo =='sha': elif algo =='sha':
@ -117,7 +117,7 @@ def mkpasswd(pwd, sambaver=3, algo='SSHA', salt=None):
def checkpwd(pwd, pwdhash): def checkpwd(pwd, pwdhash):
''' Check if the password matches the hash ''' ''' Check if the password matches the hash '''
algo = pwdhash[1:].split('}')[0] algo = pwdhash[1:].split('}')[0]
algo = algo.lower() algo = algo.lower()
@ -134,5 +134,5 @@ def checkpwd(pwd, pwdhash):
salt = base64.decodestring(pwdhash.split('}')[1])[20:] salt = base64.decodestring(pwdhash.split('}')[1])[20:]
else: else:
salt = None salt = None
return mkpasswd(pwd, sambaver=sambaver, algo=algo, salt=salt) == pwdhash return mkpasswd(pwd, sambaver=sambaver, algo=algo, salt=salt) == pwdhash

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" Gestion de lock """ Gestion de lock
Copyright (C) Frédéric Pauget Copyright (C) Frédéric Pauget
Licence : GPLv2 Licence : GPLv2
@ -51,7 +51,7 @@ def wait_lock(lock_name, lock_comment='', d=None, retry=0.2):
return d return d
def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) : def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) :
""" Création d'un lock """ Création d'un lock
si nowait=1 fait un sys.exit(254) quand un ancien lock actif est rencontré si nowait=1 fait un sys.exit(254) quand un ancien lock actif est rencontré
""" """
return return
@ -76,7 +76,7 @@ def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) :
raise AssertionError('In critical section') raise AssertionError('In critical section')
else: else:
sys.stderr.write('\tpropriétaire : inconnu\n\tpid : inconnu\n\tdémarré depuis inconnu\n') sys.stderr.write('\tpropriétaire : inconnu\n\tpid : inconnu\n\tdémarré depuis inconnu\n')
sys.exit(254) sys.exit(254)
else: else:
# La procédure de lock est deja en cours d'execution, on essaie un peu plus tard # La procédure de lock est deja en cours d'execution, on essaie un peu plus tard
time.sleep(0.5) time.sleep(0.5)
@ -87,13 +87,13 @@ def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) :
if os.path.isfile(lock_file) : if os.path.isfile(lock_file) :
### Lock existant ### Lock existant
# Lecture du lock # Lecture du lock
fd = open(lock_file, "r") fd = open(lock_file, "r")
pid= fd.readline().strip() pid= fd.readline().strip()
user = fd.readline().strip() user = fd.readline().strip()
fd.close() fd.close()
# Informations sur le processus lockant # Informations sur le processus lockant
if os.system( "ps ax | grep -q '^%s '" % pid ) : if os.system( "ps ax | grep -q '^%s '" % pid ) :
# Le script lockant ne tourne plus # Le script lockant ne tourne plus
@ -103,16 +103,16 @@ def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) :
sys.stderr.write('Lock : %s\n' % lock_file) sys.stderr.write('Lock : %s\n' % lock_file)
l=getoutput("ps ax -o pid,etime | awk '($1 == %s)'" % pid) l=getoutput("ps ax -o pid,etime | awk '($1 == %s)'" % pid)
data = [ user , pid , l.strip() ] data = [ user , pid , l.strip() ]
# Formatate de etime # Formatate de etime
s = data[-1].split('-') s = data[-1].split('-')
if len(s)==2 : if len(s)==2 :
txt = '%s jour(s) ' % s[0] txt = '%s jour(s) ' % s[0]
s=s[1] s=s[1]
else : else :
txt = '' txt = ''
s=s[0] s=s[0]
s = s.split(':') s = s.split(':')
if len(s) == 3 : if len(s) == 3 :
txt = '%sh%smin%ss' % tuple(s) txt = '%sh%smin%ss' % tuple(s)
@ -140,7 +140,7 @@ def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) :
lockf(lock_fd_dl, LOCK_UN) lockf(lock_fd_dl, LOCK_UN)
lock_fd_dl.close() lock_fd_dl.close()
return make_lock(lock_name, lock_comment) return make_lock(lock_name, lock_comment)
### Prise du lock ### Prise du lock
lock_fd = file(lock_file,"w") lock_fd = file(lock_file,"w")
try: try:
@ -153,7 +153,7 @@ def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) :
# On enleve le verrou système # On enleve le verrou système
lockf(lock_fd_dl, LOCK_UN) lockf(lock_fd_dl, LOCK_UN)
lock_fd_dl.close() lock_fd_dl.close()
def remove_lock( lock_name ) : def remove_lock( lock_name ) :
""" Destruction du lock """ """ Destruction du lock """

View file

@ -44,14 +44,14 @@ def reconf_postfix():
if limit == "yes": if limit == "yes":
# Si oui, on demande à l'utilisateur si on y touche # Si oui, on demande à l'utilisateur si on y touche
negatif = ["N", "n", ""] negatif = ["N", "n", ""]
positif = ["O", "o", "Y", "y"] positif = ["O", "o", "Y", "y"]
poursuivre = "x" poursuivre = "x"
while not (poursuivre in negatif + positif): while not (poursuivre in negatif + positif):
poursuivre = raw_input("Il y a trop de destinataires, il faut réécrire la conf de postfix [o/N] ") poursuivre = raw_input("Il y a trop de destinataires, il faut réécrire la conf de postfix [o/N] ")
if poursuivre in negatif: if poursuivre in negatif:
print "Ok, on ne touche pas au fichier..." print "Ok, on ne touche pas au fichier..."
sys.exit(0) sys.exit(0)
@ -69,7 +69,7 @@ def reconf_postfix():
sys.exit(1) sys.exit(1)
reload_postfix() reload_postfix()
return(limit,lines) return(limit,lines)
if __name__ == "__main__": if __name__ == "__main__":
@ -121,7 +121,7 @@ par le script.
except IOError: except IOError:
print "Impossible d'ouvrir le fichier à envoyer, merci, au revoir." print "Impossible d'ouvrir le fichier à envoyer, merci, au revoir."
sys.exit(1) sys.exit(1)
echecs = [] echecs = []
s = smtplib.SMTP() s = smtplib.SMTP()
s.connect('smtp.crans.org') s.connect('smtp.crans.org')
@ -141,14 +141,14 @@ par le script.
else: else:
# Tout va bien # Tout va bien
pass pass
if echecs: if echecs:
print "\nIl y a eu des erreurs :" print "\nIl y a eu des erreurs :"
print echecs print echecs
s.close() s.close()
# On rétablit la conf de postfix # On rétablit la conf de postfix
finally: finally:
if limit == "yes": if limit == "yes":
try: try:

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
Script de mise a jour des firmwares de switchs Script de mise a jour des firmwares de switchs
J.Benoist Leger J.Benoist Leger
@ -52,7 +52,7 @@ if not file_tftp :
print "Pas de fichier donné" print "Pas de fichier donné"
sys.exit(1) sys.exit(1)
# On fait les tests uniquement sur batv-3 # On fait les tests uniquement sur batv-3
# switchs=["batv-3.adm.crans.org"] # switchs=["batv-3.adm.crans.org"]
@ -87,7 +87,7 @@ for bestiole in switchs :
ssh.sendline("no ip ssh filetransfer") ssh.sendline("no ip ssh filetransfer")
ssh.sendline("tftp client") ssh.sendline("tftp client")
ssh.sendline("exit") ssh.sendline("exit")
try: try:
ssh.expect("%s# " % host, timeout=40) ssh.expect("%s# " % host, timeout=40)
except pexpect.TIMEOUT: except pexpect.TIMEOUT:

View file

@ -15,8 +15,8 @@ from iptools import AddrInNet
repertoire = '/usr/scripts/var/numeros_disponibles/' repertoire = '/usr/scripts/var/numeros_disponibles/'
""" """
Un petit hack de rien du tout pour s'assurer qu'on n'attribue Un petit hack de rien du tout pour s'assurer qu'on n'attribue
pas ces adresses. Certains services risquent de continuer pas ces adresses. Certains services risquent de continuer
d'essayer de se connecter a ces adresses d'essayer de se connecter a ces adresses
""" """
ancien_vlan_adm = ['10.231.136.0/24'] ancien_vlan_adm = ['10.231.136.0/24']

View file

@ -90,7 +90,7 @@ class spawn:
p = pexpect.spawn ('/usr/bin/ssh', ['user@example.com']) p = pexpect.spawn ('/usr/bin/ssh', ['user@example.com'])
p = pexpect.spawn ('ls', ['-latr', '/tmp']) p = pexpect.spawn ('ls', ['-latr', '/tmp'])
After this the child application will be created and After this the child application will be created and
will be ready to talk to. For normal use, see expect() and will be ready to talk to. For normal use, see expect() and
send() and sendline(). send() and sendline().
If the command parameter is an integer AND a valid file descriptor If the command parameter is an integer AND a valid file descriptor
@ -116,7 +116,7 @@ class spawn:
self.__child_fd_owner = None self.__child_fd_owner = None
self.exitstatus = None self.exitstatus = None
self.pid = None self.pid = None
self.log_file = None self.log_file = None
self.before = None self.before = None
self.after = None self.after = None
self.match = None self.match = None
@ -124,21 +124,21 @@ class spawn:
self.name = '' # File-like object. self.name = '' # File-like object.
self.flag_eof = 0 self.flag_eof = 0
# NEW -- to support buffering -- the ability to read more than one # NEW -- to support buffering -- the ability to read more than one
# byte from a TTY at a time. See setmaxread() method. # byte from a TTY at a time. See setmaxread() method.
self.buffer = '' self.buffer = ''
self.maxread = 1 # Maximum to read at a time self.maxread = 1 # Maximum to read at a time
### IMPLEMENT THIS FEATURE!!! ### IMPLEMENT THIS FEATURE!!!
# anything before maxsearchsize point is preserved, but not searched. # anything before maxsearchsize point is preserved, but not searched.
#self.maxsearchsize = 1000 #self.maxsearchsize = 1000
# If command is an int type then it must represent an open file descriptor. # If command is an int type then it must represent an open file descriptor.
if type (command) == type(0): if type (command) == type(0):
try: # Command is an int, so now check if it is a file descriptor. try: # Command is an int, so now check if it is a file descriptor.
os.fstat(command) os.fstat(command)
except OSError: except OSError:
raise ExceptionPexpect, 'Command is an int type, yet is not a valid file descriptor.' raise ExceptionPexpect, 'Command is an int type, yet is not a valid file descriptor.'
self.pid = -1 self.pid = -1
self.child_fd = command self.child_fd = command
self.__child_fd_owner = 0 # Sets who is reponsible for the child_fd self.__child_fd_owner = 0 # Sets who is reponsible for the child_fd
self.args = None self.args = None
@ -273,7 +273,7 @@ class spawn:
def setlog (self, fileobject): def setlog (self, fileobject):
"""This sets logging output to go to the given fileobject. """This sets logging output to go to the given fileobject.
Set fileobject to None to stop logging. Set fileobject to None to stop logging.
Example: Example:
child = pexpect.spawn('some_command') child = pexpect.spawn('some_command')
fout = file('mylog.txt','w') fout = file('mylog.txt','w')
@ -300,13 +300,13 @@ class spawn:
If a log file was set using setlog() then all data will If a log file was set using setlog() then all data will
also be written to the log file. also be written to the log file.
Notice that if this method is called with timeout=None Notice that if this method is called with timeout=None
then it actually may block. then it actually may block.
This is a non-blocking wrapper around os.read(). This is a non-blocking wrapper around os.read().
It uses select.select() to implement a timeout. It uses select.select() to implement a timeout.
""" """
if self.child_fd == -1: if self.child_fd == -1:
raise ValueError ('I/O operation on closed file') raise ValueError ('I/O operation on closed file')
@ -320,7 +320,7 @@ class spawn:
if not r: if not r:
self.flag_eof = 1 self.flag_eof = 1
raise EOF ('End Of File (EOF) in read(). Braindead platform.') raise EOF ('End Of File (EOF) in read(). Braindead platform.')
r, w, e = select.select([self.child_fd], [], [], timeout) r, w, e = select.select([self.child_fd], [], [], timeout)
if not r: if not r:
raise TIMEOUT('Timeout exceeded in read().') raise TIMEOUT('Timeout exceeded in read().')
@ -338,21 +338,21 @@ class spawn:
if s == '': if s == '':
self.flag_eof = 1 self.flag_eof = 1
raise EOF('End Of File (EOF) in read(). Empty string style platform.') raise EOF('End Of File (EOF) in read(). Empty string style platform.')
if self.log_file != None: if self.log_file != None:
self.log_file.write (s) self.log_file.write (s)
self.log_file.flush() self.log_file.flush()
return s return s
raise ExceptionPexpect('Reached an unexpected state in read().') raise ExceptionPexpect('Reached an unexpected state in read().')
def read (self, size = -1): # File-like object. def read (self, size = -1): # File-like object.
"""This reads at most size bytes from the file """This reads at most size bytes from the file
(less if the read hits EOF before obtaining size bytes). (less if the read hits EOF before obtaining size bytes).
If the size argument is negative or omitted, If the size argument is negative or omitted,
read all data until EOF is reached. read all data until EOF is reached.
The bytes are returned as a string object. The bytes are returned as a string object.
An empty string is returned when EOF is encountered immediately. An empty string is returned when EOF is encountered immediately.
""" """
if size == 0: if size == 0:
@ -366,16 +366,16 @@ class spawn:
# I would catch any bugs early and ensure consistant behavior. # I would catch any bugs early and ensure consistant behavior.
# It's a little less efficient, but there is less for me to # It's a little less efficient, but there is less for me to
# worry about if I have to later modify read() or expect(). # worry about if I have to later modify read() or expect().
cre = re.compile('.{%d}' % size, re.DOTALL) cre = re.compile('.{%d}' % size, re.DOTALL)
index = self.expect ([cre, EOF]) index = self.expect ([cre, EOF])
if index == 0: if index == 0:
return self.after ### self.before should be ''. Should I assert this? return self.after ### self.before should be ''. Should I assert this?
return self.before return self.before
def readline (self, size = -1): # File-like object. def readline (self, size = -1): # File-like object.
"""This reads and returns one entire line. A trailing newline is kept in """This reads and returns one entire line. A trailing newline is kept in
the string, but may be absent when a file ends with an incomplete line. the string, but may be absent when a file ends with an incomplete line.
Note: This readline() looks for a \\r\\n pair even on UNIX because this is Note: This readline() looks for a \\r\\n pair even on UNIX because this is
what the pseudo tty device returns. So contrary to what you may be used to what the pseudo tty device returns. So contrary to what you may be used to
you will receive a newline as \\r\\n. you will receive a newline as \\r\\n.
An empty string is returned when EOF is hit immediately. An empty string is returned when EOF is hit immediately.
@ -404,9 +404,9 @@ class spawn:
return result return result
def readlines (self, sizehint = -1): # File-like object. def readlines (self, sizehint = -1): # File-like object.
"""This reads until EOF using readline() and returns a list containing """This reads until EOF using readline() and returns a list containing
the lines thus read. The optional sizehint argument is ignored. the lines thus read. The optional sizehint argument is ignored.
""" """
lines = [] lines = []
while 1: while 1:
line = self.readline() line = self.readline()
@ -422,7 +422,7 @@ class spawn:
def writelines (self, sequence): # File-like object. def writelines (self, sequence): # File-like object.
"""This calls write() for each element in the sequence. """This calls write() for each element in the sequence.
The sequence can be any iterable object producing strings, The sequence can be any iterable object producing strings,
typically a list of strings. This does not add line separators typically a list of strings. This does not add line separators
There is no return value. There is no return value.
""" """
@ -449,8 +449,8 @@ class spawn:
buffer to be sent to the waiting child program without buffer to be sent to the waiting child program without
waiting for end-of-line. If it is the first character of the waiting for end-of-line. If it is the first character of the
line, the read() in the user program returns 0, which line, the read() in the user program returns 0, which
signifies end-of-file. This means to work as expected signifies end-of-file. This means to work as expected
a sendeof() has to be called at the begining of a line. a sendeof() has to be called at the begining of a line.
This method does not send a newline. It is the responsibility This method does not send a newline. It is the responsibility
of the caller to ensure the eof is sent at the beginning of a line. of the caller to ensure the eof is sent at the beginning of a line.
""" """
@ -487,7 +487,7 @@ class spawn:
# If this class was created from an existing file descriptor then # If this class was created from an existing file descriptor then
# I just check to see if the file descriptor is still valid. # I just check to see if the file descriptor is still valid.
if self.pid == -1 and not self.__child_fd_owner: if self.pid == -1 and not self.__child_fd_owner:
try: try:
os.fstat(self.child_fd) os.fstat(self.child_fd)
return 1 return 1
@ -535,7 +535,7 @@ class spawn:
def compile_pattern_list(self, patterns): def compile_pattern_list(self, patterns):
"""This compiles a pattern-string or a list of pattern-strings. """This compiles a pattern-string or a list of pattern-strings.
Patterns must be a StringType, EOF, TIMEOUT, SRE_Pattern, or Patterns must be a StringType, EOF, TIMEOUT, SRE_Pattern, or
a list of those. a list of those.
This is used by expect() when calling expect_list(). This is used by expect() when calling expect_list().
@ -569,7 +569,7 @@ class spawn:
raise TypeError, 'Argument must be one of StringType, EOF, TIMEOUT, SRE_Pattern, or a list of those type. %s' % str(type(p)) raise TypeError, 'Argument must be one of StringType, EOF, TIMEOUT, SRE_Pattern, or a list of those type. %s' % str(type(p))
return compiled_pattern_list return compiled_pattern_list
def expect(self, pattern, timeout = -1): def expect(self, pattern, timeout = -1):
"""This seeks through the stream until a pattern is matched. """This seeks through the stream until a pattern is matched.
The pattern is overloaded and may take several types including a list. The pattern is overloaded and may take several types including a list.
@ -654,14 +654,14 @@ class spawn:
#ED# incoming = '' #ED# incoming = ''
incoming = self.buffer incoming = self.buffer
while 1: # Keep reading until exception or return. while 1: # Keep reading until exception or return.
#ED# c = self.read_nonblocking (1, timeout) #ED# c = self.read_nonblocking (1, timeout)
#ED# incoming = incoming + c #ED# incoming = incoming + c
# Sequence through the list of patterns and look for a match. # Sequence through the list of patterns and look for a match.
index = -1 index = -1
for str_target in pattern_list: for str_target in pattern_list:
index = index + 1 index = index + 1
if str_target is EOF or str_target is TIMEOUT: if str_target is EOF or str_target is TIMEOUT:
continue # The Exception patterns are handled differently. continue # The Exception patterns are handled differently.
match_index = incoming.find (str_target) match_index = incoming.find (str_target)
if match_index >= 0: if match_index >= 0:
@ -670,9 +670,9 @@ class spawn:
self.buffer = incoming [match_index + len(str_target):] self.buffer = incoming [match_index + len(str_target):]
self.match = None self.match = None
return index return index
c = self.read_nonblocking (self.maxread, timeout) c = self.read_nonblocking (self.maxread, timeout)
incoming = incoming + c incoming = incoming + c
except EOF: except EOF:
self.before = incoming self.before = incoming
self.after = EOF self.after = EOF
@ -695,10 +695,10 @@ class spawn:
self.match = None self.match = None
self.buffer = '' self.buffer = ''
raise raise
def expect_list(self, pattern_list, timeout = -1): def expect_list(self, pattern_list, timeout = -1):
""" """
This takes a list of compiled regular expressions and returns This takes a list of compiled regular expressions and returns
the index into the pattern_list that matched the child's output. the index into the pattern_list that matched the child's output.
This is called by expect(). It is similar to the expect() method This is called by expect(). It is similar to the expect() method
except that expect_list() is not overloaded and it does not have to except that expect_list() is not overloaded and it does not have to
@ -711,7 +711,7 @@ class spawn:
if timeout == -1: if timeout == -1:
timeout = self.timeout timeout = self.timeout
try: try:
#ED# incoming = '' #ED# incoming = ''
incoming = self.buffer incoming = self.buffer
@ -723,7 +723,7 @@ class spawn:
index = -1 index = -1
for cre in pattern_list: for cre in pattern_list:
index = index + 1 index = index + 1
if cre is EOF or cre is TIMEOUT: if cre is EOF or cre is TIMEOUT:
continue # The patterns for PexpectExceptions are handled differently. continue # The patterns for PexpectExceptions are handled differently.
match = cre.search(incoming) match = cre.search(incoming)
if match is not None: if match is not None:
@ -735,7 +735,7 @@ class spawn:
# Read more data # Read more data
c = self.read_nonblocking (self.maxread, timeout) c = self.read_nonblocking (self.maxread, timeout)
incoming = incoming + c incoming = incoming + c
except EOF: except EOF:
self.before = incoming self.before = incoming
self.after = EOF self.after = EOF
@ -859,7 +859,7 @@ def _which (filename):
# Oddly enough this was the one line that made Pexpect # Oddly enough this was the one line that made Pexpect
# incompatible with Python 1.5.2. # incompatible with Python 1.5.2.
#pathlist = p.split (os.pathsep) #pathlist = p.split (os.pathsep)
pathlist = string.split (p, os.pathsep) pathlist = string.split (p, os.pathsep)
for path in pathlist: for path in pathlist:
@ -907,7 +907,7 @@ def _split_command_line(command_line):
if c != '\\'and state_esc: # escape mode lasts for one character. if c != '\\'and state_esc: # escape mode lasts for one character.
state_esc = 0 state_esc = 0
# Handle last argument. # Handle last argument.
if arg != '': if arg != '':
arg_list.append(arg) arg_list.append(arg)
return arg_list return arg_list
@ -936,7 +936,7 @@ def _split_command_line(command_line):
# Nonblocking on Win32? # Nonblocking on Win32?
# Reasearch this as a way to maybe make pipe work for Win32. # Reasearch this as a way to maybe make pipe work for Win32.
# http://groups.google.com/groups?q=setraw+tty&hl=en&selm=uvgpvisvk.fsf%40roundpoint.com&rnum=7 # http://groups.google.com/groups?q=setraw+tty&hl=en&selm=uvgpvisvk.fsf%40roundpoint.com&rnum=7
# #
# if istty: # if istty:
# if os.name=='posix': # if os.name=='posix':
# import tty # import tty
@ -983,10 +983,10 @@ def _split_command_line(command_line):
## self.buffer = '' ## self.buffer = ''
## ##
## def read(self, n, timeout = None): ## def read(self, n, timeout = None):
## """This does a read restricted by a timeout and ## """This does a read restricted by a timeout and
## it includes any cached data from previous calls. ## it includes any cached data from previous calls.
## This is a non-blocking wrapper around os.read. ## This is a non-blocking wrapper around os.read.
## it uses select.select to supply a timeout. ## it uses select.select to supply a timeout.
## Note that if this is called with timeout=None (the default) ## Note that if this is called with timeout=None (the default)
## then this actually MAY block. ## then this actually MAY block.
## """ ## """

View file

@ -292,7 +292,7 @@ def ressuscite(adh, oldmachine):
strmachine = u"Cette machine était une machine Wifi." strmachine = u"Cette machine était une machine Wifi."
strdef = 'Wifi' strdef = 'Wifi'
else: else:
strmachine = u"L'ancien type de cette machine est inconnu ..." strmachine = u"L'ancien type de cette machine est inconnu ..."
strdef = '' strdef = ''
# Certaines fois, on peut vouloir transformer une machine Fixe en Wifi, # Certaines fois, on peut vouloir transformer une machine Fixe en Wifi,

View file

@ -23,7 +23,7 @@ def load(file) :
except : except :
print "Impossible d'ouvrir le fichier demandé." print "Impossible d'ouvrir le fichier demandé."
sys.exit(1) sys.exit(1)
obj = cPickle.load(fd) obj = cPickle.load(fd)
try : try :
@ -39,10 +39,10 @@ def load(file) :
### Modifs pour permettre une restauration ### Modifs pour permettre une restauration
# On supprime les infos de aid, mid ou cid # On supprime les infos de aid, mid ou cid
obj.dn = obj.dn.split(',',1)[1] obj.dn = obj.dn.split(',',1)[1]
# On supprime les infos du init_data # On supprime les infos du init_data
obj._init_data={} obj._init_data={}
return obj return obj
if '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) != 2 : if '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) != 2 :
@ -61,7 +61,7 @@ def restore_adher(adh) :
prompt(u'Appuyez sur ENTREE pour continuer') prompt(u'Appuyez sur ENTREE pour continuer')
adh._data['mail'] = [] adh._data['mail'] = []
modif_adher(adh) modif_adher(adh)
def restore_machine(machine) : def restore_machine(machine) :
try : try :
obj.proprio # crash si l'adhérent est encore dans la base obj.proprio # crash si l'adhérent est encore dans la base
@ -77,7 +77,7 @@ def restore_machine(machine) :
def restore_club(club) : def restore_club(club) :
modif_club(club) modif_club(club)
# Restauration ? # Restauration ?
q = prompt(u'Restaurer cette entrée ? [O/N]') q = prompt(u'Restaurer cette entrée ? [O/N]')
if q not in 'oO' : if q not in 'oO' :

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" Fonctions de tests sur l'utilisateur """ Fonctions de tests sur l'utilisateur
Copyright (C) Frédéric Pauget Copyright (C) Frédéric Pauget
Licence : GPLv2 Licence : GPLv2
@ -15,15 +15,15 @@ def getuser() :
if not user : if not user :
user = pwd.getpwuid(os.getuid())[0] user = pwd.getpwuid(os.getuid())[0]
return user return user
def groups(login='') : def groups(login='') :
""" Retourne la liste des droits qu'a l'utilisateur fourni, si aucun """ Retourne la liste des droits qu'a l'utilisateur fourni, si aucun
utilisateur n'est fourni prend l'utilisateur loggué """ utilisateur n'est fourni prend l'utilisateur loggué """
if login == '': if login == '':
login = getuser() login = getuser()
if login == 'root': if login == 'root':
groups = ['0'] groups = ['0']
else: else:
@ -37,9 +37,9 @@ def groups(login='') :
groups = [] groups = []
else: else:
groups = adh.droits() groups = adh.droits()
return groups return groups
def isadm(login='') : def isadm(login='') :
""" Retourne True si l'utilisateur est dans le groupe 4 (adm) """ Retourne True si l'utilisateur est dans le groupe 4 (adm)

View file

@ -9,29 +9,29 @@ d'un adhérent.
Usage: %(prog)s [options] <chaine de recherche> Usage: %(prog)s [options] <chaine de recherche>
La chaine de recherche peut être : La chaine de recherche peut être :
* soit un terme unique, dans ce cas la recherche sera effectuée sur les * soit un terme unique, dans ce cas la recherche sera effectuée sur les
champs en bleu ci-dessous. champs en bleu ci-dessous.
* soit du type "champ1=valeur1&champ2!=valeur2 ...", les résultats seront * soit du type "champ1=valeur1&champ2!=valeur2 ...", les résultats seront
alors limités aux entrées correspondantes à tous les critères. alors limités aux entrées correspondantes à tous les critères.
Les champs de recherche possibles sont : Les champs de recherche possibles sont :
%(champs_rech)s %(champs_rech)s
Recherche sur prise possible (utiliser uniquement ce champ dans ce cas). Recherche sur prise possible (utiliser uniquement ce champ dans ce cas).
Les options de recherches sont : Les options de recherches sont :
* limitations sur l'affichage : * limitations sur l'affichage :
-a ou --adherent : limitation de l'affichage aux adhérents -a ou --adherent : limitation de l'affichage aux adhérents
-m ou --machine : limitation de l'affichage aux machines -m ou --machine : limitation de l'affichage aux machines
-c ou --club : limitation de l'affichage aux clubs -c ou --club : limitation de l'affichage aux clubs
-b ou --bornes : limitation de l'affichage aux bornes wifi -b ou --bornes : limitation de l'affichage aux bornes wifi
--crans : recherche uniquement les machines du crans --crans : recherche uniquement les machines du crans
* options d'affichage : * options d'affichage :
-t ou --tech : affichages des infos techniques des machines -t ou --tech : affichages des infos techniques des machines
à la place des infos administratives dans les résumés. à la place des infos administratives dans les résumés.
-i ou --ipsec : montre la clef ipsec des machines wifi -i ou --ipsec : montre la clef ipsec des machines wifi
-l <num> ou --limit=<num> : limite du nombre de résultats pour utiliser -l <num> ou --limit=<num> : limite du nombre de résultats pour utiliser
le mode d'affichage condensé au lieu du mode détaillé (défaut %(limit_aff_details)i) le mode d'affichage condensé au lieu du mode détaillé (défaut %(limit_aff_details)i)
-L <num> ou --limit-historique=<num> : limitation du nombre de lignes -L <num> ou --limit-historique=<num> : limitation du nombre de lignes
d'historique affichées (défaut %(limit_aff_historique)i) d'historique affichées (défaut %(limit_aff_historique)i)
@ -39,7 +39,7 @@ d'historique affichées (défaut %(limit_aff_historique)i)
try: try:
import sys,locale import sys,locale
loc = locale.getdefaultlocale() loc = locale.getdefaultlocale()
if loc[1]: if loc[1]:
sys.reallysetdefaultencoding(loc[1]) sys.reallysetdefaultencoding(loc[1])
@ -64,22 +64,22 @@ aff_ipsec = 0
def aff(qqch,mtech=0) : def aff(qqch,mtech=0) :
""" Affichage de qqch. """ Affichage de qqch.
qqch peut être une liste d'instances des classes adhérent ou machine qqch peut être une liste d'instances des classes adhérent ou machine
(un seul type dans la liste) dans ce cas : (un seul type dans la liste) dans ce cas :
* si la longueur de la liste est inférieure à limit_aff_details * si la longueur de la liste est inférieure à limit_aff_details
affiche les propriétés détaillées de chaque élément. affiche les propriétés détaillées de chaque élément.
* sinon résume dans un tabeau des principales propriétés * sinon résume dans un tabeau des principales propriétés
si qqch est une instance seul la traité comme une liste à une élément si qqch est une instance seul la traité comme une liste à une élément
Si mtech = 1 affiches les infomations techniques des machines plutot Si mtech = 1 affiches les infomations techniques des machines plutot
qu'administratives dans le tableau des propriétés qu'administratives dans le tableau des propriétés
""" """
if type(qqch) != list : if type(qqch) != list :
qqch = [ qqch ] qqch = [ qqch ]
if len(qqch) > limit_aff_details : if len(qqch) > limit_aff_details :
t = qqch[0].idn t = qqch[0].idn
if t == 'aid': if t == 'aid':
cprint(adhers_brief(qqch)) cprint(adhers_brief(qqch))
elif t == 'mid': elif t == 'mid':
if mtech: if mtech:
cprint(list_machines(qqch)) cprint(list_machines(qqch))
else: else:
@ -98,11 +98,11 @@ def aff(qqch,mtech=0) :
cprint(machine_details(c).strip()) cprint(machine_details(c).strip())
elif t == 'cid': elif t == 'cid':
cprint(club_details(c).strip()) cprint(club_details(c).strip())
# affiche le nombre de résultats # affiche le nombre de résultats
if len(qqch) > 1: if len(qqch) > 1:
cprint(u"Total: %d" % len(qqch)) cprint(u"Total: %d" % len(qqch))
def adhers_brief(adhers) : def adhers_brief(adhers) :
""" """
Formatage sous forme de tableau des infos sur la liste d'adhérent fournie : Formatage sous forme de tableau des infos sur la liste d'adhérent fournie :
@ -116,7 +116,7 @@ def adhers_brief(adhers) :
# Copie locale triée par (nom, prenom) # Copie locale triée par (nom, prenom)
adhers = adhers[:] adhers = adhers[:]
adhers.sort(lambda x, y: cmp((x.nom(), x.prenom()), (y.nom(), y.prenom()))) adhers.sort(lambda x, y: cmp((x.nom(), x.prenom()), (y.nom(), y.prenom())))
for a in adhers: for a in adhers:
## État administratif ## État administratif
ok = u'\x1b[1;32mo\x1b[1;0m' ok = u'\x1b[1;32mo\x1b[1;0m'
@ -128,23 +128,23 @@ def adhers_brief(adhers) :
else: paid = ok else: paid = ok
elif isinstance(a,Adherent) and not a.adherentPayant(): paid = coul('G', 'bleu') elif isinstance(a,Adherent) and not a.adherentPayant(): paid = coul('G', 'bleu')
else: paid = nok else: paid = nok
# Précablage # Précablage
if ann_scol+1 in a.paiement() : paid = coul(paid,'f_vert') if ann_scol+1 in a.paiement() : paid = coul(paid,'f_vert')
# Carte d'étudiant # Carte d'étudiant
if ann_scol in a.carteEtudiant(): if ann_scol in a.carteEtudiant():
if 'c' in a.controle(): carte = ook if 'c' in a.controle(): carte = ook
else: carte = ok else: carte = ok
else : carte = nok else : carte = nok
machines = '' machines = ''
# Récupération des machines # Récupération des machines
if len(adhers) <= limit_aff_machines: if len(adhers) <= limit_aff_machines:
for machine in a.machines() : for machine in a.machines() :
nom = machine.nom().split('.')[0] nom = machine.nom().split('.')[0]
if machine.blacklist_actif() : k = 'rouge' if machine.blacklist_actif() : k = 'rouge'
elif isinstance(machine, MachineWifi): k = 'cyan' elif isinstance(machine, MachineWifi): k = 'cyan'
else : k= '' else : k= ''
if machines : machines += ', ' + coul(nom,k) if machines : machines += ', ' + coul(nom,k)
else : machines = coul(nom,k) else : machines = coul(nom,k)
@ -155,7 +155,7 @@ def adhers_brief(adhers) :
data.append([a.id(), a.Nom(), a.chbre(), paid, carte, machines]) data.append([a.id(), a.Nom(), a.chbre(), paid, carte, machines])
else: else:
data.append([a.id(), a.Nom(), a.chbre(), paid, carte]) data.append([a.id(), a.Nom(), a.chbre(), paid, carte])
if len(adhers) <= limit_aff_machines: if len(adhers) <= limit_aff_machines:
return u"Machines en rouge = machines avec limitation de services\n" + \ return u"Machines en rouge = machines avec limitation de services\n" + \
u"P : paiement année en cours, le fond vert indique le précâblage (G bleu = inscription gratuite)\n" + \ u"P : paiement année en cours, le fond vert indique le précâblage (G bleu = inscription gratuite)\n" + \
@ -172,7 +172,7 @@ def adhers_brief(adhers) :
titre = [u'aid', u'Prénom Nom', u'Chbre', u'P', u'C'], titre = [u'aid', u'Prénom Nom', u'Chbre', u'P', u'C'],
largeur = [5, '*', 5, 1, 1], largeur = [5, '*', 5, 1, 1],
alignement = ['d', 'c', 'g', 'c', 'c']) alignement = ['d', 'c', 'g', 'c', 'c'])
def machines_brief(machines) : def machines_brief(machines) :
""" """
Formatage sous forme d'un tableau des propriétés de la liste de machine : Formatage sous forme d'un tableau des propriétés de la liste de machine :
@ -188,14 +188,14 @@ def machines_brief(machines) :
# Copie locale triée par nom # Copie locale triée par nom
machines = machines[:] machines = machines[:]
machines.sort(lambda x, y: cmp(x.nom(), y.nom())) machines.sort(lambda x, y: cmp(x.nom(), y.nom()))
for m in machines : for m in machines :
t, bl = __bases_machines(m) t, bl = __bases_machines(m)
# Propriétaire # Propriétaire
a = m.proprietaire() a = m.proprietaire()
p = a.Nom() p = a.Nom()
# A jour administrativement # A jour administrativement
if ann_scol not in a.paiement() or ann_scol not in a.carteEtudiant(): if ann_scol not in a.paiement() or ann_scol not in a.carteEtudiant():
if isinstance(a, Adherent) and not a.adherentPayant(): if isinstance(a, Adherent) and not a.adherentPayant():
@ -205,7 +205,7 @@ def machines_brief(machines) :
# Données # Données
data.append([m.id() , t, m.nom().split('.')[0], p, a.chbre(), bl]) data.append([m.id() , t, m.nom().split('.')[0], p, a.chbre(), bl])
return u"Le propriétaire en rouge signale un problème administratif, en bleu une inscription gratuite\n" + \ return u"Le propriétaire en rouge signale un problème administratif, en bleu une inscription gratuite\n" + \
tableau(data, tableau(data,
titre = [u'mid', u'Type', u'Nom de machine', u'Propriétaire', u'Chbre', u'Limitation'], titre = [u'mid', u'Type', u'Nom de machine', u'Propriétaire', u'Chbre', u'Limitation'],
@ -225,7 +225,7 @@ def clubs_brief(clubs) :
# Copie locale triée par Nom # Copie locale triée par Nom
clubs = clubs[:] clubs = clubs[:]
clubs.sort(lambda x, y: cmp(x.Nom(), y.Nom())) clubs.sort(lambda x, y: cmp(x.Nom(), y.Nom()))
for c in clubs : for c in clubs :
## État administratif ## État administratif
ok = u'\x1b[1;32mo\x1b[1;0m' ok = u'\x1b[1;32mo\x1b[1;0m'
@ -236,10 +236,10 @@ def clubs_brief(clubs) :
if 'p' in c.controle(): paid = ook if 'p' in c.controle(): paid = ook
else: paid = ok else: paid = ok
else : paid = nok else : paid = nok
# Précablage # Précablage
if ann_scol+1 in c.paiement() : paid = coul(paid,'f_vert') if ann_scol+1 in c.paiement() : paid = coul(paid,'f_vert')
machines = '' machines = ''
# Récupération des machines # Récupération des machines
for machine in c.machines() : for machine in c.machines() :
@ -248,13 +248,13 @@ def clubs_brief(clubs) :
else : k= '' else : k= ''
if machines : machines += ', ' + coul(nom,k) if machines : machines += ', ' + coul(nom,k)
else : machines = coul(nom,k) else : machines = coul(nom,k)
# Responsable # Responsable
resp = c.responsable().Nom() resp = c.responsable().Nom()
# Données # Données
data.append([c.id() , c.Nom(), c.local(), paid, resp, machines]) data.append([c.id() , c.Nom(), c.local(), paid, resp, machines])
return u"Machines en rouge = machines avec limitation de services\n" + \ return u"Machines en rouge = machines avec limitation de services\n" + \
u"P : signature charte année en cours, le fond vert indique le précâblage\n" + \ u"P : signature charte année en cours, le fond vert indique le précâblage\n" + \
tableau(data, tableau(data,
@ -262,7 +262,7 @@ def clubs_brief(clubs) :
largeur = [5, '*', 6, 1, 21, 15], largeur = [5, '*', 6, 1, 21, 15],
alignement = ['d', 'c', 'g', 'c', 'c', 'c']) alignement = ['d', 'c', 'g', 'c', 'c', 'c'])
def list_machines(machines) : def list_machines(machines) :
""" """
Formatage sous forme d'un tableau des propriétés de la liste de machine : Formatage sous forme d'un tableau des propriétés de la liste de machine :
@ -281,10 +281,10 @@ def list_machines(machines) :
for m in machines : for m in machines :
t, bl = __bases_machines(m) t, bl = __bases_machines(m)
# Données # Données
data.append([m.id(), t, m.nom().split('.')[0], m.ip(), m.mac(), bl]) data.append([m.id(), t, m.nom().split('.')[0], m.ip(), m.mac(), bl])
return tableau(data, return tableau(data,
titre = [u'mid', u'Type', u'Nom de machine', u'Adresse IP', u'Adresse MAC', u'Limitation'], titre = [u'mid', u'Type', u'Nom de machine', u'Adresse IP', u'Adresse MAC', u'Limitation'],
largeur = [5, 4, '*', 17, 19, 10], largeur = [5, 4, '*', 17, 19, 10],
@ -313,7 +313,7 @@ def list_bornes(bornes) :
for b in bornes : for b in bornes :
t, bl = __bases_machines(b) t, bl = __bases_machines(b)
if t != 'born' : continue if t != 'born' : continue
# Données # Données
try : try :
l = [x for x in b.info() if not x[0]=='<'][0] l = [x for x in b.info() if not x[0]=='<'][0]
@ -321,19 +321,19 @@ def list_bornes(bornes) :
l = l[0:11] l = l[0:11]
except : except :
l = u'????' l = u'????'
if borne_etat(b.nom()): if borne_etat(b.nom()):
etat = ok etat = ok
else: else:
etat = nok etat = nok
if '-' in b.puissance() : if '-' in b.puissance() :
puiss = coul(b.puissance(),'rouge') puiss = coul(b.puissance(),'rouge')
else : else :
puiss = b.puissance() puiss = b.puissance()
data.append([b.id(), b.nom().split('.')[0], b.ip(), b.mac(), etat, b.canal(), puiss, b.prise(), l]) data.append([b.id(), b.nom().split('.')[0], b.ip(), b.mac(), etat, b.canal(), puiss, b.prise(), l])
return u"Can=canaux, P=puissance, E=état\n" + \ return u"Can=canaux, P=puissance, E=état\n" + \
tableau(data, tableau(data,
titre = [u'mid', u'Nom', u'Adresse IP', u'Adresse MAC', u'E', u'Can', u'P', u'Pris', u'Lieu'], titre = [u'mid', u'Nom', u'Adresse IP', u'Adresse MAC', u'E', u'Can', u'P', u'Pris', u'Lieu'],
@ -349,10 +349,10 @@ def adher_details(adher) :
f+= coul(u'aid=%s ' % adher.id() ,'bleu') f+= coul(u'aid=%s ' % adher.id() ,'bleu')
# Nom, prenom # Nom, prenom
f += coul(u'Nom : ','gras') + "%s\n" % adher.Nom() f += coul(u'Nom : ','gras') + "%s\n" % adher.Nom()
# Mail # Mail
GL = RMH = u'' GL = RMH = u''
if adher.mail().find(u'@')!=-1 : if adher.mail().find(u'@')!=-1 :
f += coul(u'Adresse mail : ','gras') f += coul(u'Adresse mail : ','gras')
if adher.mail_invalide(): if adher.mail_invalide():
f += coul(adher.mail(),'rouge') f += coul(adher.mail(),'rouge')
@ -371,7 +371,7 @@ def adher_details(adher) :
GL = u' (%s)'%coul(u'GreyList','gris') GL = u' (%s)'%coul(u'GreyList','gris')
if adher.rewriteMailHeaders(): if adher.rewriteMailHeaders():
RMH = u' (%s)'%coul(u'réécriture en-têtes mail','gris') RMH = u' (%s)'%coul(u'réécriture en-têtes mail','gris')
alias = u', '.join([adher.canonical_alias()] + adher.alias()) alias = u', '.join([adher.canonical_alias()] + adher.alias())
if alias: if alias:
if alias[0] == u',': if alias[0] == u',':
@ -416,11 +416,11 @@ def adher_details(adher) :
else: else:
f += coul(u"cotisation %s/%d non réglée"% (ann_scol, ann_scol+1 ),'violet') f += coul(u"cotisation %s/%d non réglée"% (ann_scol, ann_scol+1 ),'violet')
jour = 0 jour = 0
if jour : if jour :
f += coul(u"à jour",'vert') f += coul(u"à jour",'vert')
f += '\n' f += '\n'
# Telephone # Telephone
tel = adher.tel() tel = adher.tel()
if tel != 'inconnu' : if tel != 'inconnu' :
@ -429,13 +429,13 @@ def adher_details(adher) :
except : except :
pass pass
f += coul(u'Numéro de téléphone : ','gras') + "%s\n" % tel.ljust(12) f += coul(u'Numéro de téléphone : ','gras') + "%s\n" % tel.ljust(12)
# Adresse # Adresse
chbre = adher.chbre() chbre = adher.chbre()
if chbre == 'EXT' : if chbre == 'EXT' :
# Adhérent extérieur # Adhérent extérieur
addr = adher.adresse() addr = adher.adresse()
if addr[0] : if addr[0] :
f += coul(u'Adresse : ','gras') f += coul(u'Adresse : ','gras')
f += addr[0] + u'\n' f += addr[0] + u'\n'
if addr[1] != ' ' : f += u' ' + addr[1] + u'\n' if addr[1] != ' ' : f += u' ' + addr[1] + u'\n'
@ -446,13 +446,13 @@ def adher_details(adher) :
# Chambre + prise (d'après annuaire) # Chambre + prise (d'après annuaire)
etat, vlans = prise_etat(adher.chbre()) etat, vlans = prise_etat(adher.chbre())
f += coul(u'Chambre : ','gras') + u"%s " % chbre f += coul(u'Chambre : ','gras') + u"%s " % chbre
f += u'(%s)' % etat f += u'(%s)' % etat
f += u'\n' f += u'\n'
# VLAN # VLAN
if vlans : if vlans :
f += coul(u'VLAN : ','gras') + u'%s' % vlans f += coul(u'VLAN : ','gras') + u'%s' % vlans
f += u'\n' f += u'\n'
# Études # Études
if adher.etudes(1).isdigit() : if adher.etudes(1).isdigit() :
f += coul(u'Études : ','gras')+ "%s %s%s\n" % \ f += coul(u'Études : ','gras')+ "%s %s%s\n" % \
@ -460,7 +460,7 @@ def adher_details(adher) :
elif adher.etudes(0) : elif adher.etudes(0) :
f += coul(u'Études : ','gras')+ "%s %s %s\n" % \ f += coul(u'Études : ','gras')+ "%s %s %s\n" % \
( adher.etudes(0), adher.etudes(1), adher.etudes(2) ) ( adher.etudes(0), adher.etudes(1), adher.etudes(2) )
# Solde # Solde
solde = adher.solde() solde = adher.solde()
if solde : if solde :
@ -470,20 +470,20 @@ def adher_details(adher) :
else : else :
f += str(solde).replace('.',',') f += str(solde).replace('.',',')
f += u" Euros\n" f += u" Euros\n"
# Role dans l'assoce # Role dans l'assoce
d = adher.droits() d = adher.droits()
if d : if d :
f += coul(u"Droits sur les serveurs : ",'gras') + ', '.join(d) f += coul(u"Droits sur les serveurs : ",'gras') + ', '.join(d)
if adher.droitsGeles(): if adher.droitsGeles():
f += coul(u" (droits gelés car pas cotisé cette année)",'bleu') f += coul(u" (droits gelés car pas cotisé cette année)",'bleu')
f += u'\n' f += u'\n'
# Paiement # Paiement
if adher.paiement() : if adher.paiement() :
if len(adher.paiement()) == 1 : if len(adher.paiement()) == 1 :
f += coul(u'Cotisation payée pour l\'année scolaire :','gras') f += coul(u'Cotisation payée pour l\'année scolaire :','gras')
else : else :
f += coul(u'Cotisation payée pour les années scolaires :','gras') f += coul(u'Cotisation payée pour les années scolaires :','gras')
g = u'' g = u''
for an in adher.paiement() : g += u" %i-%i" % ( an, an+1 ) for an in adher.paiement() : g += u" %i-%i" % ( an, an+1 )
@ -508,7 +508,7 @@ def adher_details(adher) :
f += _blacklist(adher) f += _blacklist(adher)
f += _info(adher) f += _info(adher)
f += _hist(adher) f += _hist(adher)
# Formatage des machines aussi # Formatage des machines aussi
f += coul(u'Machine(s) : ','gras') f += coul(u'Machine(s) : ','gras')
m = adher.machines() m = adher.machines()
@ -532,34 +532,34 @@ def ipsec_ok(machine) :
clients = [x.split("/")[0] for x in commands.getoutput("%snetstat -r -f encap | awk '($2 == \"0\") {print $6}'" % prefix).split("\n")] clients = [x.split("/")[0] for x in commands.getoutput("%snetstat -r -f encap | awk '($2 == \"0\") {print $6}'" % prefix).split("\n")]
globals()['clients_ipsec'] = clients globals()['clients_ipsec'] = clients
return machine.nom() in clients return machine.nom() in clients
def machine_details(machine) : def machine_details(machine) :
""" """
Formatage du détail des propriétés d'une machine Formatage du détail des propriétés d'une machine
""" """
f = '' f = ''
f+= coul(u'mid=%s ' % machine.id(),'bleu') f+= coul(u'mid=%s ' % machine.id(),'bleu')
# Type de machine # Type de machine
if isinstance(machine, MachineWifi): a = 'Machine wifi' if isinstance(machine, MachineWifi): a = 'Machine wifi'
elif isinstance(machine, BorneWifi): a = 'Borne wifi' elif isinstance(machine, BorneWifi): a = 'Borne wifi'
else: a = 'Machine fixe' else: a = 'Machine fixe'
f += coul(a + ' : ', 'gras') f += coul(a + ' : ', 'gras')
f+= "%s\n" % machine.nom() f+= "%s\n" % machine.nom()
# Alias ? # Alias ?
alias = machine.alias() alias = machine.alias()
if alias : if alias :
f += coul(u'Alias : ' ,'gras') + ', '.join(alias) f += coul(u'Alias : ' ,'gras') + ', '.join(alias)
f+= '\n' f+= '\n'
f+= coul(u'IP : ','gras') + "%s\t\t" %machine.ip() f+= coul(u'IP : ','gras') + "%s\t\t" %machine.ip()
f+= coul(u'MAC : ','gras') + "%s\n" %machine.mac() f+= coul(u'MAC : ','gras') + "%s\n" %machine.mac()
# Propriétaire # Propriétaire
f+= coul(u'Propriétaire : ','gras') f+= coul(u'Propriétaire : ','gras')
try : try :
f += machine.proprio + coul(' (adhérent détruit)', 'jaune') f += machine.proprio + coul(' (adhérent détruit)', 'jaune')
a = AssociationCrans() a = AssociationCrans()
except : except :
@ -567,12 +567,12 @@ def machine_details(machine) :
f += "%s" % a.Nom() f += "%s" % a.Nom()
if a.chbre() in ['EXT', '????']: if a.chbre() in ['EXT', '????']:
f += ' (%s = %s)' % (a.idn, a.id()) f += ' (%s = %s)' % (a.idn, a.id())
elif a.chbre() != 'CRA': elif a.chbre() != 'CRA':
f += " (%s)" % a.chbre() f += " (%s)" % a.chbre()
else : else :
f += coul(u'\t\tPrise : ','gras') + machine.prise() f += coul(u'\t\tPrise : ','gras') + machine.prise()
f+= '\n' f+= '\n'
if isinstance(machine, MachineCrans): if isinstance(machine, MachineCrans):
n = machine.nombrePrises() n = machine.nombrePrises()
if n >= 0: if n >= 0:
@ -580,12 +580,12 @@ def machine_details(machine) :
f += "%d\n" % n f += "%d\n" % n
# Adhérent blacklisté ? # Adhérent blacklisté ?
bl = a.blacklist_actif() bl = a.blacklist_actif()
if bl : if bl :
f += coul(u'Restrictions sur adhérent : ','gras') f += coul(u'Restrictions sur adhérent : ','gras')
f += coul(u', '.join(bl),'rouge') f += coul(u', '.join(bl),'rouge')
f += '\n' f += '\n'
# Borne wifi # Borne wifi
if isinstance(machine, BorneWifi): if isinstance(machine, BorneWifi):
f += coul(u'Hotspot : ', 'gras') f += coul(u'Hotspot : ', 'gras')
@ -602,10 +602,10 @@ def machine_details(machine) :
f += coul(u'VLANs : ', 'gras') f += coul(u'VLANs : ', 'gras')
from hptools import sw_prise from hptools import sw_prise
f += ', '.join(sw_prise(machine.prise()).vlans()) f += ', '.join(sw_prise(machine.prise()).vlans())
f += '\n' f += '\n'
except: except:
pass pass
f += coul(u'Puissance : ','gras') + u"%4.d" % int(machine.puissance()) f += coul(u'Puissance : ','gras') + u"%4.d" % int(machine.puissance())
f += coul(u'\tCanaux : ', 'gras') + machine.canal() f += coul(u'\tCanaux : ', 'gras') + machine.canal()
f += coul(u'\tÉtat : ', 'gras') f += coul(u'\tÉtat : ', 'gras')
@ -654,11 +654,11 @@ def machine_details(machine) :
if machine.nvram(): if machine.nvram():
f += coul(u'NVRAM : ', 'gras') f += coul(u'NVRAM : ', 'gras')
f += ', '.join(machine.nvram()) + '\n' f += ', '.join(machine.nvram()) + '\n'
if aff_ipsec and isinstance(machine, MachineWifi): if aff_ipsec and isinstance(machine, MachineWifi):
f += coul(u'Clef IPsec : ','gras') + machine.ipsec() f += coul(u'Clef IPsec : ','gras') + machine.ipsec()
f += '\n' f += '\n'
# Ports spéciaux # Ports spéciaux
if machine.portTCPin(): if machine.portTCPin():
f += coul(u'Ports TCP ouvert ext->machine : ','gras') + ' '.join(machine.portTCPin()) + '\n' f += coul(u'Ports TCP ouvert ext->machine : ','gras') + ' '.join(machine.portTCPin()) + '\n'
@ -676,7 +676,7 @@ def machine_details(machine) :
f += _blacklist(machine) f += _blacklist(machine)
f += _info(machine) f += _info(machine)
f += _hist(machine) f += _hist(machine)
return f return f
def club_details(club) : def club_details(club) :
@ -688,7 +688,7 @@ def club_details(club) :
f+= coul(u'cid=%s ' % club.id() ,'bleu') f+= coul(u'cid=%s ' % club.id() ,'bleu')
# Nom # Nom
f += coul(u'Nom : ','gras') + "%s\n" % club.Nom() f += coul(u'Nom : ','gras') + "%s\n" % club.Nom()
# responsale # responsale
f += coul(u'Responsable : ','gras') + "%s\n" % club.responsable().Nom() f += coul(u'Responsable : ','gras') + "%s\n" % club.responsable().Nom()
@ -704,11 +704,11 @@ def club_details(club) :
if not jour : f += ' et ' if not jour : f += ' et '
f += coul(u"charte %s/%d non signée"% (ann_scol, ann_scol+1 ),'violet') f += coul(u"charte %s/%d non signée"% (ann_scol, ann_scol+1 ),'violet')
jour = 0 jour = 0
if jour : if jour :
f += coul(u"à jour",'vert') f += coul(u"à jour",'vert')
f += '\n' f += '\n'
# Chambre + prise # Chambre + prise
etat, vlans = prise_etat(club.chbre()) etat, vlans = prise_etat(club.chbre())
f += coul(u'Local : ','gras') + "%s " % club.local() f += coul(u'Local : ','gras') + "%s " % club.local()
@ -718,7 +718,7 @@ def club_details(club) :
if vlans : if vlans :
f += coul(u'VLAN : ','gras') + u'%s' % vlans f += coul(u'VLAN : ','gras') + u'%s' % vlans
f += u'\n' f += u'\n'
# Paiement # Paiement
if club.paiement() : if club.paiement() :
f += coul(u'Charte signée pour les années scolaires :','gras') f += coul(u'Charte signée pour les années scolaires :','gras')
@ -733,7 +733,7 @@ def club_details(club) :
if login : if login :
f += coul(u'Login : ','gras') + login f += coul(u'Login : ','gras') + login
alias = club.alias() alias = club.alias()
if alias : if alias :
f += coul(u'\tAlias : ','gras') + ', '.join(alias) f += coul(u'\tAlias : ','gras') + ', '.join(alias)
f+= u'\n' f+= u'\n'
@ -781,14 +781,14 @@ def _blacklist(clas):
dates = u'du %s au ' % dates dates = u'du %s au ' % dates
dates += strftime('%d/%m/%Y %H:%M', localtime(int(event[1]))) dates += strftime('%d/%m/%Y %H:%M', localtime(int(event[1])))
f += u"%s\n\t " % coul(u'%s : %s [%s]' % (dates, event[2], event[3]), c) f += u"%s\n\t " % coul(u'%s : %s [%s]' % (dates, event[2], event[3]), c)
f = f[:-6] # supression des espaces superflus f = f[:-6] # supression des espaces superflus
if f: if f:
return coul(u'Blackliste : ', 'gras') + f return coul(u'Blackliste : ', 'gras') + f
else: else:
return '' return ''
def _info(clas) : def _info(clas) :
""" Formatage des remarques de la classe fournie """ """ Formatage des remarques de la classe fournie """
f= u'' f= u''
@ -812,7 +812,7 @@ def _hist(clas) :
a = h[i] # Produit une erreur si i trop grand a = h[i] # Produit une erreur si i trop grand
if i !=0 : f += ' ' if i !=0 : f += ' '
try: try:
# on force l'encodage ici sinon il est fait au moment de l'impression a # on force l'encodage ici sinon il est fait au moment de l'impression a
# l'ecran et il empeche l'affichage de toutes les infos # l'ecran et il empeche l'affichage de toutes les infos
f += u'%s\n' % a.encode("iso-8859-15").decode("iso-8859-15") f += u'%s\n' % a.encode("iso-8859-15").decode("iso-8859-15")
except Exception, e: except Exception, e:
@ -826,25 +826,25 @@ def _hist(clas) :
if h[i+1] : f += ' [...]\n' if h[i+1] : f += ' [...]\n'
except : except :
None None
return f return f
def __bases_machines(m) : def __bases_machines(m) :
""" Retourne [ type de la machines, blacklist ] """ """ Retourne [ type de la machines, blacklist ] """
#Type #Type
if isinstance(m, MachineWifi): t = 'wifi' if isinstance(m, MachineWifi): t = 'wifi'
elif isinstance(m, BorneWifi): t = 'born' elif isinstance(m, BorneWifi): t = 'born'
else : t='fixe' else : t='fixe'
# Déconnectée ? # Déconnectée ?
b = m.blacklist_actif() b = m.blacklist_actif()
if not b : if not b :
bl = '-' bl = '-'
elif len(b) == 1 : elif len(b) == 1 :
bl = coul(b[0],'rouge') bl = coul(b[0],'rouge')
else : else :
bl = coul(u'cf détails','rouge') bl = coul(u'cf détails','rouge')
return t , bl return t , bl
def borne_etat(borne) : def borne_etat(borne) :
@ -937,7 +937,7 @@ def prise_etat(chbre) :
count += 1 count += 1
elif not prise.is_enable() : elif not prise.is_enable() :
f+= u', ' + coul(u'prise désactivée','rouge') f+= u', ' + coul(u'prise désactivée','rouge')
else : else :
f+= u', activée, lien non détecté' f+= u', activée, lien non détecté'
except ConversationError, r: except ConversationError, r:
# Switch non manageable ou down # Switch non manageable ou down
@ -975,12 +975,12 @@ def __usage() :
for c in base.auto_search_champs.values(): for c in base.auto_search_champs.values():
for champ in c: for champ in c:
if champ not in champs: if champ not in champs:
champs.append(champ) champs.append(champ)
for champ in champs: for champ in champs:
coul_champ = coul(champ, "bleu") coul_champ = coul(champ, "bleu")
if accu == "": if accu == "":
accu = coul_champ accu = coul_champ
longueur = len(champ) longueur = len(champ)
elif longueur + 2 + len(champ) < 80: elif longueur + 2 + len(champ) < 80:
longueur += 2 + len(champ) longueur += 2 + len(champ)
accu += ", " + coul_champ accu += ", " + coul_champ
@ -994,7 +994,7 @@ def __usage() :
for c in base.non_auto_search_champs.values(): for c in base.non_auto_search_champs.values():
for champ in c: for champ in c:
if champ not in champs: if champ not in champs:
champs.append(champ) champs.append(champ)
for champ in champs: for champ in champs:
if longueur + 2 + len(champ) < 80: if longueur + 2 + len(champ) < 80:
longueur += 2 + len(champ) longueur += 2 + len(champ)
@ -1006,7 +1006,7 @@ def __usage() :
# Dernière ligne # Dernière ligne
liste.append(accu) liste.append(accu)
cprint(__doc__ % { 'prog': sys.argv[0].split('/')[-1].split('.')[0], cprint(__doc__ % { 'prog': sys.argv[0].split('/')[-1].split('.')[0],
'champs_rech': '\n'.join(liste), 'champs_rech': '\n'.join(liste),
'limit_aff_details': limit_aff_details, 'limit_aff_details': limit_aff_details,
@ -1018,7 +1018,7 @@ def __recherche() :
Recherche et affichage des résultats à partir des options founies (sys.argv) Recherche et affichage des résultats à partir des options founies (sys.argv)
""" """
global aff_ipsec, limit_aff_details, limit_aff_historique, debug global aff_ipsec, limit_aff_details, limit_aff_historique, debug
# Récupération des options # Récupération des options
if len(sys.argv) == 1 : if len(sys.argv) == 1 :
# Pas d'option fournie # Pas d'option fournie
@ -1028,8 +1028,8 @@ def __recherche() :
options, arg = getopt.getopt(sys.argv[1:], 'hamctbil:L:', [ 'debug', 'help', 'adherent', 'machine', 'club' , 'tech', 'bornes', 'limit=', 'limit-historique=', 'ipsec', 'crans' ]) options, arg = getopt.getopt(sys.argv[1:], 'hamctbil:L:', [ 'debug', 'help', 'adherent', 'machine', 'club' , 'tech', 'bornes', 'limit=', 'limit-historique=', 'ipsec', 'crans' ])
except getopt.error, msg : except getopt.error, msg :
__usage_brief(unicode(msg)) __usage_brief(unicode(msg))
# Traitement des options # Traitement des options
only_adh=0 only_adh=0
only_mac=0 only_mac=0
@ -1037,7 +1037,7 @@ def __recherche() :
only_bornes=0 only_bornes=0
only_crans=0 only_crans=0
mtech = 0 mtech = 0
for opt, val in options : for opt, val in options :
if opt == '-h' or opt=='--help' : if opt == '-h' or opt=='--help' :
__usage() __usage()
@ -1075,7 +1075,7 @@ def __recherche() :
# Recherche initiale sans critère # Recherche initiale sans critère
arg = [ 'canal=*&host=*.crans.org'] arg = [ 'canal=*&host=*.crans.org']
elif arg[0].find('=')!=-1 : elif arg[0].find('=')!=-1 :
# Recherche avec critères # Recherche avec critères
arg += [ '&canal=*' ] arg += [ '&canal=*' ]
elif opt in [ '-t', '--tech' ] : elif opt in [ '-t', '--tech' ] :
# Format affichage des machines # Format affichage des machines
@ -1083,7 +1083,7 @@ def __recherche() :
elif opt in [ '-i', '--ipsec' ] : elif opt in [ '-i', '--ipsec' ] :
# Affichage des clefs ipsec # Affichage des clefs ipsec
aff_ipsec = 1 aff_ipsec = 1
if only_adh + only_mac + only_club + only_bornes > 1 : if only_adh + only_mac + only_club + only_bornes > 1 :
__usage_brief(u'Options utilisées incompatibles') __usage_brief(u'Options utilisées incompatibles')
@ -1110,7 +1110,7 @@ def __recherche() :
#cprint(u"Recherche sur chambre %s" % chbre) #cprint(u"Recherche sur chambre %s" % chbre)
arg = u'chbre=%s' % chbre arg = u'chbre=%s' % chbre
# sinon on ne fait rien et on recherche sur le champ prise # sinon on ne fait rien et on recherche sur le champ prise
try: try:
if only_crans : if only_crans :
res = { 'machine' : AssociationCrans().machines() , 'adherent' : [] , 'club' : [] } res = { 'machine' : AssociationCrans().machines() , 'adherent' : [] , 'club' : [] }
@ -1121,7 +1121,7 @@ def __recherche() :
res = base.search(arg) res = base.search(arg)
except ValueError, c : except ValueError, c :
__usage_brief(c.args[0]) __usage_brief(c.args[0])
# Traitement du résultat # Traitement du résultat
if not res['adherent'] and not res['machine'] and not res['club']: if not res['adherent'] and not res['machine'] and not res['club']:
# Pas de résultat dans la base # Pas de résultat dans la base
@ -1160,14 +1160,14 @@ def __recherche() :
elif res['club'] : elif res['club'] :
cprint(u'Aucun résultat à afficher') cprint(u'Aucun résultat à afficher')
sys.exit(4) sys.exit(4)
elif only_mac : elif only_mac :
if res['machine'] : aff(res['machine'],mtech) if res['machine'] : aff(res['machine'],mtech)
else : else :
to_aff = [] to_aff = []
for a in res['adherent'] + res['club'] : for a in res['adherent'] + res['club'] :
to_aff += a.machines() to_aff += a.machines()
aff(to_aff) aff(to_aff)
elif only_club : elif only_club :
if res['club'] : aff(res['club']) if res['club'] : aff(res['club'])
elif res['machine'] : elif res['machine'] :
to_aff=[] to_aff=[]
@ -1196,15 +1196,15 @@ def __recherche() :
if res['club']: if res['club']:
cprint(u"Résultats trouvés parmi les clubs :", 'cyan') cprint(u"Résultats trouvés parmi les clubs :", 'cyan')
aff(res['club']) aff(res['club'])
if __name__ == '__main__' : if __name__ == '__main__' :
global debug global debug
debug = 0 debug = 0
import sys, getopt import sys, getopt
base = crans_ldap() base = crans_ldap()
try : try :
__recherche() __recherche()
except KeyboardInterrupt : except KeyboardInterrupt :
@ -1215,7 +1215,7 @@ if __name__ == '__main__' :
sys.exit(c) sys.exit(c)
except : except :
cprint(u"""Une erreur fatale s'est produite durant l'exécution. cprint(u"""Une erreur fatale s'est produite durant l'exécution.
Pour l'amélioration de ce programme merci de prévenir nounou en spécifiant la Pour l'amélioration de ce programme merci de prévenir nounou en spécifiant la
marche à suivre pour reproduire cette erreur.""") marche à suivre pour reproduire cette erreur.""")
if debug : if debug :
cprint('-'*40) cprint('-'*40)