[gestion/*.py] Ré-encodage de certains scripts en UTF-8

Ignore-this: dafa22ed56eaf0d816fd089e42672eb5

darcs-hash:20090309212124-0445d-09ac8ae4052b6f333706be1baa1c7f4d94455fd5.gz
This commit is contained in:
Stephane Glondu 2009-03-09 22:21:24 +01:00
parent 7addc503a8
commit cc31727b60
21 changed files with 1351 additions and 1351 deletions

View file

@ -1,15 +1,15 @@
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
# -*- coding: utf-8 -*-
""" Collection de fonction/classe pour avoir un bel affichage
Copyright (C) Frédéric Pauget
Copyright (C) Frédéric Pauget
Licence : GPLv2
"""
import sys, re, os, tempfile
# Détermination de l'encodage
# Détermination de l'encodage
encoding = None
try:
from locale import getpreferredencoding
@ -20,7 +20,7 @@ except:
if not encoding:
encoding = sys.stdin.encoding or "ISO-8859-15"
# Si aucune locale n'est définie, on se met en ISO-8859-15
# Si aucune locale n'est définie, on se met en ISO-8859-15
if encoding == "ANSI_X3.4-1968":
encoding = "ISO-8859-15"
@ -32,13 +32,13 @@ else:
stdout_atty = sys.stdout.isatty()
def dialog(backtitle,arg,dialogrc='') :
""" Affiche la boite de dialogue défine avec les arguments fournis
""" Affiche la boite de dialogue défine avec les arguments fournis
(cf man dialog)
si tout se déroule bien retourne :
si tout se déroule bien retourne :
[ 0, [ reponse(s) ] ]
si annulatin retourne :
[ 1, [] ]
si appui sur ESC demande confirmation de l'abandon et exécute sys.exit(0)
si appui sur ESC demande confirmation de l'abandon et exécute sys.exit(0)
si erreur dans les arguments raise RuntimeError
"""
f = tempfile.NamedTemporaryFile()
@ -49,7 +49,7 @@ def dialog(backtitle,arg,dialogrc='') :
# Annuler
f.close()
return [ 1, [] ]
# Lecture du fichier de résultat et effacement
# Lecture du fichier de résultat et effacement
try:
result=f.readlines()
f.close()
@ -62,7 +62,7 @@ def dialog(backtitle,arg,dialogrc='') :
raise RuntimeError( arg, result[1].strip() )
elif res==65280 :
# Appui sur ESC
arg1 = u'--title "Annulation" --yesno "Quitter ?\nLes dernières modifications seront perdues." 6 48'
arg1 = u'--title "Annulation" --yesno "Quitter ?\nLes dernières modifications seront perdues." 6 48'
print backtitle
cmd = u'%s /usr/bin/dialog --backtitle "%s" %s' % (dialogrc, backtitle,arg1)
res = os.system(cmd.encode('iso-8859-15','ignore') )
@ -73,8 +73,8 @@ def dialog(backtitle,arg,dialogrc='') :
def coul(txt, col=None):
"""
Retourne la chaine donnée encadrée des séquences qui
vont bien pour obtenir la couleur souhaitée
Retourne la chaine donnée encadrée des séquences qui
vont bien pour obtenir la couleur souhaitée
Les couleur sont celles de codecol
Il est possible de changer la couleur de fond grace aux couleur f_<couleur>
"""
@ -123,7 +123,7 @@ def cprint(txt, col='blanc', newline=True):
def tableau(data, titre=None, largeur=None, alignement=None, format=None):
"""
Retourne une chaine formatée repésentant un tableau.
Retourne une chaine formatée repésentant un tableau.
data : liste de listes, chacune contenant les valeurs d'une ligne
@ -132,7 +132,7 @@ def tableau(data, titre=None, largeur=None, alignement=None, format=None):
largeur : liste des largeurs des colonnes, '*' met la plus grande
largeur possible.
Si None, réduit aux max chaque colonne
Si None, réduit aux max chaque colonne
alignement : liste des alignements : c = centrer
g = gauche
@ -149,7 +149,7 @@ def tableau(data, titre=None, largeur=None, alignement=None, format=None):
elif titre :
nbcols = len(titre)
else :
return u'Aucune donnée'
return u'Aucune donnée'
# Formats
#########
@ -195,12 +195,12 @@ def tableau(data, titre=None, largeur=None, alignement=None, format=None):
# Alignement
if l > largeur :
# découpage d'une chaine trop longue
# découpage d'une chaine trop longue
regexp = re.compile('\x1b\[1;([0-9]|[0-9][0-9])m')
new_data = u''
new_len = 0
# On laisse la mise en forme et on coupe les caratères affichés
# On laisse la mise en forme et on coupe les caratères affichés
while True :
s = regexp.search(data)
if s and not s.start() :
@ -208,12 +208,12 @@ def tableau(data, titre=None, largeur=None, alignement=None, format=None):
new_data += data[:s.end()]
data = data[s.end():]
elif new_len < largeur - 1 :
# c'est un caratère normal, et il y a la place
# c'est un caratère normal, et il y a la place
new_data += data[0]
data = data[1:]
new_len += 1
else :
# c'est un caratère normal mais on a dépassé le max
# c'est un caratère normal mais on a dépassé le max
data = data[1:]
if not data :
return new_data + '*'
@ -237,19 +237,19 @@ def tableau(data, titre=None, largeur=None, alignement=None, format=None):
if titre :
# ligne de titre
chaine = sep_col + sep_col.join([aligne(titre[i],'c',largeur[i]) for i in range(nbcols)]) + sep_col + u'\n'
# ligne de séparation
# ligne de séparation
chaine += sep_col + u'+'.join([u'-'*largeur[i] for i in range(nbcols)]) + sep_col + u'\n'
else :
chaine = u''
# Les données
# Les données
#############
chaine += u'\n'.join([sep_col + sep_col.join([ligne[i] for i in range(nbcols)]) + sep_col for ligne in data])
return chaine
def get_screen_size():
"""Retourne la taille de l'écran.
"""Retourne la taille de l'écran.
Sous la forme d'un tuble (lignes, colonnes)"""
@ -265,7 +265,7 @@ def get_screen_size():
def prompt(prompt, defaut='', couleur='gras'):
u"""
Pose la question prompt en couleur (défaut gras), retourne la réponse.
Pose la question prompt en couleur (défaut gras), retourne la réponse.
"""
sys.stdout.write(coul(prompt, couleur).encode(encoding))
if defaut :
@ -276,12 +276,12 @@ def prompt(prompt, defaut='', couleur='gras'):
return v
class anim :
""" Permet de créer une animation :
""" Permet de créer une animation :
truc................./
truc.................-
truc.................\
truc.................|
ou une barre de progression si le nombre total d'itérations est founi.
ou une barre de progression si le nombre total d'itérations est founi.
"""
def __init__(self,truc,iter=0) :
""" Affichage de :
@ -304,7 +304,7 @@ class anim :
def cycle(self) :
""" Efface la ligne courrante et
affiche : truc..................?
? caratère variant à chaque appel """
? caratère variant à chaque appel """
sys.stdout.write(el + self.txt)
if self.iter!=0 :
sys.stdout.write('[')

View file

@ -1,5 +1,5 @@
#! /usr/bin/env python
# -*- coding: iso-8859-15 -*-
# -*- coding: utf-8 -*-
#
# $Id: ajoute_chambre.py,v 1.2 2007-02-24 01:08:45 dimino Exp $
#
@ -25,7 +25,7 @@
#
#
# Description:
# Ajoute une chambre sur une prise libre (fait pour le batiment g à la base)
# Ajoute une chambre sur une prise libre (fait pour le batiment g à la base)
#
import sys, os
@ -35,14 +35,14 @@ sys.path.append('/usr/scripts/gestion')
from annuaires import chbre_prises, reverse, bat_switchs
from affich_tools import cprint
# C'est juste pour le déboggage
# C'est juste pour le déboggage
__fichier_annuaire = "/usr/scripts/gestion/annuaires.py"
def assigne_chambre(prise, chbre):
""" Assigne une chambre à une prise.
""" Assigne une chambre à une prise.
prise doit être de la forme bnnn[g/d], ou nnn[g/d], dans ce dernier cas le bâtiment est le g.
prise doit être de la forme bnnn[g/d], ou nnn[g/d], dans ce dernier cas le bâtiment est le g.
"""
if len(chbre) != 3 or not chbre.isdigit():
@ -75,7 +75,7 @@ prise doit
# if chambre != 'XXX':
# return 'prise_utilisee'
# Ajout effectif de la chambre sur la prise donnée
# Ajout effectif de la chambre sur la prise donnée
annuaire = open(__fichier_annuaire, 'r')
tampon = annuaire.read()
@ -109,15 +109,15 @@ prise doit
if not user:
user = os.getenv('USER') or "inconnu"
# Vu que ça va être mis dans la ligne de commande éxécuter après,
# autant être parano.
# Vu que ça va être mis dans la ligne de commande éxécuter après,
# autant être parano.
for c in user:
if not (c.isalnum or c in [ '-', '_' ]):
user = "(uid=%d)" % (os.getuid())
break
os.system('cd /usr/scripts/gestion && /usr/bin/cvs commit %s \
-m "ajoute_chambre.py: chambre %s%s ajouté sur la prise %s%s par %s"' %
-m "ajoute_chambre.py: chambre %s%s ajouté sur la prise %s%s par %s"' %
(__fichier_annuaire, bat, chbre, bat, prise, user))
@ -133,18 +133,18 @@ def __aide():
""" Aide """
cprint(u"""Usage: %s [OPTIONS] <prise> <chambre>
Ajoute une chambre sur une prise qui n'était pas encore utilisé.
Ajoute une chambre sur une prise qui n'était pas encore utilisé.
Options:
-h, --help affiche cette aide
<prise> doit être de la forme bnnn ou nnn :
- B est le batiment (g si non spécifié)
- nnn est le numéro de la prise
<prise> doit être de la forme bnnn ou nnn :
- B est le batiment (g si non spécifié)
- nnn est le numéro de la prise
<chambre> doit être de la forme nnn
<chambre> doit être de la forme nnn
Rapporter toutes anomalies à <dimino@crans.org>.""" % sys.argv[0].split('/')[-1].split('.')[0])
Rapporter toutes anomalies à <dimino@crans.org>.""" % sys.argv[0].split('/')[-1].split('.')[0])
sys.exit(0)
@ -173,7 +173,7 @@ if __name__ == '__main__':
__usage(u"Format de la chambre invalide")
elif resultat == 'chambre_deja_cablee':
__usage(u"La chambre est déjà cablée")
__usage(u"La chambre est déjà cablée")
elif resultat == 'batiment_inconnu':
__usage(u"Le batiment n'existe pas")
@ -182,11 +182,11 @@ if __name__ == '__main__':
__usage(u"La prise n'existe pas")
elif resultat == 'prise_utilisee':
__usage(u"La prise est déjà utilisée")
__usage(u"La prise est déjà utilisée")
elif resultat == 'prise_introuvable':
cprint(u"""La prise n'a pas été trouvé dans l'annuaire.
Vérifiez que vous avez bien mis le numéro de prise et de chambre.""")
cprint(u"""La prise n'a pas été trouvé dans l'annuaire.
Vérifiez que vous avez bien mis le numéro de prise et de chambre.""")
elif resultat == 'fichier_annuaire_invalide':
cprint(u"Le fichier d'annuaire n'est pas reconnu, envoyer un mail à dimino@crans.org")
cprint(u"Le fichier d'annuaire n'est pas reconnu, envoyer un mail à dimino@crans.org")

View file

@ -1,7 +1,7 @@
#!/usr/bin/python
# -*- coding: iso-8859-15 -*-
# -*- coding: utf-8 -*-
# Liste des bâtiments avec switch manageables
# Liste des bâtiments avec switch manageables
bat_switchs = [ 'a' , 'b' , 'c' , 'h' , 'i' , 'j' , 'm' , 'p']
bat_manuels = [ 'o' , 'r' ] # Y en a plus aucun :) ou presque
@ -9,8 +9,8 @@ aide={
'g' : "appart du RDC=G901"
}
# Toute chambre ne commencant pas par 3 chiffres sera considéré comme un local club
# En conséquence les locaux club ne devront pas commencer par 3 chiffres.
# Toute chambre ne commencant pas par 3 chiffres sera considéré comme un local club
# En conséquence les locaux club ne devront pas commencer par 3 chiffres.
#Pour le G :
# le signe - indique un cable 10 Mbps
@ -52,8 +52,8 @@ chbre_prises={ 'a' :
'603d':'301', '608d':'302', 'cl6':'303'},
# Le local club du 6ème et les chambres A608d, A603d sont sur la
# prise 202 (switch au 6ème dans le local technique à coté de
# Le local club du 6ème et les chambres A608d, A603d sont sur la
# prise 202 (switch au 6ème dans le local technique à coté de
# l'ascensseur
'b' :
@ -465,11 +465,11 @@ chbre_prises={ 'a' :
'XXX':'641' , 'XXX':'642' , 'XXX':'643' , 'XXX':'644' ,
'XXX':'645' , 'XXX':'646', 'XXX':'647' , 'XXX':'648' ,
# Ce switch n'est pas au bâtiment G comme on pourrait le croire
# Ce switch n'est pas au bâtiment G comme on pourrait le croire
'999':'701' , '998':'702' , '997':'703' , '996':'704'}
}
# Prises d'uplink, de machines du crans / Prises d'utilité CRANS
# Prises d'uplink, de machines du crans / Prises d'utilité CRANS
uplink_prises={ 'a' :
{ 49 : 'uplink->backbone', 50 : 'uplink->bata-1',
149 : 'uplink->bata-0', 150 : 'uplink->bata-2',
@ -535,8 +535,8 @@ def reverse(bat) :
def all_switchs(bat=None):
"""Retourne la liste des switchs pour un batiment.
Si bat est donné, seulement pour le bâtiment demandé, sinon pour
tous les bâtiments. bat peut être une liste aussi. Le backbone n'est
Si bat est donné, seulement pour le bâtiment demandé, sinon pour
tous les bâtiments. bat peut être une liste aussi. Le backbone n'est
pas pris en compte. La convention est batx-y sauf si y=0 et on a donc
simplement batx"""
def cmp(x,y):
@ -568,7 +568,7 @@ def locaux_clubs() :
'Mcl0' : 'Shape',
'Mcl1' : 'Krobot',
'EXT' : 'EXT' }
# Ajout des locaux d'étage A, B et C
# Ajout des locaux d'étage A, B et C
for b in 'ABC' :
for i in range(2,7) :
locaux_clubs['%scl%i' % ( b, i)] = '%i@%s' % (i, b)

View file

@ -1,9 +1,9 @@
#! /usr/bin/env python
# -*- coding: iso-8859-15 -*-
# -*- coding: utf-8 -*-
# Serveur SSL qui renvoie la MAC correspondant à une IP
# Ce serveur est utilisé sur Nectaris par les bornes wifi pour faire
# les requêtes ARP.
# Serveur SSL qui renvoie la MAC correspondant à une IP
# Ce serveur est utilisé sur Nectaris par les bornes wifi pour faire
# les requêtes ARP.
# Lancement : twistd -n -y arp.py --pidfile=/var/run/arp.pid
# Pas de -n pour qu'il passe en fond
@ -29,18 +29,18 @@ import re
class ServerContextFactory(ContextFactory):
def getContext(self):
"""Création d'un contexte SSL côté serveur."""
"""Création d'un contexte SSL côté serveur."""
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.use_certificate_file('/etc/ssl/certs/nectaris.pem')
ctx.use_privatekey_file('/etc/ssl/private/nectaris.pem')
return ctx
class ARPProtocol(basic.LineReceiver):
"""Protocole de communication pour récupérer une adresse MAC.
"""Protocole de communication pour récupérer une adresse MAC.
Chaque lignee reçue contient une adresse IP et le serveur répond
Chaque lignee reçue contient une adresse IP et le serveur répond
avec l'adresse MAC correspondante ou avec `unknown' si celle-ci
est inconnue (ou non autorisée).
est inconnue (ou non autorisée).
"""
def lineReceived(self, IP):
self.factory.getMac(IP
@ -51,7 +51,7 @@ class ARPProtocol(basic.LineReceiver):
def answerMac(self, m):
"""Renvoie au client la bonne adresse MAC.
`m' peut être None.
`m' peut être None.
"""
if m:
return self.transport.write(str(m) + "\r\n")
@ -59,7 +59,7 @@ class ARPProtocol(basic.LineReceiver):
return self.transport.write("unknown\r\n")
class ARPFactory(protocol.ServerFactory):
"""Backend du serveur. Effectue la résolution IP/MAC."""
"""Backend du serveur. Effectue la résolution IP/MAC."""
protocol = ARPProtocol
def __init__(self, network='0.0.0.0/0'):
@ -70,26 +70,26 @@ class ARPFactory(protocol.ServerFactory):
return defer.succeed(self._getMac(IP))
def _getMac(self, IP):
"""Fonction réelle, synchrone, qui obtient l'adresse MAC."""
"""Fonction réelle, synchrone, qui obtient l'adresse MAC."""
try:
if AddrInNet(IP, self.network):
results = self.ldap.search('ip=%s' % IP)['machine']
if results:
# On a au moins un résultat, on retourne le premier
# On a au moins un résultat, on retourne le premier
return results[0].mac().strip()
else:
# On a rien
return None
else:
# L'IP n'est pas autorisée
# L'IP n'est pas autorisée
return None
except ValueError:
# A priori, ce n'était pas une IP
# A priori, ce n'était pas une IP
return None
# Corps du programme
# On écoute sur le port 5243 et on ne répond qu'aux requêtes concernant le
# sous-réseau wifi
# On écoute sur le port 5243 et on ne répond qu'aux requêtes concernant le
# sous-réseau wifi
application = service.Application('arp')
factory = ARPFactory('138.231.148.0/21')
# Remplacer SSL par TCP pour ne pas utiliser SSL et virer ServerContextFactory

View file

@ -1,5 +1,5 @@
#! /usr/bin/env python
# -*- coding: iso-8859-15 -*-
# -*- coding: utf-8 -*-
"""
Script de changement de mots de passe LDAP
@ -7,14 +7,14 @@ Script de changement de mots de passe LDAP
Utilisation :
* cas 1 : sans arguements par un utlisateur lambda :
changement de son propre mdp
* cas 2 : avec argument par un utilisateur ayant accès
total à la base LDAP (respbats) mais PAS ROOT :
changement du mdp de l'adhérent fourni en argument,
impossibilité de modifier le mdp d'un compte privilégié
* cas 3 : lancé par root : possibilité de modifier
* cas 2 : avec argument par un utilisateur ayant accès
total à la base LDAP (respbats) mais PAS ROOT :
changement du mdp de l'adhérent fourni en argument,
impossibilité de modifier le mdp d'un compte privilégié
* cas 3 : lancé par root : possibilité de modifier
tous les mots de passe LDAP
Copyright (C) Frédéric Pauget
Copyright (C) Frédéric Pauget
Licence : GPLv2
"""
@ -33,17 +33,17 @@ uri = 'ldap://ldap.adm.crans.org'
syslog.openlog('chgpass',syslog.LOG_PID,syslog.LOG_AUTH)
def decode64(chaine):
""" Décode une chaine de caratère utf8/64 et retourne un unicode """
""" Décode une chaine de caratère utf8/64 et retourne un unicode """
try:
return base64.decodestring(chaine).decode('utf8','ignore')
except:
return chaine.decode('utf8','ignore')
def chgpass(dn) :
cprint(u"""Le nouveau mot de passe doit comporter au minimum 6 caractères.
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 "Le mot de passe tapé ne sera pas écrit à l'écran."
cprint(u"""Le nouveau mot de passe doit comporter au minimum 6 caractères.
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 "Le mot de passe tapé ne sera pas écrit à l'écran."
print "Taper Ctrl-D pour abandonner"
try :
@ -60,17 +60,17 @@ Il ne doit pas
try:
mdp = mdp.encode('ascii')
except UnicodeEncodeError:
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')
continue
## 2bis - On évite une attaque de type injection de code shell
## 2bis - On évite une attaque de type injection de code shell
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')
continue
## 3 - assez de caractères de types différents ?
## 3 - assez de caractères de types différents ?
chiffres = 0
majuscules = 0
minuscules = 0
@ -94,9 +94,9 @@ Il ne doit pas
test = commands.getoutput("echo '%s' | /usr/sbin/crack_testlib" % mdp)
if test.split(':')[-1] != ' ok' :
commentaire = {
' 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 too simplistic/systematic': u'Le mot de passe est trop simple/répétitif'
' 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 too simplistic/systematic': u'Le mot de passe est trop simple/répétitif'
}.get(test.split(':')[-1],test.split(':')[-1])
cprint(commentaire, 'rouge')
continue
@ -104,7 +104,7 @@ Il ne doit pas
### On redemande le mot de passe
mdp1 = getpass.getpass('Retaper mot de passe : ')
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
break
@ -114,7 +114,7 @@ Il ne doit pas
cprint(u'Erreur lors du changement de mot de passe', 'rouge')
syslog.syslog("LDAP password changed for dn=%s" % dn)
else :
cprint(u'Changement effectué avec succès', u'vert')
cprint(u'Changement effectué avec succès', u'vert')
except KeyboardInterrupt :
cprint(u'\nAbandon', 'rouge')
@ -125,7 +125,7 @@ Il ne doit pas
pass
if __name__ == '__main__' :
sys.stdout.write('\r \r') # Pour esthétique lors de l'utilisation par sudo
sys.stdout.write('\r \r') # Pour esthétique lors de l'utilisation par sudo
if len(sys.argv) == 1 :
# Changement de son mot de passe
login = getuser()
@ -136,7 +136,7 @@ if __name__ == '__main__' :
print "Changement du mot de passe du compte choisi."
sys.exit(255)
else :
# Changement du mot de passe par un câbleur ou une nounou
# Changement du mot de passe par un câbleur ou une nounou
login = sys.argv[1]
self_mode = False
for c in login[:] :
@ -153,12 +153,12 @@ if __name__ == '__main__' :
else :
s = commands.getoutput("/usr/bin/ldapsearch -D cn=readonly,dc=crans,dc=org -y/etc/ldap/readonly -x -LLL '(&(objectClass=posixAccount)(uid=%s))' dn nom prenom droits | grep -v MultiMachines" % login).strip()
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)
# Ca a l'air bon
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')
sys.exit(4)
@ -174,7 +174,7 @@ if __name__ == '__main__' :
sys.exit(5)
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_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()
@ -188,7 +188,7 @@ if __name__ == '__main__' :
sys.exit(8)
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'
To = 'roots@crans.org'
mail = """From: Root <%s>
@ -203,7 +203,7 @@ Tentative de changement du mot de passe de %s par %s.
conn = smtplib.SMTP('localhost')
conn.sendmail(From, To , mail )
conn.quit()
cprint(u'Impossible de changer le mot de passe de cet adhérent : compte privilégié', 'rouge')
cprint(u'Impossible de changer le mot de passe de cet adhérent : compte privilégié', 'rouge')
sys.exit(6)
# Finalement !

View file

@ -1,10 +1,10 @@
#! /usr/bin/env python
# -*- coding: iso-8859-15 -*-
# -*- coding: utf-8 -*-
""" Changement du shell de l'utilisateur lancant le programme
DOIT ETRE LANCE PAR SUDO
Copyright (C) Frédéric Pauget
Copyright (C) Frédéric Pauget
Licence : GPLv2
"""
import os, sys
@ -15,18 +15,18 @@ from ldap_crans import crans_ldap
db = crans_ldap()
uid = os.getenv('SUDO_UID')
if not uid :
print "Impossible de déterminer l'utilisateur"
print "Impossible de déterminer l'utilisateur"
sys.exit(1)
s = db.search('uidNumber=%s' % os.getenv('SUDO_UID'),'w')
# On vérifie que c'est pas un club
# On vérifie que c'est pas un club
club = s['club']
if len(club) == 1 :
print 'Pas de changement de shell pour les clubs'
sys.exit(2)
# On regarde si on a des résultats dans les adhérents
# On regarde si on a des résultats dans les adhérents
adh = s['adherent']
if len(adh) != 1 :
print 'Erreur fatale lors de la consultation de la base LDAP'

View file

@ -1,34 +1,34 @@
# -*- python -*-
# -*- coding: iso-8859-15 -*-
# -*- coding: utf-8 -*-
############################################
## Définition du comportement des scripts ##
## Définition du comportement des scripts ##
############################################
from time import localtime
# Administratif
caution = 0
#Précablage possible ?
#Précablage possible ?
precab = False
# Année scolaire en cours
# Année scolaire en cours
dat = localtime()
if dat[1]<9 : ann_scol = dat[0]-1
else : ann_scol = dat[0]
# Bloquage si carte d'étudiants manquante pour l'année en cours
# Bloquage si carte d'étudiants manquante pour l'année en cours
# Au niveau du Squid
bl_carte_et_actif = True
# L'adhérent est considéré comme paiement pas ok
# L'adhérent est considéré comme paiement pas ok
bl_carte_et_definitif = False
# Gel des cableurs pas a jour de cotisation
# Les droits ne sont pas retires mais il n'y a plus de sudo
bl_vieux_cableurs = False
##Création de comptes
# Gid des comptes créés
##Création de comptes
# Gid des comptes créés
gid=100
club_gid=120
# Shell
@ -37,7 +37,7 @@ club_login_shell='/usr/bin/rssh'
# Longueur maximale d'un login
maxlen_login=15
## Répertoire de stockage des objets détruits
## Répertoire de stockage des objets détruits
cimetiere = '/home/cimetiere'
## Adresses mac utiles
@ -47,7 +47,7 @@ mac_titanic = 'aa:73:65:63:6f:76'
## Serveur principal de bcfg2
bcfg2_main = "vert.adm.crans.org"
## Compatibilité inverse
## Compatibilité inverse
cfengine_main = bcfg2_main
## Fichier de mapping lun/nom de volume iscsi
@ -58,10 +58,10 @@ class impression:
"""Cette classe contient toutes les variables
de prix concernant l'impression"""
# Découvert autorisé (en euro)
# Découvert autorisé (en euro)
decouvert = 0.
###### Variables de prix (tout est exprimé en centimes) ######
###### Variables de prix (tout est exprimé en centimes) ######
# Cout imprimante : 9150,60 euros
# 200.000 pages par mois, garantie 1an
@ -91,13 +91,13 @@ class impression:
# 1406.50 les 3 tambours couleurs pour 40.000 passages
c_tambour_coul = 3.51624
# Une feuille à 5% = 5 unites
# Cout de 1 unité de noir
# Une feuille à 5% = 5 unites
# Cout de 1 unité de noir
# 1 toner fait 125.000 unites et coute 203.32euros
# 1 kit de nettoyage fait 250.000 unites et coute 63.30euros
c_noir = 0.18798
# Cout de 1 unité de couleur
# Cout de 1 unité de couleur
# 1 tonner fait 125.000 unites et coute 328.90euros
c_coul = 0.78936
@ -105,7 +105,7 @@ class impression:
c_agrafe = 4800. / 5000. / 3.
# Prix de la facture
# 2500 feuilles rouges à 40.07 euros (pour l'instant l'encre
# 2500 feuilles rouges à 40.07 euros (pour l'instant l'encre
# de la facture est gracieusement offerte)
# fact = 1.6028
fact = 0
@ -118,7 +118,7 @@ class impression:
## Pour le controle d'upload
class upload:
# liste des exemptations générales
# liste des exemptations générales
exempt = [ ['138.231.136.0/21', '138.231.0.0/16'],
['138.231.148.0/22', '138.231.0.0/16'] ]
@ -128,11 +128,11 @@ class upload:
# limite hard
hard = 700
# envoi des mails à disconnect@
# envoi des mails à disconnect@
disconnect_mail_soft = False
disconnect_mail_hard = True
# expéditeur des mails de déconnexion
# expéditeur des mails de déconnexion
expediteur = "disconnect@crans.org"
# textes des mails
@ -143,33 +143,33 @@ Content-Type: text/plain; charset="iso-8859-15"
Bonjour %(proprio)s,
Nous t'informons que ta (tes) machine(s) envoie(nt) une quantité
importante de données vers l'extérieur (%(upload)s Mo en 24 heures).
Nous t'informons que ta (tes) machine(s) envoie(nt) une quantité
importante de données vers l'extérieur (%(upload)s Mo en 24 heures).
*Ce message t'est envoyé à titre informatif, il ne te sanctionne pas.*
*Ce message t'est envoyé à titre informatif, il ne te sanctionne pas.*
Il signifie que tu as envoyé plus de 100 Mo au cours des dernières 24
Il signifie que tu as envoyé plus de 100 Mo au cours des dernières 24
heures. Cela peut venir du fait que, *par exemple*, tu essaies
d'envoyer des fichiers de grosse taille à l'extérieur de la zone
d'envoyer des fichiers de grosse taille à l'extérieur de la zone
crans, ou encore que tu as fait une utilisation importante de
logiciels envoyant une très grande quantité de petites données
(vidéo-conférence par exemple). Il peut y avoir d'autres raisons.
logiciels envoyant une très grande quantité de petites données
(vidéo-conférence par exemple). Il peut y avoir d'autres raisons.
Si cela continuait, et que tu dépassais la limite acceptable des 700
Mo sur 24 heures, tu serais automatiquement déconnecté du réseau pour
une durée de 24 heures. Il t'appartient donc de surveiller cela de
plus près et de faire en sorte que tes machines n'uploadent pas de
manière excessive à l'avenir.
Si cela continuait, et que tu dépassais la limite acceptable des 700
Mo sur 24 heures, tu serais automatiquement déconnecté du réseau pour
une durée de 24 heures. Il t'appartient donc de surveiller cela de
plus près et de faire en sorte que tes machines n'uploadent pas de
manière excessive à l'avenir.
Pour plus d'informations, tu peux consulter la page:
http://wiki.crans.org/VieCrans/DéconnexionPourUpload
http://wiki.crans.org/VieCrans/DéconnexionPourUpload
Si tu as des questions, contacte disconnect@crans.org
NB : L'upload consiste en l'envoi de données vers des machines n'étant
pas branchées sur le CRANS.
NB : L'upload consiste en l'envoi de données vers des machines n'étant
pas branchées sur le CRANS.
--
Disconnect team"""
@ -181,23 +181,23 @@ Content-Type: text/plain; charset="iso-8859-15"
Bonjour %(proprio)s,
Tu as temporairement été déconnecté du réseau en raison de l'envoi
trop important de données vers l'extérieur (%(upload)s Mo en 24h).
Tu as temporairement été déconnecté du réseau en raison de l'envoi
trop important de données vers l'extérieur (%(upload)s Mo en 24h).
Tu as toujours accés au web ainsi qu'à tes mails crans mais tous les
Tu as toujours accés au web ainsi qu'à tes mails crans mais tous les
autres services te sont suspendus. Si cela devait se renouveller trop
souvent, tu serais déconnecté complétement pour une durée plus
importante. Il t'appartient donc de surveiller cela de plus près et de
faire en sorte que ta machine n'uploade plus de manière excessive à
souvent, tu serais déconnecté complétement pour une durée plus
importante. Il t'appartient donc de surveiller cela de plus près et de
faire en sorte que ta machine n'uploade plus de manière excessive à
l'avenir.
Pour plus d'informations, tu peux consulter la page :
http://wiki.crans.org/VieCrans/DéconnexionPourUpload
http://wiki.crans.org/VieCrans/DéconnexionPourUpload
Si tu as des questions, contacte disconnect@crans.org
NB: L'upload consiste en l'envoi de données vers des machines n'étant
pas branchées sur le CRANS.
NB: L'upload consiste en l'envoi de données vers des machines n'étant
pas branchées sur le CRANS.
--
Disconnect team"""
@ -211,17 +211,17 @@ Content-Type: text/plain; charset="iso-8859-15"
%(proprio)s uploade actuellement %(upload)s Mo.
--
Message créé par deconnexion.py"""
Message créé par deconnexion.py"""
message_disconnect_hard = u"""From: %(from)s
To: %(to)s
Subject: %(proprio)s a =?iso-8859-1?Q?=E9t=E9=20d=E9connect=E9?=
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
To: %(to)s
@ -229,13 +229,13 @@ Subject: %(proprio)s a =?iso-8859-1?Q?=E9t=E9=20d=E9connect=E9?=
%(nbdeco)d fois pour upload en un mois !
Content-Type: text/plain; charset="iso-8859-15"
L'adhérent %(proprio)s a été déconnecté %(nbdeco)d fois pour upload en un mois !
L'adhérent %(proprio)s a été déconnecté %(nbdeco)d fois pour upload en un mois !
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
--
Message créé par deconnexion.py"""
Message créé par deconnexion.py"""
message_demenagement = u"""From: %(from)s
@ -245,9 +245,9 @@ Content-Type: text/plain; charset="iso-8859-15"
Bonjour,
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.
Pourrais tu nous préciser ta nouvelle chambre ou adresse stp ?
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.
Pourrais tu nous préciser ta nouvelle chambre ou adresse stp ?
Si tu es parti du campus, souhaites-tu garder tes machines ?
--
@ -255,7 +255,7 @@ Merci par avance,
Les membres actifs du Crans"""
# Classe pour les paramètres du firewall #
# Classe pour les paramètres du firewall #
##########################################
class conf_fw:
mark = { 'https-radin': '0x3',
@ -263,25 +263,25 @@ class conf_fw:
'proxy' : '0x2',
'bittorrent' : '0x1' }
# Valeur du masque utilisé pour créer un arbre dans les filtres
# Valeur du masque utilisé pour créer un arbre dans les filtres
mask = [24]
# Classe pour la détection des virus #
# Classe pour la détection des virus #
######################################
class virus:
# Nombre de Flood Par heure
flood = 100
virus = 10
# Classe pour la détection du p2p #
# Classe pour la détection du p2p #
###################################
class p2p :
# Limite de débit pour l'ensemble du p2p classifié, en octets/s
# Limite de débit pour l'ensemble du p2p classifié, en octets/s
# identique en upload et download
debit_max = 1000000 # = 1 Mb/s = 125 ko/s
debit_adh = 12000 # = 12 Kb/s = 1500 o/s (>= MTU [1500 bytes])
# Limite de paquets acceptés par protocole P2P en deux heures
# Limite de paquets acceptés par protocole P2P en deux heures
limite = {'Bittorrent': 20,
'AppleJuice': 50,
'SoulSeek': 500,
@ -291,10 +291,10 @@ class p2p :
'KaZaa': 50,
'Ares': 50,
'GNUtella': 50 }
# Envoi des mails à disconnect@
# Envoi des mails à disconnect@
disconnect_mail = True
# Expéditeur des mails de déconnexion
# Expéditeur des mails de déconnexion
expediteur = "disconnect@crans.org"
avertissement = u"""From: %(From)s
@ -302,35 +302,35 @@ To: %(To)s
Subject: =?iso-8859-1?Q?D=E9tection?= de p2p sur la machine %(hostname)s
Content-Type: text/plain; charset="iso-8859-15"
La machine %(hostname)s a été déconnectée pendant 24h pour
La machine %(hostname)s a été déconnectée pendant 24h pour
utilisation du protocole %(protocole)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
To: %(To)s
Subject: Avis de =?iso-8859-15?Q?D=E9connexion?=
Content-Type: text/plain; charset="iso-8859-15"
Bonjour,
Nous avons détecté que ta machine, %(hostname)s utilisait le
Nous avons détecté que ta machine, %(hostname)s utilisait le
*protocole* %(protocole)s.
Cela signifie :
- Ou bien que tu utilises le logiciel qui a le même nom
- Ou bien que tu utilises le logiciel qui a le même nom
que ce protocole,
- Ou bien que tu utilises un logiciel qui utilise le
protocole en question pour partager des fichiers.
Or l'usage de *protocoles* de type peer to peer est interdit
sur notre réseau, conformément aux documents que tu as acceptés
en adhérant au CR@NS.
sur notre réseau, conformément aux documents que tu as acceptés
en adhérant au CR@NS.
Lorsqu'un seul des adhérents du CR@NS utilise des protocoles interdits,
il pénalise l'ensemble des adhérents de l'association.
Lorsqu'un seul des adhérents du CR@NS utilise des protocoles interdits,
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"""
@ -340,29 +340,29 @@ To: %(to)s
Subject: %(proprio)s a =?iso-8859-15?Q?=E9t=E9=20d=E9connect=E9?= %(nbdeco)d fois pour p2p en un an !
Content-Type: text/plain; charset="iso-8859-15"
L'adhérent %(proprio)s a été déconnecté %(nbdeco)d fois pour p2p en un an !
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
--
Message créé par deconnexion.py"""
Message créé par deconnexion.py"""
#############################
## Paramètres des machines ##
## Paramètres des machines ##
#############################
## >>>>>>>>>>>>>>> La modification des paramètres suivants doit se
## >> ATTENTION >> faire avec précaution, il faut mettre la base à
## >>>>>>>>>>>>>>> jour en parralèle de ces modifs.
## >>>>>>>>>>>>>>> La modification des paramètres suivants doit se
## >> ATTENTION >> faire avec précaution, il faut mettre la base à
## >>>>>>>>>>>>>>> jour en parralèle de ces modifs.
# Sous réseaux alloués à chaque type de machine ou bâtiment
# Pour la zone wifi, il faut penser à modifier le /etc/network/interfaces
# Sous réseaux alloués à chaque type de machine ou bâtiment
# Pour la zone wifi, il faut penser à modifier le /etc/network/interfaces
# de sable, zamok et komaz pour ajouter les zones en plus (et de
# faire en sorte qu'ils prennent effet immédiatement ; c'est important pour
# komaz car c'est la route par défaut mais aussi pour zamok et sable
# à cause de leur firewall et de leur patte wifi.
# faire en sorte qu'ils prennent effet immédiatement ; c'est important pour
# komaz car c'est la route par défaut mais aussi pour zamok et sable
# à cause de leur firewall et de leur patte wifi.
NETs = { 'serveurs' : [ '138.231.136.0/28' ],
'adherents' : [ '138.231.137.0/24',
'138.231.138.0/24',
@ -381,7 +381,7 @@ NETs = { 'serveurs' : [ '138.231.136.0/28' ],
NETs_regexp = { 'all' : '^138\.231\.1(3[6789]|4[0123456789]|5[01])\.\d+$' }
# Domaines dans lesquels les machines sont placées suivant leur type
# Domaines dans lesquels les machines sont placées suivant leur type
domains = { 'machineFixe': 'crans.org',
'machineCrans': 'crans.org',
'machineWifi': 'wifi.crans.org',
@ -420,24 +420,24 @@ To: %(To)s
Subject: [CRANS] Bienvenue au Cr@ns !
Content-Type: text/plain; charset="iso-8859-15"
Si tu lis ce mail, c'est que ton inscription à l'association est effective !
Si tu lis ce mail, c'est que ton inscription à l'association est effective !
Rappel : Le site web de l'association est http://www.crans.org.
Par ailleurs, toutes les informations concernant l'association sont
disponibles sur le WIKI à l'adresse http://wiki.crans.org
disponibles sur le WIKI à l'adresse http://wiki.crans.org
Notamment, il est important de prendre le temps de lire la page :
http://wiki.crans.org/CransPratique
Elle regroupe toutes les informations nécessaires à l'utilisation des
Elle regroupe toutes les informations nécessaires à l'utilisation des
ressources de l'association.
Sans lire attentivement ce document, l'accès au Web peut ne pas
Sans lire attentivement ce document, l'accès au Web peut ne pas
fonctionner.
-----
L'accés aux news et au wiki sont limités à un usage interne au CRANS.
Pour y avoir accés depuis l'extérieur il faut utiliser un mot de passe:
L'accés aux news et au wiki sont limités à un usage interne au CRANS.
Pour y avoir accés depuis l'extérieur il faut utiliser un mot de passe:
- Pour les news :
* Utilisateur : Vivelapa
* Mot de passe : ranoia!
@ -448,7 +448,7 @@ Pour y avoir acc
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."""
@ -460,14 +460,14 @@ Content-Type: text/plain; charset="iso-8859-15"
Bonjour,
Tu viens d'être doté des droits %(Droit)s au Cr@ns.
Une description de ces droits et de la manière
Tu viens d'être doté des droits %(Droit)s au Cr@ns.
Une description de ces droits et de la manière
de les utiliser est disponible sur la page :
%(Page)s
Si tu as des questions, n'hésite pas à les poser
à d'autres câbleurs ou aux nounous.
Si tu as des questions, n'hésite pas à les poser
à d'autres câbleurs ou aux nounous.
--
Les nounous"""
@ -487,10 +487,10 @@ Content-Type: text/plain; charset="iso-8859-1"
Bonjour,
Il semble que tu es membre actif du CRANS et que tu n'as pas
signé la charte des membres actifs. Si tu n'es pas membre actif
ou si tu as signé la charte des membres actifs, merci de nous le
signé la charte des membres actifs. Si tu n'es pas membre actif
ou si tu as signé la charte des membres actifs, merci de nous le
signaler. Sinon, il faudrait signer la charte et nous la rendre
rapidement. Tu peux l'imprimer à partir du fichier suivant :
rapidement. Tu peux l'imprimer à partir du fichier suivant :
https://wiki.crans.org/CransAdministratif?action=AttachFile&do=get&target=charte_ma.pdf
@ -506,11 +506,11 @@ Content-Type: text/plain; charset="iso-8859-1"
Bonjour,
Les droits que tu avais sur ton compte CRANS ont été retirés
car tu ne cotises pas cette année et que tes droits ne semblent
pas être utiles pour une utilisation à distance. Si nous avons
Les droits que tu avais sur ton compte CRANS ont été retirés
car tu ne cotises pas cette année et que tes droits ne semblent
pas être utiles pour une utilisation à distance. Si nous avons
commis une erreur, nous te prions de nous en excuser. Si tu
souhaites par la suite retrouver des droits, nous serons bien sûr
souhaites par la suite retrouver des droits, nous serons bien sûr
heureux de te les remettre.
Cordialement,

View file

@ -1,12 +1,12 @@
#! /usr/bin/env python
# -*- coding: iso8859-15 -*-
# -*- coding: utf-8 -*-
###############################################################################
# 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
# Etienne Chové <etienne.chove@crans.org>
# Etienne Chové <etienne.chove@crans.org>
#
# Copyright (C) 2006 Etienne Chové
# Copyright (C) 2006 Etienne Chové
# All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
@ -28,7 +28,7 @@
## Chaines de formatage pour le procmailrc
"""
Script permetant de gérer sa configuration mail
Script permetant de gérer sa configuration mail
Usage : ConfigMail.py [--forward=(|<mail>)] [--spam=(accepte|marque|supprime)]
Retourne :
@ -37,7 +37,7 @@ Retourne :
"""
procmail_warning = """################################################################
# Ce fichier de configuration a été automatiquement généré par #
# Ce fichier de configuration a été automatiquement généré par #
# l'intranet. #
# #
# ATTENTION : ne le modifiez que si vous savez ce que vous #
@ -51,7 +51,7 @@ procmail_mark = """# Passage des mails dans spamassassin
* < 256000
| spamc
# Serveur blacklisté
# Serveur blacklisté
:0
* ^X-Reject: 554
* !^X-Spam-Status: Yes
@ -100,7 +100,7 @@ def _IsMail(mail):
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
"""
if type(texte) != list:
@ -126,7 +126,7 @@ def _GetConfig():
# utilisation de procmail
if fic_forward != _Clean(forward_procmail)[0]:
raise MailConfigError, 'Fichier forward non compréhensible'
raise MailConfigError, 'Fichier forward non compréhensible'
## lecture du .procmailrc
fic_procmail = _Clean( open('%s/.procmailrc'%home).readlines() )
@ -145,7 +145,7 @@ def _GetConfig():
# marquage des spams
tmp = _Clean( procmail_mark )
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):]
# suppression des spams ?
@ -154,7 +154,7 @@ def _GetConfig():
elif fic_procmail == _Clean(procmail_delete_spam):
return {'forward':forward, 'spam':'supprime'}
else:
raise MailConfigError, 'Fichier de procmail non compréhensible'
raise MailConfigError, 'Fichier de procmail non compréhensible'
def _SetConfig(forward = None, spam= None):
""" Modifie la configuration de l'utilisateur courant """
@ -165,7 +165,7 @@ def _SetConfig(forward = None, spam= None):
elif spam == None:
new_spam = _GetConfig()['spam']
else:
raise ValueError, 'Valeur interdite pour le paramètre spam'
raise ValueError, 'Valeur interdite pour le paramètre spam'
# variable forward
if forward == None:
@ -175,7 +175,7 @@ def _SetConfig(forward = None, spam= None):
else:
raise ValueError, 'Adresse mail invalide'
# génération des fichiers
# génération des fichiers
if new_spam=='accepte':
# suppression du .procmailrc
try:
@ -188,14 +188,14 @@ def _SetConfig(forward = None, spam= None):
else:
os.remove('%s/.forward'%home)
else:
# écriture du .procmailc
# écriture du .procmailc
txt = procmail_warning + procmail_mark
if new_spam=='supprime':
txt += procmail_delete_spam
if new_forward:
txt += procmail_forward % new_forward
open('%s/.procmailrc'%home,'w').write(txt)
# écriture du .forward
# écriture du .forward
open('%s/.forward'%home,'w').write(forward_procmail)
def _Sudo(uid, forward=None, spam=None):
@ -234,9 +234,9 @@ def _Sudo(uid, forward=None, spam=None):
def MailConfig(uid=None, forward=None, spam=None):
""" 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
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.
@ -275,7 +275,7 @@ if __name__=="__main__":
## execution de MailConfig
res = MailConfig(forward=forward, spam=spam)
## affichage des résultats
## affichage des résultats
for i in res.items():
print "%s=%s" % i

View file

@ -1,14 +1,14 @@
#! /usr/bin/env python
# -*- coding: iso-8859-15 -*-
# -*- coding: utf-8 -*-
# Copyright (C) Stéphane Glondu + ???
# Copyright (C) Stéphane Glondu + ???
# Licence : ???
"""
Envoi de mails textes encodés et bien formatés (encodages spécifiés il faut).
Envoi de mails textes encodés et bien formatés (encodages spécifiés il faut).
Autres outils relatifs aux mails.
format_sender et send_email adaptés depuis /usr/scripts/impression/crans_backend.py.
format_sender et send_email adaptés depuis /usr/scripts/impression/crans_backend.py.
"""
import re
@ -103,12 +103,12 @@ def send_email(sender, recipient, subject, body, server='localhost', cc=None, de
def parse_mail_template(fichier):
"""
Lit fichier et renvoie le couple sujet, corps en unicode.
Les trois premières lignes de fichier doivent être :
Les trois premières lignes de fichier doivent être :
Encoding: <encodage du fichier>
Subject: <sujet du mail>
<ligne vide>
Le reste forme le corps du mail.
L'argument fichier peut être un nom de fichier, ou directement une
L'argument fichier peut être un nom de fichier, ou directement une
instance de file.
"""
if not isinstance(fichier, file):

File diff suppressed because it is too large Load diff

View file

@ -1,13 +1,13 @@
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
# -*- coding: utf-8 -*-
"""
Fichier de base d'interface avec les switchs manageables.
Donne la classe switch qui permet d'effectuer les opérations
élémentaires sur les switchs manageable HP 26xx.
Donne la classe switch qui permet d'effectuer les opérations
élémentaires sur les switchs manageable HP 26xx.
Frédéric PAUGET
Frédéric PAUGET
"""
from time import sleep
from popen2 import popen3
@ -28,13 +28,13 @@ try:
from secrets import config_snmp_secrete, reconf_snmp
except:
# Si a pas le droit de lire config_snmp_secrete
# on va tenter de tout faire en snmpv1 et communauté public
# on va tenter de tout faire en snmpv1 et communauté public
def config_snmp_secrete(snmp,switch) :
snmp = snmp(switch,version='1',community='public')
return snmp.get, snmp.set, snmp.walk
#############################################################################################
### Définitions de classes utiles
### Définitions de classes utiles
# Quelques exceptions
class ConnectionTimout(Exception) :
@ -50,7 +50,7 @@ class ConversationError(Exception) :
import pexpect
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) :
@ -77,13 +77,13 @@ class ssh :
self.ssh.close()
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
self.ssh.sendline(cmd)
self.__sshout = ''
try:
# Attente de la réponse
# Attente de la réponse
while 1:
index = self.ssh.expect([' \[y/n\]\? ',
'%s\(config\)# ' % self.switch,
@ -92,7 +92,7 @@ class ssh :
self.__sshout = self.__sshout + self.ssh.before
if index == 0:
# On répond oui
# On répond oui
self.ssh.send("y")
elif index == 1:
# On est revenu au prompt
@ -112,13 +112,13 @@ class ssh :
class snmp :
""" Classe de communication SNMP """
def __init__(self,host,version=None,community=None,authentication_protocol=None, authentication_pass=None, username=None, privacy_pass=None) :
""" host doit être la machine sur laquelle se connecter
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
""" host doit être la machine sur laquelle se connecter
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
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
si privacy_pass est fourni accès en authPriv
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
si privacy_pass est fourni accès en authPriv
"""
self.host = host
self.version = version
@ -150,11 +150,11 @@ class snmp :
return r
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 ) )
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 ) )
if s=="\"\"":
return ""
@ -170,14 +170,14 @@ class snmp :
raise ValueError('Type inconnu')
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
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 ) )
def walk(self,base_oid) :
""" Retourne le résultat de snmpwalk
""" Retourne le résultat de snmpwalk
le retour est un dictionnaire { oid : valeur }
"""
lignes = self.__exec('snmpwalk -O q %s %s' % (self.options, base_oid ) ).split('\n')
@ -204,7 +204,7 @@ class hpswitch :
__conn_ssh = None
def __init__(self,switch) :
""" 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 )
self.switch = switch.lower()
@ -219,20 +219,20 @@ class hpswitch :
return self.__conn_ssh.send_cmd(cmd,timout)
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 self.__debug : self.__logDest.write("HP DEBUG : show_prise_mac(prise=%s)\n" % prise)
try:
data = self.walk('STATISTICS-MIB::hpSwitchPortFdbAddress.%d' % int(prise))
return map(lambda x:findall('".*"',":".join(x.lower().split(' ')))[0][1:-2],data.values())
except ValueError:
# Pas de MAC trouvée
# Pas de MAC trouvée
return []
def where_is_mac(self, mac) :
"""Retrouve la prise correspondant à une adresse MAC donnée"""
"""Retrouve la prise correspondant à une adresse MAC donnée"""
if self.__debug : self.__logDest.write("HP DEBUG : where_is_mac(mac=%s)\n" % mac)
# On va transformer l'adresse MAC cherchée pour la mettre au format 0A 0A 0A 0A 0A 0A
# On va transformer l'adresse MAC cherchée pour la mettre au format 0A 0A 0A 0A 0A 0A
mac = mac.upper()
mac = filter(lambda x: x in "0123456789ABCDEF", mac) # 0A0A0A0A0A0A
mac = "%s %s %s %s %s %s" % (mac[0:2], mac[2:4], mac[4:6],
@ -246,7 +246,7 @@ class hpswitch :
if onemac[1:-2] == mac:
return int(onesnmp.split(".")[1])
# On a rien trouvé
# On a rien trouvé
return None
def __scp(self,destination,fichier) :
@ -272,8 +272,8 @@ class hpswitch :
self.scp('ssh/mgr_keys',file)
def multicast(self,ip='') :
""" Donne la liste des ports du swich inscrits au flux multicast donné
Si aucun flux donné teste tous les flux multicast possibles.
""" Donne la liste des ports du swich inscrits au flux multicast donné
Si aucun flux donné teste tous les flux multicast possibles.
Retourne un dictionnaire : { adresse du flux : [ ports inscrits ] }
"""
@ -311,7 +311,7 @@ class hpswitch :
return self.set('IF-MIB::ifAdminStatus.%d' % int(prise), 'i', 1)
def disable(self,prise=0) :
""" Désactive une prise """
""" Désactive une prise """
if not prise : prise = self.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)
@ -323,15 +323,15 @@ class hpswitch :
nb = 0
for oid,etat in self.walk(oid).items() :
if etat == 'up' and int(oid.split('.')[1])<51 :
# Le <51 est ici pour éviter de compter les ports fictifs
# Le <51 est ici pour éviter de compter les ports fictifs
nb += 1
return nb
prise = prise.replace('-','')
return self.get(oid + '.' + prise) == 'up'
def is_enable(self,prise=0) :
""" 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 """
""" 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 """
if prise != 'all': prise = int(prise)
return self.__is('IF-MIB::ifAdminStatus',prise)
@ -342,7 +342,7 @@ class hpswitch :
return self.__is('IF-MIB::ifOperStatus',prise)
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
oid = 'IF-MIB::ifAlias.%d' % int(prise)
if nom==None :
@ -377,7 +377,7 @@ class hpswitch :
self.set(oid,'i',code)
def vlans(self, prise = None):
"""Récupère les vlans activés sur la prise 'prise'"""
"""Récupère les vlans activés sur la prise 'prise'"""
if not prise:
prise = self.prise
prise = int(prise)
@ -461,7 +461,7 @@ if __name__ == '__main__' :
for opt, val in options :
if opt == '-h' or opt=='--help' :
print "Usage : %s [[-c commande1] -c commande2...] [-U firmware] [--snmp] regex "
print "Envoi les commandes données au switchs matchant la regex"
print "Envoi les commandes données au switchs matchant la regex"
print "si aucune commande est founie lit l'entree standart"
print "L'envoi de firmware ne fait pas rebooter le switch"
print "L'option --snmp ajoute les commandes de reconfiguration snmp"
@ -486,7 +486,7 @@ if __name__ == '__main__' :
switchs.append(sw)
if not switchs :
print "Aucun switch trouvé"
print "Aucun switch trouvé"
print "Note : il faut une _regex_ (!= wilcards au sens du shell)"
sys.exit(3)
@ -499,7 +499,7 @@ if __name__ == '__main__' :
print
try:
raw_input("Appuyer sur entrée pour continuer")
raw_input("Appuyer sur entrée pour continuer")
except EOFError:
# On lisait depuis un pipe
print '\r'+' '*33+'\r'
@ -507,7 +507,7 @@ if __name__ == '__main__' :
for sw in switchs :
print sw
try:
# Au cas ou le switch ne répondrai pas
# Au cas ou le switch ne répondrai pas
s = hpswitch(sw)
if firmware :
s.upgrade(firmware)

View file

@ -1,21 +1,21 @@
#! /usr/bin/env python
# -*- coding: iso-8859-15 -*-
# -*- coding: utf-8 -*-
"""
Manipulation d'IPv4
Copyright (C) Frédéric Pauget
Copyright (C) Frédéric Pauget
Licence : GPLv2
"""
import re
from config import NETs_regexp
# Pour accélérer QuadToDec...
# Pour accélérer QuadToDec...
__QuadToDecDone = {}
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
"""
if ip in __QuadToDecDone:
@ -31,12 +31,12 @@ def QuadToDec(ip) :
__QuadToDecDone[ip] = ip_dec
return ip_dec
# Pour accélérer DecToQuad
# Pour accélérer DecToQuad
__DecToQuadDone = {}
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
"""
if ip_dec in __DecToQuadDone:
@ -56,14 +56,14 @@ __paramDone = {}
def param(net, raw=False) :
"""
net est un résau fourni sous la forme xxx.xxx.xxx.xxx/yy
si donnée valide retourne un dictionnaire :
net est un résau fourni sous la forme xxx.xxx.xxx.xxx/yy
si donnée valide retourne un dictionnaire :
{ 'network' : xxx.xxx.xxx.xxx ,
'netmask' : yyy.yyy.yyy.yyy ,
'broadcast' : zzz.zzz.zzz.zzz }
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.
"""
if raw and net in __paramDone:
@ -96,9 +96,9 @@ def AddrInNet(ip,net) :
"""
ip est de la forme xxx.xxx.xxx.xxx
net est de la forme xxx.xxx.xxx.xxx/yy
net peut être une liste de chaînes ci-dessus
Retourne True si l'ip est dans un des réseaux.
Note : retourne False si l'IP est une adresse de réseau ou broadcast
net peut être une liste de chaînes ci-dessus
Retourne True si l'ip est dans un des réseaux.
Note : retourne False si l'IP est une adresse de réseau ou broadcast
"""
if type(net)==str : net = [ net ]
@ -113,7 +113,7 @@ def AddrInNet(ip,net) :
return r
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) """
for net in nets :
if AddrInNet(ip,net) :
@ -121,7 +121,7 @@ def AddrInNets(ip,nets) :
return False
def is_crans(ip):
""" Vérifie que l'ip est dans le réseau CRANS
""" Vérifie que l'ip est dans le réseau CRANS
"""
# Pour prove le temps du point rencontre
if ip == '138.231.136.19' :
@ -131,7 +131,7 @@ def is_crans(ip):
return False
def netmask(mask, dec=True) :
""" On génère le sous réseau /bits
""" On génère le sous réseau /bits
"""
non_dec_netmask = (1L<<(32-mask)) - 1
dec_netmask = (1L<<32) - 1 - non_dec_netmask
@ -148,25 +148,25 @@ def IpSubnet(ip, mask) :
return subnet
def NetSubnets(net, subnet_mask) :
""" On construit une liste des sous réseaux /subnet_mask
compris dans le sous réseau /mask comprenant l'ip ip
""" On construit une liste des sous réseaux /subnet_mask
compris dans le sous réseau /mask comprenant l'ip ip
"""
subnets = []
# On récupère une ip du réseau indiqué
# On récupère une ip du réseau indiqué
ip = net.split('/')[0]
# On récupère la valeur du masque
# On récupère la valeur du masque
mask = int(net.split('/')[1])
# On transforme les valeurs d'entrées en valeurs décimales
# On définit la valeur du sous réseau initial
# On transforme les valeurs d'entrées en valeurs décimales
# On définit la valeur du sous réseau initial
dec_netmask = netmask(mask)
dec_ip = QuadToDec(ip)
dec_subnet_netmask = netmask(subnet_mask)
# On calcule la première ip du sous réseau indiqué
# On calcule la première ip du sous réseau indiqué
start_ip = dec_ip & dec_netmask
seq_ip = start_ip
# On fait une itération sur toutes les ip du sous réseau
# On fait une itération sur toutes les ip du sous réseau
while (seq_ip & dec_netmask) == start_ip:
# On récupère le sous réseau de la taille demandée
# On récupère le sous réseau de la taille demandée
subnet = DecToQuad(seq_ip & dec_subnet_netmask) + "/%s" % subnet_mask
if not subnets.count(subnet) :
subnets.append(subnet)

File diff suppressed because it is too large Load diff

View file

@ -1,14 +1,14 @@
# -*- coding: iso8859-15 -*-
# -*- coding: utf-8 -*-
###############################################################################
# ldap_passwd.py : manipulation des mots de passes LDAP
# $Id: ldap_passwd.py,v 1.7 2006-05-04 17:46:58 chove Exp $
###############################################################################
# The authors of this code are
# Bjorn Ove Grotan <bgrotan@grotan.com>
# Etienne Chové <etienne.chove@crans.org>
# Etienne Chové <etienne.chove@crans.org>
#
# Copyright (C) 2005 Bjorn Ove Grotan
# Copyright (C) 2006 Etienne Chové
# Copyright (C) 2006 Etienne Chové
# All rights reserved.
#
# This program is free software; you can redistribute it and/or modify

View file

@ -1,9 +1,9 @@
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
# -*- coding: utf-8 -*-
""" Gestion de lock
Copyright (C) Frédéric Pauget
Copyright (C) Frédéric Pauget
Licence : GPLv2
"""
@ -14,10 +14,10 @@ from fcntl import lockf, LOCK_EX, LOCK_NB, LOCK_UN
import errno, random
def wait_lock(lock_name, lock_comment='', d=None, retry=0.2):
"""Attend la disponibilité d'un lock en utilisant le framework Twisted.
"""Attend la disponibilité d'un lock en utilisant le framework Twisted.
Si d est de type Deferred, on est en mode asynchrone.
retry permet de réessayer dans `retry' secondes.
retry permet de réessayer dans `retry' secondes.
"""
from twisted.internet import reactor, defer
try:
@ -30,7 +30,7 @@ def wait_lock(lock_name, lock_comment='', d=None, retry=0.2):
import traceback
traceback.print_exc()
# On a sans doute pas le lock et c'est pas moi qui me tape
# à debugguer les trucs à Fred.
# à debugguer les trucs à Fred.
raise AssertionError
# On a le lock
@ -51,8 +51,8 @@ def wait_lock(lock_name, lock_comment='', d=None, retry=0.2):
return d
def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) :
""" Création d'un lock
si nowait=1 fait un sys.exit(254) quand un ancien lock actif est rencontré
""" Création d'un lock
si nowait=1 fait un sys.exit(254) quand un ancien lock actif est rencontré
"""
return
lock_dir = '/var/lock/gestion'
@ -62,7 +62,7 @@ def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) :
pass
lock_file = "%s/%s" % (lock_dir, lock_name)
# On créé une zone d'exclusion
# On créé une zone d'exclusion
lock_fd_dl=open("%s-dotlock" % lock_file, "w")
# On demande un verrou exclusif
try:
@ -75,12 +75,12 @@ def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) :
# On va plutot lever une exception
raise AssertionError('In critical section')
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)
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)
# On enleve le verrou système
# On enleve le verrou système
lockf(lock_fd_dl, LOCK_UN)
lock_fd_dl.close()
return make_lock(lock_name, lock_comment)
@ -124,7 +124,7 @@ def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) :
data[-1]=txt
if not quiet:
sys.stderr.write('\tpropriétaire : %s\n\tpid : %s\n\tdémarré depuis %s\n' % tuple(data) )
sys.stderr.write('\tpropriétaire : %s\n\tpid : %s\n\tdémarré depuis %s\n' % tuple(data) )
sys.exit(254)
else:
# On va plutot lever une exception
@ -136,7 +136,7 @@ def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) :
time.sleep(1)
a.cycle()
sys.stdout.write('\r')
# On enleve le verrou système
# On enleve le verrou système
lockf(lock_fd_dl, LOCK_UN)
lock_fd_dl.close()
return make_lock(lock_name, lock_comment)
@ -150,7 +150,7 @@ def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) :
lock_fd.write("%s\n%s\n%s" % (os.getpid(), utilisateur, lock_comment) )
lock_fd.close()
# On enleve le verrou système
# On enleve le verrou système
lockf(lock_fd_dl, LOCK_UN)
lock_fd_dl.close()
@ -158,7 +158,7 @@ def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) :
def remove_lock( lock_name ) :
""" Destruction du lock """
return
# On créé une zone d'exclusion
# On créé une zone d'exclusion
lock_dir = '/var/lock/gestion'
lock_file = "%s/%s" % (lock_dir, lock_name)
@ -169,7 +169,7 @@ def remove_lock( lock_name ) :
except IOError, e:
if e.errno not in [errno.EACCES, errno.EAGAIN]:
raise
# Déjà locké
# Déjà locké
time.sleep(0.5)
return remove_lock(lock_name)
try :
@ -180,6 +180,6 @@ def remove_lock( lock_name ) :
except :
pass
# On enleve le verrou système
# On enleve le verrou système
lockf(lock_fd_dl, LOCK_UN)
lock_fd_dl.close()

View file

@ -1,8 +1,8 @@
#! /usr/bin/env python
# -*- encoding: iso-8859-15 -*-
# Envoi d'un mail donné à certains adherents
# -*- encoding: utf-8 -*-
# Envoi d'un mail donné à certains adherents
# Premier parametre : critere de recherche
# Second parametre, fichier à envoyer
# Second parametre, fichier à envoyer
import smtplib
import sys,os
@ -32,7 +32,7 @@ def reconf_postfix():
limit="no"
for line in lines:
if line == LIMIT_CONF:
nlines+=u"## mail_all.py a commenté la ligne suivante"
nlines+=u"## mail_all.py a commenté la ligne suivante"
nlines+="# smtpd_client_message_rate_limit = 10\n"
limit="yes"
else:
@ -43,14 +43,14 @@ def reconf_postfix():
sys.exit(1)
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", ""]
positif = ["O", "o", "Y", "y"]
poursuivre = "x"
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:
print "Ok, on ne touche pas au fichier..."
@ -58,14 +58,14 @@ def reconf_postfix():
assert (poursuivre in positif)
# On réécrit la conf
# On réécrit la conf
try:
nconf_fd = open (POSTFIX_CONF, "w")
print u"Réécriture de la configuration de postfix"
print u"Réécriture de la configuration de postfix"
nconf_fd.writelines(nlines)
nconf_fd.close ()
except IOError:
print u"Je n'arrive pas à réécrire la conf de postfix, es-tu root ?"
print u"Je n'arrive pas à réécrire la conf de postfix, es-tu root ?"
sys.exit(1)
reload_postfix()
@ -76,50 +76,50 @@ if __name__ == "__main__":
if len(sys.argv) != 3:
print """Usage:
Ce script permet d'envoyer un mail à toute une catégorie d'adhérents.
Ce script permet d'envoyer un mail à toute une catégorie d'adhérents.
Le premier paramètre est le critère de recherche :
paiement=ok pour les adhérents en règle
paiement=ok&paiement!=2004 pour ceux qui n'ont pas encore payé pour cette année
Le premier paramètre est le critère de recherche :
paiement=ok pour les adhérents en règle
paiement=ok&paiement!=2004 pour ceux qui n'ont pas encore payé pour cette année
chbre=????&paiement=ok pour ceux dont la chambre est inconnue
paiement=ok&carteEtudiant!=2004 pour ceux qui n'ont pas de carte d'étudiant
paiement=ok&carteEtudiant!=2004 pour ceux qui n'ont pas de carte d'étudiant
Le second paramètre est un fichier texte qui contient le message à envoyer. Il
doit également contenir les entêtes, à l'exception du destinataire qui sera rajouté
Le second paramètre est un fichier texte qui contient le message à envoyer. Il
doit également contenir les entêtes, à l'exception du destinataire qui sera rajouté
par le script.
/!\ Ce script ne demande aucune confirmation, il faut veiller à
vérifier avec who que l'on cible bien les utilisateurs que l'on
veut. Et si on veut vérifier que le mail a une bonne tête on se
l'envoie d'abord en mettant login=machin comme critère de
/!\ Ce script ne demande aucune confirmation, il faut veiller à
vérifier avec who que l'on cible bien les utilisateurs que l'on
veut. Et si on veut vérifier que le mail a une bonne tête on se
l'envoie d'abord en mettant login=machin comme critère de
recherche.
/!\ Ce script a pour but de spammer, et spammer c'est mal. Il faut
donc contourner les limitations qui ont été mises en place au
Cr@ns. Si plus de 10 mails doivent être envoyés, il faut le faire
donc contourner les limitations qui ont été mises en place au
Cr@ns. Si plus de 10 mails doivent être envoyés, il faut le faire
depuis rouge, et ce en root.
"""
sys.exit(0)
# On en est là
# On en est là
# On ouvre la base et on cherche
adherents = ldap_crans.crans_ldap().search(sys.argv[1])['adherent']
card= len(adherents)
print "%d adhérent(s) a/ont été trouvé(s)..." % card
print "%d adhérent(s) a/ont été trouvé(s)..." % card
time.sleep(3) # On dort un peu, ctrl-c welcome
limit="no"
if card >= 10:
(limit, backup_conf) = reconf_postfix()
# Il faudra quoiqu'il arrive rétablir la conf de postfix
# Il faudra quoiqu'il arrive rétablir la conf de postfix
# try capture-t-il les SIGTERM ?!
try:
try:
texte = "".join(file(sys.argv[2], "r").readlines())
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)
echecs = []
@ -129,14 +129,14 @@ par le script.
mail = adherent.mail().encode("iso-8859-15", "ignore")
if "@" not in mail:
mail = mail + "@crans.org"
print "Envoi du mail à %s <%s>..." % (adherent.Nom().encode("iso-8859-15","ignore"), mail)
print "Envoi du mail à %s <%s>..." % (adherent.Nom().encode("iso-8859-15","ignore"), mail)
try:
recipient = format_sender(u'"%s" <%s>\n' % (adherent.Nom(), mail))
s.sendmail('bulk+%s@crans.org' % mail.replace("@",'-at-'),
(mail,),
"To: %s\n%s" % (recipient, texte))
except:
print "Erreur lors de l'envoi à %s <%s>..." % (adherent.Nom().encode("iso-8859-15","ignore"), mail)
print "Erreur lors de l'envoi à %s <%s>..." % (adherent.Nom().encode("iso-8859-15","ignore"), mail)
echecs.append(mail)
else:
# Tout va bien
@ -148,7 +148,7 @@ par le script.
s.close()
# On rétablit la conf de postfix
# On rétablit la conf de postfix
finally:
if limit == "yes":
try:

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
# -*- coding: utf-8 -*-
"""
Script de mise a jour des firmwares de switchs
@ -17,7 +17,7 @@ import os
if sys.argv[1] == '-h' or sys.argv[1]=='--help' :
print "Usage : %s <ip du serveur tftp> <fichier sur le tftp> regex " % sys.argv[0]
print "Envoi les commandes données au switchs matchant la regex"
print "Envoi les commandes données au switchs matchant la regex"
sys.exit(0)
ip_tftp=sys.argv[1]
@ -40,16 +40,16 @@ print switchs
print "---------------"
if not switchs :
print "Aucun switch trouvé"
print "Aucun switch trouvé"
print "Note : il faut une _regex_ (!= wilcards au sens du shell)"
sys.exit(1)
if not ip_tftp :
print "Pas de serveur tftp donné"
print "Pas de serveur tftp donné"
sys.exit(1)
if not file_tftp :
print "Pas de fichier donné"
print "Pas de fichier donné"
sys.exit(1)
# On fait les tests uniquement sur batv-3
@ -127,7 +127,7 @@ for bestiole in switchs :
i=i+1
sleep(1)
if i==300 :
print "Le switch n'a tjs pas rebooté"
print "Le switch n'a tjs pas rebooté"
echecs.append(bestiole)
aie=1
break
@ -136,8 +136,8 @@ for bestiole in switchs :
print "---------------"
continue
print "Reboot commencé"
print "Attente de réponse au ping"
print "Reboot commencé"
print "Attente de réponse au ping"
i=0
aie=0
@ -154,7 +154,7 @@ for bestiole in switchs :
print "---------------"
continue
print "Le switch répond au ping"
print "Le switch répond au ping"
print "Connexion ssh"

View file

@ -1,5 +1,5 @@
#! /usr/bin/env python
# -*- coding: iso-8859-15 -*-
# -*- coding: utf-8 -*-
"""
Mise a jour periodique des listes d'ip et d'id disponibles.
@ -42,7 +42,7 @@ def lister_ip_utilisees():
def update_ip(plage, occupees):
net = NETs[plage]
pool_ip = [] # Pool d'IP à tester
pool_ip = [] # Pool d'IP à tester
for ne in net:
ip = ne.split('/')[0]
ip = ip.split('.')
@ -58,7 +58,7 @@ def update_ip(plage, occupees):
if n[2] == 255: break
ip = "%d.%d.%d.%d" % tuple(n)
if not AddrInNet(ip, ne):
# On est allé trop loin
# On est allé trop loin
break
pool_ip.append(ip)

View file

@ -1,10 +1,10 @@
#! /usr/bin/env python
# -*- coding: iso-8859-15 -*-
# -*- coding: utf-8 -*-
"""
Restauration d'un objet précédement détruit dans la base.
Restauration d'un objet précédement détruit dans la base.
Copyright (C) Frédéric Pauget
Copyright (C) Frédéric Pauget
Licence : GPLv2
"""
@ -17,21 +17,21 @@ from gest_crans import modif_adher, set_machine, modif_club
from ldap_crans import mailexist
def load(file) :
""" Charge l'objet (adhérent, machine ou club contenu dans le fichier fourni """
""" Charge l'objet (adhérent, machine ou club contenu dans le fichier fourni """
try :
fd=open(file,'rb')
except :
print "Impossible d'ouvrir le fichier demandé."
print "Impossible d'ouvrir le fichier demandé."
sys.exit(1)
obj = cPickle.load(fd)
try :
# Si machine vérif si le proprio est encore dans la base
# Si machine vérif si le proprio est encore dans la base
test_proprio = obj.proprietaire()
if test_proprio.Nom() != obj.proprio :
raise
# Propriétaire encore dans la base => on récupère les infos de la base
# Propriétaire encore dans la base => on récupère les infos de la base
del obj.proprio
except :
pass
@ -47,7 +47,7 @@ def load(file) :
if '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) != 2 :
print "%s <fichier>" % sys.argv[0].split('/')[-1].split('.')[0]
print "Restauration ou visualisation d'un objet précédement détruit dans la base."
print "Restauration ou visualisation d'un objet précédement détruit dans la base."
print "Les fichiers de sauvegarde sont dans %s" % config.cimetiere
sys.exit(255)
@ -56,17 +56,17 @@ aff(obj)
def restore_adher(adh) :
if adh.compte() and mailexist(adh.compte()) :
print "AVERTISSEMENT : le login %s à déja été réattribué." % adh.compte()
print " il faudra recréer un compte avec un login différent"
print "AVERTISSEMENT : le login %s à déja été réattribué." % adh.compte()
print " il faudra recréer un compte avec un login différent"
prompt(u'Appuyez sur ENTREE pour continuer')
adh._data['mail'] = []
modif_adher(adh)
def restore_machine(machine) :
try :
obj.proprio # crash si l'adhérent est encore dans la base
# L'adhérent est plus dans la base
t = prompt(u"Ratacher la machine à un [C]lub ou un [A]dhérent ?")
obj.proprio # crash si l'adhérent est encore dans la base
# L'adhérent est plus dans la base
t = prompt(u"Ratacher la machine à un [C]lub ou un [A]dhérent ?")
t = t.lower()
if t in 'ac' :
i = prompt(u"Entrez l'%sid auquel ratacher la machine : %sid =" % (t,t) )
@ -79,11 +79,11 @@ def restore_club(club) :
modif_club(club)
# Restauration ?
q = prompt(u'Restaurer cette entrée ? [O/N]')
q = prompt(u'Restaurer cette entrée ? [O/N]')
if q not in 'oO' :
sys.exit(0)
obj.connect() # Reconnection à la base LDAP
obj.connect() # Reconnection à la base LDAP
if obj.idn == 'aid' :
restore_adher(obj)
elif obj.idn == 'mid' :

View file

@ -1,9 +1,9 @@
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
# -*- coding: utf-8 -*-
""" Fonctions de tests sur l'utilisateur
Copyright (C) Frédéric Pauget
Copyright (C) Frédéric Pauget
Licence : GPLv2
"""
@ -18,7 +18,7 @@ def getuser() :
def groups(login='') :
""" 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 == '':
login = getuser()
@ -43,15 +43,15 @@ def groups(login='') :
def isadm(login='') :
""" Retourne True si l'utilisateur est dans le groupe 4 (adm)
Si login='', prend l'utilisateur loggué """
Si login='', prend l'utilisateur loggué """
return u'Nounou' in groups(login) or '0' in groups(login)
def isdeconnecteur(login='') :
""" Retourne True si l'utilisateur est dans le groupe 611 (bureau)
Si login='', prend l'utilisateur loggué """
Si login='', prend l'utilisateur loggué """
return isadm(login) or u'Bureau' in groups(login)
def iscableur(login=''):
""" Retourne True si l'utilisateur est dans le groupe 604 (respbat)
Si login='', prend l'utilisateur loggué """
Si login='', prend l'utilisateur loggué """
return isadm(login) or u'Cableur' in groups(login)

View file

@ -1,19 +1,19 @@
#! /usr/bin/env python
# -*- coding: iso-8859-15 -*-
# -*- coding: utf-8 -*-
# Copyright (C) Frédéric Pauget
# Copyright (C) Frédéric Pauget
# Licence : GPLv2
u"""Ce script permet de recherche et d'afficher le détail d'une machine ou
d'un adhérent.
u"""Ce script permet de recherche et d'afficher le détail d'une machine ou
d'un adhérent.
Usage: %(prog)s [options] <chaine de recherche>
La chaine de recherche peut être :
* soit un terme unique, dans ce cas la recherche sera effectuée sur les
La chaine de recherche peut être :
* soit un terme unique, dans ce cas la recherche sera effectuée sur les
champs en bleu ci-dessous.
* soit du type "champ1=valeur1&champ2!=valeur2 ...", les résultats seront
alors limités aux entrées correspondantes à tous les critères.
* soit du type "champ1=valeur1&champ2!=valeur2 ...", les résultats seront
alors limités aux entrées correspondantes à tous les critères.
Les champs de recherche possibles sont :
%(champs_rech)s
@ -22,19 +22,19 @@ Recherche sur prise possible (utiliser uniquement ce champ dans ce cas).
Les options de recherches sont :
* 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
-c ou --club : limitation de l'affichage aux clubs
-b ou --bornes : limitation de l'affichage aux bornes wifi
--crans : recherche uniquement les machines du crans
* options d'affichage :
-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
-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)
-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)
-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)
"""
try:
@ -63,14 +63,14 @@ aff_ipsec = 0
def aff(qqch,mtech=0) :
""" 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 :
* si la longueur de la liste est inférieure à limit_aff_details
affiche les propriétés détaillées de chaque élément.
* 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 la longueur de la liste est inférieure à limit_aff_details
affiche les propriétés détaillées de chaque élément.
* 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 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 :
qqch = [ qqch ]
@ -99,26 +99,26 @@ def aff(qqch,mtech=0) :
elif t == 'cid':
cprint(club_details(c).strip())
# affiche le nombre de résultats
# affiche le nombre de résultats
if len(qqch) > 1:
cprint(u"Total: %d" % len(qqch))
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 :
* aid
* prénom nom
* prénom nom
* chambre
* machines
"""
data = []
# Copie locale triée par (nom, prenom)
# Copie locale triée par (nom, prenom)
adhers = adhers[:]
adhers.sort(lambda x, y: cmp((x.nom(), x.prenom()), (y.nom(), y.prenom())))
for a in adhers:
## État administratif
## État administratif
ok = u'\x1b[1;32mo\x1b[1;0m'
ook = u'\x1b[1;32mO\x1b[1;0m'
nok = u'\x1b[1;31mn\x1b[1;0m'
@ -129,17 +129,17 @@ def adhers_brief(adhers) :
elif isinstance(a,Adherent) and not a.adherentPayant(): paid = coul('G', 'bleu')
else: paid = nok
# Précablage
# Précablage
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 'c' in a.controle(): carte = ook
else: carte = ok
else : carte = nok
machines = ''
# Récupération des machines
# Récupération des machines
if len(adhers) <= limit_aff_machines:
for machine in a.machines() :
nom = machine.nom().split('.')[0]
@ -150,7 +150,7 @@ def adhers_brief(adhers) :
else : machines = coul(nom,k)
else:
machines = None
# Données
# Données
if len(adhers) <= limit_aff_machines:
data.append([a.id(), a.Nom(), a.chbre(), paid, carte, machines])
else:
@ -158,41 +158,41 @@ def adhers_brief(adhers) :
if len(adhers) <= limit_aff_machines:
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"C : carte d'étudiant année en cours\n" + \
u"P : paiement année en cours, le fond vert indique le précâblage (G bleu = inscription gratuite)\n" + \
u"C : carte d'étudiant année en cours\n" + \
tableau(data,
titre = [u'aid', u'Prénom Nom', u'Chbre', u'P', u'C', u'Machines'],
titre = [u'aid', u'Prénom Nom', u'Chbre', u'P', u'C', u'Machines'],
largeur = [5, 30, 5, 1, 1, '*'],
alignement = ['d', 'c', 'g', 'c', 'c', 'c'])
else:
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"C : carte d'étudiant année en cours\n" + \
u"P : paiement année en cours, le fond vert indique le précâblage (G bleu = inscription gratuite)\n" + \
u"C : carte d'étudiant année en cours\n" + \
tableau(data,
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],
alignement = ['d', 'c', 'g', 'c', 'c'])
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 :
* mid
* type (fixe ou wifi, born)
* nom
* adresse IP
* adresse MAC
* si blacklistée
* si blacklistée
"""
data = []
# Copie locale triée par nom
# Copie locale triée par nom
machines = machines[:]
machines.sort(lambda x, y: cmp(x.nom(), y.nom()))
for m in machines :
t, bl = __bases_machines(m)
# Propriétaire
# Propriétaire
a = m.proprietaire()
p = a.Nom()
@ -203,12 +203,12 @@ def machines_brief(machines) :
else:
p = coul(p,'rouge')
# Données
# Données
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,
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'],
largeur = [5, 4, 18, '*', 5, 10],
alignement = ['d', 'c', 'c', 'c', 'g', 'c'])
@ -222,12 +222,12 @@ def clubs_brief(clubs) :
"""
data = []
# Copie locale triée par Nom
# Copie locale triée par Nom
clubs = clubs[:]
clubs.sort(lambda x, y: cmp(x.Nom(), y.Nom()))
for c in clubs :
## État administratif
## État administratif
ok = u'\x1b[1;32mo\x1b[1;0m'
ook = u'\x1b[1;32mO\x1b[1;0m'
nok = u'\x1b[1;31mn\x1b[1;0m'
@ -237,11 +237,11 @@ def clubs_brief(clubs) :
else: paid = ok
else : paid = nok
# Précablage
# Précablage
if ann_scol+1 in c.paiement() : paid = coul(paid,'f_vert')
machines = ''
# Récupération des machines
# Récupération des machines
for machine in c.machines() :
nom = machine.nom().split('.')[0]
if machine.blacklist_actif() : k = 'rouge'
@ -252,11 +252,11 @@ def clubs_brief(clubs) :
# Responsable
resp = c.responsable().Nom()
# Données
# Données
data.append([c.id() , c.Nom(), c.local(), paid, resp, machines])
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,
titre = [u'cid', u'Nom ', u'Local', u'P', u'Responsable', u'Machines'],
largeur = [5, '*', 6, 1, 21, 15],
@ -265,24 +265,24 @@ def clubs_brief(clubs) :
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 :
* mid
* type (fixe ou wifi)
* nom
* adresse IP
* adresse MAC
* si blacklistée
* si blacklistée
"""
data = []
# Copie locale triée par nom
# Copie locale triée par nom
machines = machines[:]
machines.sort(lambda x, y: cmp(x.nom(), y.nom()))
for m in machines :
t, bl = __bases_machines(m)
# Données
# Données
data.append([m.id(), t, m.nom().split('.')[0], m.ip(), m.mac(), bl])
return tableau(data,
@ -292,19 +292,19 @@ def list_machines(machines) :
def list_bornes(bornes) :
"""
Formatage sous forme d'un tableau des propriétés de la liste de bornes wifi :
Formatage sous forme d'un tableau des propriétés de la liste de bornes wifi :
* mid
* nom
* adresse IP
* adresse MAC
* État
* État
* puissance
* canal
* lieu (la première remarque en fait)
* lieu (la première remarque en fait)
"""
data = []
# Copie locale triée par nom
# Copie locale triée par nom
bornes = bornes[:]
bornes.sort(lambda x, y: cmp(x.nom(), y.nom()))
@ -314,7 +314,7 @@ def list_bornes(bornes) :
t, bl = __bases_machines(b)
if t != 'born' : continue
# Données
# Données
try :
l = [x for x in b.info() if not x[0]=='<'][0]
if len(l) > 11 :
@ -334,7 +334,7 @@ def list_bornes(bornes) :
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,
titre = [u'mid', u'Nom', u'Adresse IP', u'Adresse MAC', u'E', u'Can', u'P', u'Pris', u'Lieu'],
largeur = [5, 13, 15, 17, 1, 5, 3, 4, '*'],
@ -342,7 +342,7 @@ def list_bornes(bornes) :
def adher_details(adher) :
"""
Affichage du détail des propriétés d'un adhérent
Affichage du détail des propriétés d'un adhérent
"""
f=u''
# Aid
@ -370,12 +370,12 @@ def adher_details(adher) :
if not adher.contourneGreylist():
GL = u' (%s)'%coul(u'GreyList','gris')
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())
if alias:
if alias[0] == u',':
# Canonical étéait vide
# Canonical étéait vide
alias = alias[2:]
f += coul(u'Alias : ','gras') + alias
f += GL
@ -390,9 +390,9 @@ def adher_details(adher) :
if forward:
f += coul(u'Redirection : ', 'gras') + forward
except IOError, e:
# Pas de .forward, ou .forward privé... on laisse tomber
# Pas de .forward, ou .forward privé... on laisse tomber
pass
f += coul(u'Dernière connexion : ', 'gras')
f += coul(u'Dernière connexion : ', 'gras')
timestamp = adher.derniereConnexion()
if timestamp == 0:
f += coul(u'Jamais', 'rouge')
@ -401,24 +401,24 @@ def adher_details(adher) :
time()-timestamp > 32*24*3600 and 'rouge' or '')
f += u"\n"
# État administratif
# État administratif
f += coul("Date d'inscription : ", "gras")
f += strftime('%d/%m/%Y %H:%M', localtime(adher.dateInscription()))
f += coul(u'\nÉtat administratif : ','gras')
f += coul(u'\nÉtat administratif : ','gras')
jour=1
if ann_scol not in adher.carteEtudiant() :
f += coul(u"manque carte d'étudiant",'violet')
f += coul(u"manque carte d'étudiant",'violet')
jour = 0
if ann_scol not in adher.paiement() :
if not jour : f += ' et '
if isinstance(adher, Adherent) and not adher.adherentPayant():
f += coul(u"inscription gratuite", 'bleu')
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
if jour :
f += coul(u"à jour",'vert')
f += coul(u"à jour",'vert')
f += '\n'
# Telephone
@ -428,12 +428,12 @@ def adher_details(adher) :
tel = u'%s %s %s %s %s' % ( tel[:2], tel[2:4], tel[4:6], tel[6:8], tel[8:] )
except :
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
chbre = adher.chbre()
if chbre == 'EXT' :
# Adhérent extérieur
# Adhérent extérieur
addr = adher.adresse()
if addr[0] :
f += coul(u'Adresse : ','gras')
@ -443,7 +443,7 @@ def adher_details(adher) :
elif chbre == '????' :
f += coul(u'Chambre invalide\n','violet')
else :
# Chambre + prise (d'après annuaire)
# Chambre + prise (d'après annuaire)
etat, vlans = prise_etat(adher.chbre())
f += coul(u'Chambre : ','gras') + u"%s " % chbre
f += u'(%s)' % etat
@ -453,12 +453,12 @@ def adher_details(adher) :
f += coul(u'VLAN : ','gras') + u'%s' % vlans
f += u'\n'
# Études
# Études
if adher.etudes(1).isdigit() :
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) )
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) )
# Solde
@ -476,15 +476,15 @@ def adher_details(adher) :
if d :
f += coul(u"Droits sur les serveurs : ",'gras') + ', '.join(d)
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'
# Paiement
if adher.paiement() :
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 :
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''
for an in adher.paiement() : g += u" %i-%i" % ( an, an+1 )
if len(g) > 35 : f += '\n\t'
@ -492,12 +492,12 @@ def adher_details(adher) :
if 'p' in adher.controle(): f += coul(u' (OK)', 'vert')
f += u'\n'
# Cartes d'étudiant fournie
# Cartes d'étudiant fournie
if adher.carteEtudiant() :
if len(adher.carteEtudiant()) == 1 :
f += coul(u"Carte d'étudiant fournie pour l'année scolaire :",'gras')
f += coul(u"Carte d'étudiant fournie pour l'année scolaire :",'gras')
else :
f += coul(u"Carte d'étudiant fournie pour les années scolaires :",'gras')
f += coul(u"Carte d'étudiant fournie pour les années scolaires :",'gras')
g = u''
for an in adher.carteEtudiant() : g += u" %i-%i" % ( an, an+1 )
if len(g) > 25 : f += '\n\t'
@ -521,7 +521,7 @@ def adher_details(adher) :
clients_ipsec = None
def ipsec_ok(machine) :
"""Indique si une machine est correctement authentifiée"""
"""Indique si une machine est correctement authentifiée"""
prefix=""
if hostname != "ragnarok":
if not os.path.isfile("/usr/scripts/gestion/clef-encap"):
@ -535,7 +535,7 @@ def ipsec_ok(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+= coul(u'mid=%s ' % machine.id(),'bleu')
@ -557,10 +557,10 @@ def machine_details(machine) :
f+= coul(u'IP : ','gras') + "%s\t\t" %machine.ip()
f+= coul(u'MAC : ','gras') + "%s\n" %machine.mac()
# Propriétaire
f+= coul(u'Propriétaire : ','gras')
# Propriétaire
f+= coul(u'Propriétaire : ','gras')
try :
f += machine.proprio + coul(' (adhérent détruit)', 'jaune')
f += machine.proprio + coul(' (adhérent détruit)', 'jaune')
a = AssociationCrans()
except :
a = machine.proprietaire()
@ -579,10 +579,10 @@ def machine_details(machine) :
f += coul(u'Nombre de prises : ', 'gras')
f += "%d\n" % n
# Adhérent blacklisté ?
# Adhérent blacklisté ?
bl = a.blacklist_actif()
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 += '\n'
@ -592,8 +592,8 @@ def machine_details(machine) :
f += machine.hotspot() and 'oui' or 'non'
position = machine.position()
if position:
f += coul(u'\t\t\tCoordonnées : ', 'gras')
f += u'%s°N, %s°E\n' % position
f += coul(u'\t\t\tCoordonnées : ', 'gras')
f += u'%s°N, %s°E\n' % position
else:
f += '\n'
@ -608,7 +608,7 @@ def machine_details(machine) :
f += coul(u'Puissance : ','gras') + u"%4.d" % int(machine.puissance())
f += coul(u'\tCanaux : ', 'gras') + machine.canal()
f += coul(u'\tÉtat : ', 'gras')
f += coul(u'\tÉtat : ', 'gras')
if borne_etat(machine.nom()):
f += coul(u'borne active', 'vert')
f += '\n'
@ -621,7 +621,7 @@ def machine_details(machine) :
if clients and base:
f += coul(u'Clients : \n','gras')
for (client, rssi) in clients:
# On va chercher le nom correspondant à l'adresse MAC
# On va chercher le nom correspondant à l'adresse MAC
res = base.search("mac=%s" % client)['machine']
authentification=""
if not res:
@ -630,7 +630,7 @@ def machine_details(machine) :
else:
client_nom = ", ".join(["%s [%s]" % (x.nom().split(".")[0],
x.proprietaire().Nom()) for x in res])
# On va regarder si le client est authentifié
# On va regarder si le client est authentifié
auth_ok = ipsec_ok(x)
if auth_ok != None:
if auth_ok:
@ -649,7 +649,7 @@ def machine_details(machine) :
coul("%d" % rssi, coul_rssi),
authentification)
else:
f += coul(u'borne éteinte','rouge')
f += coul(u'borne éteinte','rouge')
f += '\n'
if machine.nvram():
f += coul(u'NVRAM : ', 'gras')
@ -659,7 +659,7 @@ def machine_details(machine) :
f += coul(u'Clef IPsec : ','gras') + machine.ipsec()
f += '\n'
# Ports spéciaux
# Ports spéciaux
if machine.portTCPin():
f += coul(u'Ports TCP ouvert ext->machine : ','gras') + ' '.join(machine.portTCPin()) + '\n'
if machine.portTCPout():
@ -671,7 +671,7 @@ def machine_details(machine) :
# Exemption d'upload
if machine.exempt() :
f += coul(u'Upload exempté vers : ','gras') + ', '.join(machine.exempt()) + '\n'
f += coul(u'Upload exempté vers : ','gras') + ', '.join(machine.exempt()) + '\n'
f += _blacklist(machine)
f += _info(machine)
@ -681,7 +681,7 @@ def machine_details(machine) :
def club_details(club) :
"""
Affichage du détail des propriétés d'un club
Affichage du détail des propriétés d'un club
"""
f=''
# Cid
@ -697,16 +697,16 @@ def club_details(club) :
f += (coul(u'Imprimeurs : ', 'gras') + "%s\n" % ', '.join(map(lambda x:
club.search("aid=%s" % x)['adherent'][0].Nom(), club.imprimeurs())))
# État administratif
f += coul(u'État administratif : ','gras')
# État administratif
f += coul(u'État administratif : ','gras')
jour=1
if ann_scol not in club.paiement() :
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
if jour :
f += coul(u"à jour",'vert')
f += coul(u"à jour",'vert')
f += '\n'
# Chambre + prise
@ -721,7 +721,7 @@ def club_details(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')
g = ''
for an in club.paiement() : g += " %i-%i" % ( an, an+1 )
if len(g) > 35 : f += '\n\t'
@ -762,7 +762,7 @@ def club_details(club) :
return f
###########################################
# Fonctions annexes de formatage de données
# Fonctions annexes de formatage de données
def _blacklist(clas):
""" Formatage blackliste de la classe fournie """
@ -776,7 +776,7 @@ def _blacklist(clas):
event = event.split('$')
dates = strftime('%d/%m/%Y %H:%M', localtime(int(event[0])))
if event[1] == '-':
dates = u'à partir du %s' % dates
dates = u'à partir du %s' % dates
else:
dates = u'du %s au ' % dates
dates += strftime('%d/%m/%Y %H:%M', localtime(int(event[1])))
@ -836,14 +836,14 @@ def __bases_machines(m) :
elif isinstance(m, BorneWifi): t = 'born'
else : t='fixe'
# Déconnectée ?
# Déconnectée ?
b = m.blacklist_actif()
if not b :
bl = '-'
elif len(b) == 1 :
bl = coul(b[0],'rouge')
else :
bl = coul(u'cf détails','rouge')
bl = coul(u'cf détails','rouge')
return t , bl
@ -859,14 +859,14 @@ def borne_etat(borne) :
return False
def borne_clients_canal(borne) :
"""Renvoie la liste des adresses MAC associées à la borne ainsi que le canal.
"""Renvoie la liste des adresses MAC associées à la borne ainsi que le canal.
Chaque adresse MAC est en fait contenue dans un couple comprenant
l'adresse MAC et le RSSI du client associé.
l'adresse MAC et le RSSI du client associé.
On en profite pour renvoyer également le canal en cours de la
borne. On fait cela dans la même fonction car cela évite de faire
deux connexions ssh (ce qui est fort coûteux).
On en profite pour renvoyer également le canal en cours de la
borne. On fait cela dans la même fonction car cela évite de faire
deux connexions ssh (ce qui est fort coûteux).
Au final, on renvoie un dictionnaire
- mac-rssi: une liste de couples (MAC, RSSI)
@ -894,18 +894,18 @@ def borne_clients_canal(borne) :
return {"canal": canal, "mac-rssi": macs}
def prise_etat(chbre) :
""" Retoune un doublet contenant l'état de la prise associée à la chbre et les VLANs actives"""
""" Retoune un doublet contenant l'état de la prise associée à la chbre et les VLANs actives"""
f = u''
vlans = u''
try:
# On met aussi l'état
# On met aussi l'état
from hptools import sw_chbre, ConversationError
prise = sw_chbre(chbre)
vlans += ', '.join(prise.vlans())
f += u'prise %s' % prise.prise_brute
rows, cols = get_screen_size()
if prise.is_up() :
f += u', ' + coul(u'machine branchée','vert')
f += u', ' + coul(u'machine branchée','vert')
reste_cols = cols - 45
if prise.eth_mode().find('10Mbits')!=-1 :
f+= u', ' + coul(u'prise en 10Mbps','jaune')
@ -914,15 +914,15 @@ def prise_etat(chbre) :
macs = prise.show_prise_mac()
if len(macs) == 0:
if reste_cols < 20 :
# Faut aller à la ligne
# Faut aller à la ligne
f += u'\n '
f += coul(u'aucune MAC détectée', 'jaune')
f += coul(u'aucune MAC détectée', 'jaune')
else:
if len(macs) == 1 and reste_cols > 25 :
# Une seule mac et on a assez de place
f += u"MAC: %s" % macs[0]
else :
# On va à la ligne
# On va à la ligne
# Combien d'adresses MAC peut-on mettre par ligne ?
# Une adresse MAC =~ 20 caracteres
cols -= 17 # On met 15espaces devant chaque ligne
@ -936,9 +936,9 @@ def prise_etat(chbre) :
f += u"%s" % macs.pop()
count += 1
elif not prise.is_enable() :
f+= u', ' + coul(u'prise désactivée','rouge')
f+= u', ' + coul(u'prise désactivée','rouge')
else :
f+= u', activée, lien non détecté'
f+= u', activée, lien non détecté'
except ConversationError, r:
# Switch non manageable ou down
f += ', '
@ -956,7 +956,7 @@ def prise_etat(chbre) :
return f, vlans
##############################################################################
## Partie dévolue au système de recherche
## Partie dévolue au système de recherche
def __usage_brief(err='') :
""" Message d'erreur """
@ -1004,7 +1004,7 @@ def __usage() :
accu = champ
longueur = len(champ)
# Dernière ligne
# Dernière ligne
liste.append(accu)
cprint(__doc__ % { 'prog': sys.argv[0].split('/')[-1].split('.')[0],
@ -1015,11 +1015,11 @@ def __usage() :
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
# Récupération des options
# Récupération des options
if len(sys.argv) == 1 :
# Pas d'option fournie
__usage_brief()
@ -1045,37 +1045,37 @@ def __recherche() :
# Mode debug
debug = 1
elif opt == '-l' or opt =='--limit':
# Passage mode condensé, mode détaillé
# Passage mode condensé, mode détaillé
try : limit_aff_details = int(val)
except :
__usage_brief(u'Valeur du paramètre %s incorecte (doit être un entier positif)' % opt)
__usage_brief(u'Valeur du paramètre %s incorecte (doit être un entier positif)' % opt)
elif opt == '-L' or opt =='--limit-historique':
# Limitation du nombre de lignes d'historique
try : limit_aff_historique = int(val)
except :
__usage_brief(u'Valeur du paramètre %s incorecte (doit être un entier positif)' % opt)
__usage_brief(u'Valeur du paramètre %s incorecte (doit être un entier positif)' % opt)
elif opt in [ '-a', '--adherent' ] :
only_adh = 1
cprint(u"Affichage limité aux adhérents.")
cprint(u"Affichage limité aux adhérents.")
elif opt in [ '-m', '--machine' ] :
only_mac = 1
cprint(u"Affichage limité aux machines.")
cprint(u"Affichage limité aux machines.")
elif opt in [ '-c', '--club' ] :
only_club = 1
cprint(u"Affichage limité aux clubs.")
cprint(u"Affichage limité aux clubs.")
elif opt == '--crans' :
only_crans = 1
mtech = 1
cprint(u"Affichage limité aux machines du crans.")
cprint(u"Affichage limité aux machines du crans.")
elif opt in [ '-b', '--bornes' ] :
only_bornes = 1
cprint(u"Affichage limité aux bornes wifi.")
cprint(u"Affichage limité aux bornes wifi.")
# On va tenter de limiter un peu la recherche
if not arg :
# Recherche initiale sans critère
# Recherche initiale sans critère
arg = [ 'canal=*&host=*.crans.org']
elif arg[0].find('=')!=-1 :
# Recherche avec critères
# Recherche avec critères
arg += [ '&canal=*' ]
elif opt in [ '-t', '--tech' ] :
# Format affichage des machines
@ -1085,13 +1085,13 @@ def __recherche() :
aff_ipsec = 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')
arg = ' '.join(arg)
# Cas particulier de recherche sur prise
if arg.count('=') == 1 and arg.split('=')[0] == 'prise' :
prise = arg.split('=')[1]
# Récupération de la chambre
# Récupération de la chambre
try:
from annuaires import reverse
chbre = reverse(prise[0].lower())[prise[1:]]
@ -1103,7 +1103,7 @@ def __recherche() :
if chbre:
if len(chbre) != 1 :
cprint(u"Prise correspondante à plusieurs chambres %s" % ' '.join(chbre))
cprint(u"Prise correspondante à plusieurs chambres %s" % ' '.join(chbre))
return
# On fait la recherche sur la chambre
chbre= prise[0] + chbre[0]
@ -1122,21 +1122,21 @@ def __recherche() :
except ValueError, c :
__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']:
# Pas de résultat dans la base
# Pas de résultat dans la base
# Recherche sur chambre ?
if arg.count('=') == 1 and arg.split('=')[0] == 'chbre' :
# Affichage des infos de la chambre
chbre = arg.split('=')[1]
cprint(u"Chambre %s inoccupée ou invalide (%s)" % (chbre,prise_etat(chbre)[0]))
cprint(u"Chambre %s inoccupée ou invalide (%s)" % (chbre,prise_etat(chbre)[0]))
else :
cprint(u"Aucun résultat trouvé.")
cprint(u"Aucun résultat trouvé.")
sys.exit(3)
# L'affichage souhaité a été précisé ?
# L'affichage souhaité a été précisé ?
elif only_bornes :
if not res['machine'] :
cprint(u'Aucun résultat à afficher')
cprint(u'Aucun résultat à afficher')
sys.exit(4)
else :
if len(res['machine']) > limit_aff_details :
@ -1154,11 +1154,11 @@ def __recherche() :
traite.append(a.id())
to_aff.append(m.proprietaire())
if not(to_aff) :
cprint(u'Aucun résultat à afficher')
cprint(u'Aucun résultat à afficher')
sys.exit(4)
aff(to_aff)
elif res['club'] :
cprint(u'Aucun résultat à afficher')
cprint(u'Aucun résultat à afficher')
sys.exit(4)
elif only_mac :
if res['machine'] : aff(res['machine'],mtech)
@ -1179,22 +1179,22 @@ def __recherche() :
traite.append(a.id())
to_aff.append(m.proprietaire())
if not(to_aff) :
cprint(u'Aucun résultat à afficher')
cprint(u'Aucun résultat à afficher')
sys.exit(4)
aff(to_aff)
elif res['adherent'] :
cprint(u'Aucun résultat à afficher')
cprint(u'Aucun résultat à afficher')
sys.exit(4)
# Non : on affiche tout.
else :
if res['adherent'] :
cprint(u"Résultats trouvés parmi les adhérents :", 'cyan')
cprint(u"Résultats trouvés parmi les adhérents :", 'cyan')
aff(res['adherent'])
if res['machine'] :
cprint(u"Résultats trouvés parmi les machines :", 'cyan')
cprint(u"Résultats trouvés parmi les machines :", 'cyan')
aff(res['machine'],mtech)
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'])
if __name__ == '__main__' :
@ -1214,12 +1214,12 @@ if __name__ == '__main__' :
# Fin
sys.exit(c)
except :
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
marche à suivre pour reproduire cette erreur.""")
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
marche à suivre pour reproduire cette erreur.""")
if debug :
cprint('-'*40)
cprint(u'Détails techniques :')
cprint(u'Détails techniques :')
import traceback
# On veut le traceback sur la sortie standard
sys.stderr = sys.stdout