Commit 7fde44ea authored by Hamza Dely's avatar Hamza Dely

Merge branch 'switches'

Incorporation des modifications faisant suite au changement
de VLAN pour le management des switches
parents 1819f382 62dbb37d
......@@ -59,3 +59,6 @@ secours/etat_*
# Fichier de son pour asterisk
sip/sound/
#Firmwares des switchs
firmwares_switchs/
......@@ -183,7 +183,7 @@ def get_prise_chbre(data):
Par convention, le nom d'une chambre commence (lettre du bâtiment) par une
majuscule, tandis que la prise correspondante commence par une miniscule.
"""
## Filaire: NAS-Identifier => contient le nom du switch (batm-3.adm.crans.org)
## Filaire: NAS-Identifier => contient le nom du switch (batm-3.switches.crans.org)
## NAS-Port => port du switch (ex 42)
# Lettre du bâtiment (C, B, A, etc, en majuscule)
......
......@@ -353,7 +353,7 @@ def dialogStyle(texte, what):
"""
if isinstance(what, str):
if isinstance(what, (str, unicode)):
what = [what]
dialog_styles = {
......
......@@ -48,7 +48,7 @@ def _need_conn(f):
return first_connect
# Le v est virtuel.
bat_switchs = ["a", "b", "c", "g", "h", "i", "j", "m", "o", "p", "r", "v"]
bat_switchs = ["a", "b", "c", "g", "h", "i", "j", "k", "m", "o", "p", "r", "v"]
class ChbreNotFound(ValueError):
"""Lorsqu'une chambre n'existe pas"""
......@@ -96,6 +96,13 @@ def lieux_public():
results = cur.fetchall()
return [batiment.upper()+chambre for batiment, chambre in results]
@_need_conn
def disabled_radius():
cur = conn.cursor()
cur.execute("SELECT batiment,chambre FROM prises_prise WHERE has_radius=False")
results = cur.fetchall()
return [batiment.upper()+chambre for batiment, chambre in results]
@_need_conn
def reverse(batiment, prise = None):
"""Correspondance prise -> chambre"""
......@@ -145,7 +152,7 @@ uplink_prises={ 'a' :
349 : 'uplink->batb-4', 350 : 'libre-service',
401 : 'uplink->batb-0', 402 : 'uplink->batb-1',
403 : 'uplink->batb-2', 404 : 'uplink->batb-3',
405 : 'uplink->backbone', 523 : 'uplink->batb-4',
405 : 'uplink->backbone',
626 : 'uplink->backbone',
},
'c' :
......@@ -206,7 +213,7 @@ uplink_prises={ 'a' :
421 : 'uplink->batj-3', 422 : 'libre-service',
},
'k' : {
25 : 'uplink->backbone',
23 : 'uplink->backbone',
},
'm' :
{
......@@ -232,18 +239,16 @@ uplink_prises={ 'a' :
149: 'uplink->batp-4 (R3.1)',
249: 'uplink->batp-4 (R2.1)',
350: 'uplink->batp-4 (R1.2)',
# On ne génère pas la conf de batp-4 automatiquement, mais ses uplinks
# peuvent être utiles à connaître
401: 'uplink->batp0', 402: 'uplink->batp-1',
403: 'uplink->batp2', 403: 'uplink->batp-3',
405: 'libre-service', 406: 'uplink->bato-1',
401: 'uplink->batp-3', 402: 'uplink->batp-2',
403: 'uplink->batp-1', 404: 'uplink->batp-0',
405: 'libre-service', 409: 'uplink->bato-1',
},
'o' :
{
25 : 'uplink->bato-1', 26 : 'libre-service',
101 : 'uplink->bato-0', 121: 'uplink->NRD',
122: 'uplink->backbone', 123: 'uplink->backbone (unused)',
124: 'uplink->batp-0'
124: 'uplink->batp-4',
} ,
'r' :
{
......@@ -284,32 +289,25 @@ uplink_prises={ 'a' :
},
}
_SPECIAL_SWITCHES = ['backbone.adm.crans.org',
'multiprise-v6.adm.crans.org',
'batk-0.crans.org',
'minigiga.adm.crans.org',
'batb-5.crans.org',
_SPECIAL_SWITCHES = [
'backbone.switches.crans.org',
'minigiga.switches.crans.org',
]
_HIDDEN_SWITCHES = [
'batp-4.adm.crans.org',
'batv-0.adm.crans.org',
'batp-4.switches.crans.org',
'batv-0.switches.crans.org',
]
def guess_switch_fqdn(switch_name):
"""Retourne le FQDN d'un switch à partir de son nom"""
try:
return socket.gethostbyname_ex(switch_name)[0]
return socket.gethostbyname_ex(switch_name + ".switches.crans.org")[0]
except socket.gaierror:
pass
try:
return socket.gethostbyname_ex(switch_name + ".adm.crans.org")[0]
except socket.gaierror:
pass
try:
return socket.gethostbyname_ex(switch_name + ".crans.org")[0]
return socket.gethostbyname_ex(switch_name)[0]
except socket.gaierror:
pass
......@@ -339,8 +337,10 @@ def all_switchs(bat=None, hide=_SPECIAL_SWITCHES + _HIDDEN_SWITCHES):
continue
if hostname not in hide:
switchs.append(hostname)
switchs = set(switchs)
# on ajoute quand-même le backbone et/ou multiprise-v6 si demandé
switchs += set(_SPECIAL_SWITCHES).difference(hide)
switchs |= (set(_SPECIAL_SWITCHES) - set(hide))
switchs = list(switchs)
switchs.sort()
return switchs
......
# -*- mode: python; coding: utf-8 -*-
# Mapping des versions de switchs <-> firmware à jour
hp_procurve_map = {
"J9777" : ("YA.16.03.0003", "HP 2530"),
"J4899" : ("H.10.119", "HP 2626"),
"J4900" : ("H.10.119", "HP 2650"),
"J9626" : ("RA.16.03.0003", "HP 2620"),
"J9623" : ("RA.16.03.0003", "HP 2620"),
"J9145" : ("W.15.14.0014", "HP 2910 al"),
"J9085" : ("R.11.119", "HP 2610"),
"J9088" : ("R.11.119", "HP 2610"),
"J9021" : ("N.11.75", "HP 2810"),
"J9727" : ("WB.15.15.0012", "HP 2920"),
}
all_models = [
"HP 2530", "HP 2626", "HP 2650", "HP 2620",
"HP 2910 al", "HP 2610", "HP 2810", "HP 2920",
]
......@@ -6,6 +6,9 @@ Copyright (C) Valentin Samir
Licence : GPLv3
"""
from __future__ import unicode_literals
import os
import sys
import time
......@@ -14,11 +17,9 @@ import signal
import inspect
import traceback
if '/usr/scripts' not in sys.path:
sys.path.append('/usr/scripts')
from pythondialog import Dialog as PythonDialog
from pythondialog import DialogTerminatedBySignal, PythonDialogErrorBeforeExecInChildProcess
from pythondialog import error as DialogError
from dialog import Dialog as PythonDialog
from dialog import DialogTerminatedBySignal, PythonDialogErrorBeforeExecInChildProcess
from dialog import error as DialogError
from gestion import affichage
debug_enable = False
......@@ -32,9 +33,9 @@ def mydebug(txt):
debugf = open('/tmp/gest_crans_lc.log', 'w')
if isinstance(txt, list):
for v in txt:
mydebug(' ' + str(v))
mydebug(' ' + unicode(v))
else:
debugf.write(str(txt)+'\n')
debugf.write(unicode(txt)+'\n')
debugf.flush()
os.fsync(debugf)
......@@ -51,7 +52,7 @@ class TailCaller(object) :
Parameters
----------
f : function
Fonction décoré
Fonction décorée
"""
other_callers = {}
def __init__(self, f) :
......@@ -140,7 +141,7 @@ class TailCall(object) :
if key not in targs.args:
raise TypeError("%s() got an unexpected keyword argument '%s'" % (call.func_name, key))
def __str__(self):
def __unicode__(self):
return "TailCall<%s(%s%s%s)>" % (
self.call.func_name,
', '.join(repr(a) for a in self.args),
......@@ -150,10 +151,10 @@ class TailCall(object) :
def copy(self):
'''
Renvois une copie de l'objet courant
attention les elements et args ou kwargs sont juste linké
ça n'est pas gennant dans la mesure où ils ne sont normalement pas
éditer mais remplacé par d'autres éléments
Renvoie une copie de l'objet courant.
Attention les elements et args ou kwargs sont juste linkés
Ça n'est pas gênant dans la mesure où ils ne sont normalement pas
édités mais remplacés par d'autres éléments.
'''
result = TailCall(self.call, *list(self.args), **dict(self.kwargs))
result.stacklvl = self.stacklvl
......@@ -170,9 +171,9 @@ class TailCall(object) :
def handle(self) :
"""
Exécute la fonction call sur sa liste d'argument.
on déréférence les TailCaller le plus possible pour réduire
la taille de la stack
Exécute la fonction call sur sa liste d'arguments.
On déréférence les TailCallers le plus possible pour réduire
la taille de la stack.
"""
caller = None
call = self.call
......@@ -182,9 +183,15 @@ class TailCall(object) :
return call(*self.args, **self.kwargs)
def unicode_of_Error(x):
"""Formatte des exception"""
return u"\n".join(unicode(i, 'utf-8') if type(i) == str
else repr(i) for i in x.args)
"""Formatte des exceptions"""
def _exc_formatter(element):
if isinstance(element, str):
return element.decode('utf-8', 'ignore')
elif isinstance(element, unicode):
return element
else:
return repr(element)
return "\n".join(_exc_formatter(i) for i in x.args)
def raiseKeyboardInterrupt(x, y):
"""fonction utilisée pour réactiver les Ctrl-C"""
......@@ -259,21 +266,27 @@ class Dialog(object):
signal.signal(signal.SIGINT, signal.SIG_IGN) # Pas de Ctrl-C
if e[1] == 11:
self.dialog.msgbox(
"La fenêtre dialog à été fermée par une erreur de segmentation",
timeout=self.timeout, title="Erreur rencontrée", width=73, height=10
"La fenêtre dialog à été fermée par une erreur de segmentation",
timeout=self.timeout,
title="Erreur rencontrée",
width=73,
height=10
)
raise Continue(cancel_cont)
else:
raise
except PythonDialogErrorBeforeExecInChildProcess:
self.dialog.msgbox(
"La fenêtre dialog à été fermée et a retourné le code 127 : \n" +\
" * peut être que dialog n'a put être éxécuté\n" +\
" * peut être qu'il n'y a plus de mémoire disponible\n" +\
" * peut être que le nombre max de descripteur de fichier a été atteins\n" +\
"ou peut être que dialog fait juste du caca.\n" +\
"La fenêtre dialog à été fermée et a retourné le code 127 : \n"
" * peut être que dialog n'a put être éxécuté\n"
" * peut être qu'il n'y a plus de mémoire disponible\n"
" * peut être que le nombre max de descripteur de fichier a été atteins\n"
"ou peut être que dialog fait juste du caca.\n"
"Quitter l'interface ?",
title="Erreur rencontrée", width=73, height=12, defaultno=True,
title="Erreur rencontrée",
width=73,
height=12,
defaultno=True,
timeout=self.timeout
)
raise Continue(cancel_cont)
......@@ -287,15 +300,15 @@ class Dialog(object):
@tailcaller
def handle_dialog_result(self, code, output, cancel_cont, error_cont, codes_todo=[]):
"""
Gère les fonctions traitant les résultat d'appels à dialog.
s'occupe de gérer les exceptions, Ctrl-C, propagation de certaine exceptions, l'appuis sur annuler.
Le code à exécuté lui ai passé via la liste codes_todo, qui doit contenir une liste de triple :
Gère les fonctions traitant les résultats d'appels à dialog.
S'occupe de gérer les exceptions, Ctrl-C, propagation de certaine exceptions, l'appui sur annuler.
Le code à exécuter lui est passé via la liste codes_todo, qui doit contenir une liste de triple :
(code de retour dialog, fonction à exécuter, liste des arguements de la fonction)
la fonction est appelée sur ses arguements si le code retourné par dialog correspond.
codes_todo = [(code, todo, todo_args)]
"""
# Si on a appuyé sur annulé ou ESC, on s'en va via la continuation donnée en argument
if code in (self.dialog.DIALOG_CANCEL, self.dialog.DIALOG_ESC):
if code in (self.dialog.CANCEL, self.dialog.ESC):
raise Continue(cancel_cont)
# Sinon, c'est OK
else:
......@@ -314,16 +327,26 @@ class Dialog(object):
# En cas d'une autre erreur, on l'affiche et on retourne au menu d'édition
except (Exception, ldap.OBJECT_CLASS_VIOLATION) as e:
signal.signal(signal.SIGINT, signal.SIG_IGN) # Pas de Ctrl-C
self.dialog.msgbox(traceback.format_exc() if self.debug_enable else "%s" % unicode_of_Error(e), timeout=self.timeout,
title="Erreur rencontrée", width=73, height=10)
self.dialog.msgbox(
traceback.format_exc().decode('utf-8') if self.debug_enable else "%s" % unicode_of_Error(e),
timeout=self.timeout,
title="Erreur rencontrée",
width=73,
height=10
)
raise Continue(error_cont)
except KeyboardInterrupt:
signal.signal(signal.SIGINT, signal.SIG_IGN) # Pas de Ctrl-C
raise Continue(cancel_cont)
# En cas de code de retour dialog non attendu, on prévient et on retourne au menu d'édition
self.dialog.msgbox("Le code de retour dialog est %s, c'est étrange" % code,
timeout=self.timeout, title="Erreur rencontrée", width=73, height=10)
self.dialog.msgbox(
"Le code de retour dialog est %s, c'est étrange" % code,
timeout=self.timeout,
title="Erreur rencontrée",
width=73,
height=10
)
raise Continue(error_cont)
......@@ -333,60 +356,102 @@ class Dialog(object):
Fait entrer à l'utilisateur un commentaire et le retourne.
Si force est à True, on oblige le commentaire à être non vide
"""
(code, output) = self.dialog.inputbox(text=text, title=title, timeout=self.timeout, init=init)
retry_cont = TailCall(self.get_comment, title=title, text=text, cont=cont, force=force)
(code, output) = self.dialog.inputbox(
text=text,
title=title,
timeout=self.timeout,
init=init
)
retry_cont = TailCall(
self.get_comment,
title=title,
text=text,
cont=cont,
force=force
)
def todo(output, force, title, retry_cont):
if force and not output:
self.dialog.msgbox("Entrée vide, merci d'indiquer quelque chose", timeout=self.timeout, title=title)
self.dialog.msgbox(
"Entrée vide, merci d'indiquer quelque chose",
timeout=self.timeout,
title=title
)
raise Continue(retry_cont)
else:
return unicode(output, 'utf-8')
return output
return self.handle_dialog_result(
code=code,
output=output,
cancel_cont=cont,
error_cont=retry_cont,
codes_todo=[([self.dialog.DIALOG_OK], todo, [output, force, title, retry_cont])]
codes_todo=[([self.dialog.OK], todo, [output, force, title, retry_cont])]
)
@tailcaller
def get_password(self, cont, confirm=True, title="Choix d'un mot de passe", **kwargs):
"""
Affiche une série d'inpuxbox pour faire entrer un mot de passe puis le retourne,
Affiche une série d'inputbox pour faire entrer un mot de passe puis le retourne,
si confirm=True, il y a une confirmation du mot de passe de demandée
"""
def todo(self_cont, cont):
(code, pass1) = self.dialog.passwordbox("Entrez un mot de passe", title=title, timeout=self.timeout, **kwargs)
if code != self.dialog.DIALOG_OK:
(code, pass1) = self.dialog.passwordbox(
"Entrez un mot de passe",
title=title,
timeout=self.timeout,
**kwargs
)
if code != self.dialog.OK:
raise Continue(cont)
elif not pass1:
raise ValueError("Mot de pass vide !")
raise ValueError("Mot de passe vide !")
if confirm:
(code, pass2) = self.dialog.passwordbox("Comfirmer le mot de passe", timeout=self.timeout, title=title, **kwargs)
if code != self.dialog.DIALOG_OK:
(code, pass2) = self.dialog.passwordbox(
"Confirmer le mot de passe",
timeout=self.timeout,
title=title,
**kwargs
)
if code != self.dialog.OK:
raise Continue(self_cont)
if pass1 != pass2:
raise ValueError("Les deux mots de passe ne concordent pas")
return pass1
self_cont = TailCall(self.get_password, cont=cont)
return self.handle_dialog_result(
code=self.dialog.DIALOG_OK,
code=self.dialog.OK,
output="",
cancel_cont=cont,
error_cont=self_cont,
codes_todo=[([self.dialog.DIALOG_OK], todo, [self_cont, cont])]
codes_todo=[([self.dialog.OK], todo, [self_cont, cont])]
)
@tailcaller
def get_timestamp(self, title, text, cont, hour=-1, minute=-1, second=-1, day=0, month=0, year=0, date_only=False):
def get_timestamp(self, title, text, cont, hour=-1, minute=-1, second=-1,
day=0, month=0, year=0, date_only=False):
"""Fait choisir une date et une heure et retourne le tuple (year, month, day, hour, minute, second)"""
retry_cont = TailCall(self.get_timestamp, title=title, text=text, cont=cont, hour=hour,
minute=minute, second=second, day=day, month=month, year=year)
retry_cont = TailCall(
self.get_timestamp,
title=title,
text=text,
cont=cont,
hour=hour,
minute=minute,
second=second,
day=day,
month=month,
year=year
)
def get_date(day, month, year):
(code, output) = self.dialog.calendar(text, day=day, month=month, year=year,
timeout=self.timeout, title=title)
if code in (self.dialog.DIALOG_CANCEL, self.dialog.DIALOG_ESC):
(code, output) = self.dialog.calendar(
text,
day=day,
month=month,
year=year,
timeout=self.timeout,
title=title
)
if code in (self.dialog.CANCEL, self.dialog.ESC):
raise Continue(cont)
elif output:
(day, month, year) = output
......@@ -394,9 +459,14 @@ class Dialog(object):
else:
raise EnvironmentError("Pourquoi je n'ai pas de date ?")
def get_time(hour, minute, second, day, month, year):
(code, output) = self.dialog.timebox(text, timeout=self.timeout, hour=hour,
minute=minute, second=second)
if code in (self.dialog.DIALOG_CANCEL, self.dialog.DIALOG_ESC):
(code, output) = self.dialog.timebox(
text,
timeout=self.timeout,
hour=hour,
minute=minute,
second=second
)
if code in (self.dialog.CANCEL, self.dialog.ESC):
raise Continue(retry_cont(day=day, month=month, year=year))
elif output:
(hour, minute, second) = output
......@@ -413,14 +483,13 @@ class Dialog(object):
def confirm(self, text, title, defaultno=False, width=0, height=0):
"""wrapper autour du widget yesno"""
return self.dialog.yesno(
text,
no_collapse=True,
colors=True,
no_mouse=True,
timeout=self.timeout,
title=title,
defaultno=defaultno,
width=width, height=height,
backtitle="Appuyez sur MAJ pour selectionner du texte"
) == self.dialog.DIALOG_OK
text,
no_collapse=True,
colors=True,
no_mouse=True,
timeout=self.timeout,
title=title,
defaultno=defaultno,
width=width, height=height,
backtitle="Appuyez sur MAJ pour selectionner du texte"
) == self.dialog.OK
......@@ -6,12 +6,13 @@ Copyright (C) Valentin Samir
Licence : GPLv3
"""
from __future__ import unicode_literals
import sys
import time
import ldap
import traceback
if '/usr/scripts' not in sys.path:
sys.path.append('/usr/scripts')
from gestion import affichage
import gestion.config as config
......@@ -38,7 +39,7 @@ class Dialog(lc.Dialog):
for bl in obj['blacklist']:
choices.append(
(
str(index),
unicode(index),
affichage.style(
"%s [%s]" % (bl['type'], bl['comm']),
'rouge' if bl['actif'] else None,
......@@ -48,7 +49,8 @@ class Dialog(lc.Dialog):
)
index+=1
return self.dialog.menu(
"Éditer une blacklist ou en ajouter une nouvelle ?\n(les blacklistes actives apparaissent en rouge)",
"Éditer une blacklist ou en ajouter une nouvelle ?\n"
"(les blacklistes actives apparaissent en rouge)",
width=0,
timeout=self.timeout,
height=0,
......@@ -59,7 +61,8 @@ class Dialog(lc.Dialog):
colors=True,
cancel_label="Retour",
backtitle=self._connected_as(),
choices=choices)
choices=choices
)
def todo(tag):
if tag == 'new':
......@@ -69,7 +72,6 @@ class Dialog(lc.Dialog):
bl.update(obj['blacklist'][int(tag)].value)
return tag, bl
(code, tag) = self.handle_dialog(cont, box)
retry_cont = TailCall(self.edit_blacklist_select, obj=obj, title=title, cont=cont)
return self.handle_dialog_result(
......@@ -77,7 +79,7 @@ class Dialog(lc.Dialog):
output=tag,
cancel_cont=cont,
error_cont=retry_cont,
codes_todo=[([self.dialog.DIALOG_OK], todo, [tag])]
codes_todo=[([self.dialog.OK], todo, [tag])]
)
@tailcaller
......@@ -98,15 +100,21 @@ class Dialog(lc.Dialog):
colors=True,
cancel_label="Retour",
backtitle=self._connected_as(),
choices=[(k,v) for (k,v) in config.blacklist_items.items()])
choices=[(k,v) for (k,v) in config.blacklist_items.items()]
)
def todo(tag, retry_cont):
if tag in config.blacklist_items:
return tag