[switchs.py] utf-8 + début de ménage

This commit is contained in:
Daniel STAN 2013-04-13 15:59:49 +02:00
parent f7abf46550
commit adebfe1ea0

View file

@ -1,11 +1,11 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: iso-8859-15 -*- # -*- coding: utf-8 -*-
""" met à jour les propriétés des prises des switchs du bat : """ met à jour les propriétés des prises des switchs du bat :
mac autorisée(s), état (activé ou non) et nom de la prise mac autorisée(s), état (activé ou non) et nom de la prise
argument : nom du switch argument : nom du switch
procédure de configuration initiale : procédure de configuration initiale :
* mot de passe admin (password manager user-name <username>) * mot de passe admin (password manager user-name <username>)
* activation du ssh (crypto key generate ssh) * activation du ssh (crypto key generate ssh)
* copie fichier de conf * copie fichier de conf
@ -23,9 +23,10 @@ from ldap_crans import crans_ldap, BorneWifi
from annuaires_pg import uplink_prises, reverse, bat_manuels, all_switchs, bat_switchs from annuaires_pg import uplink_prises, reverse, bat_manuels, all_switchs, bat_switchs
from random import shuffle from random import shuffle
from gen_confs import * from gen_confs import *
from time import localtime import datetime
import config import config
import re import re
from crans.deprecated import deprecated
capture_model = re.compile(r'\((.*)\)') capture_model = re.compile(r'\((.*)\)')
headers_by_model = { headers_by_model = {
@ -38,27 +39,20 @@ headers_by_model = {
gigabit_models = ['J9021A', 'J9145A'] gigabit_models = ['J9021A', 'J9145A']
try:
any
except NameError:
def any(iterable):
for item in iterable:
if item:
return True
return False
class switch(gen_config) : class switch(gen_config) :
# Répertoire ou écire les fichiers de conf """Classe de configuration d'un switch"""
CONF_REP='/tmp/' # avec un / derrière # Répertoire ou écire les fichiers de conf
CONF_REP='/tmp/' # avec un / derrière
config = """%(switch_config_header)s config = """%(switch_config_header)s
hostname "%(switch)s" hostname "%(switch)s"
; Generated %(date_gen)s by switchs.py
%(module-type)s %(module-type)s
;-------------------------------------------------------- Snmp ;-------------------------------------------------------- Snmp
snmp-server contact "root@crans.org" snmp-server contact "root@crans.org"
snmp-server location "Batiment %(bat)s" snmp-server location "Batiment %(bat)s"
;A faire à la main ;A faire à la main
snmpv3 enable snmpv3 enable
snmpv3 restricted-access snmpv3 restricted-access
;snmpv3 user "initial" ;snmpv3 user "initial"
@ -121,7 +115,7 @@ vlan %(vlan_appts)s
exit exit
;-------------------------------------------------------- Logs ;-------------------------------------------------------- Logs
%(INTERFACES_CONF)s %(INTERFACES_CONF)s
;------------------------------------------------------- Accès d'administration ;------------------------------------------------------- Accès d'administration
no telnet-server no telnet-server
no web-management no web-management
aaa authentication ssh login public-key none aaa authentication ssh login public-key none
@ -144,7 +138,7 @@ no cdp run
no stack no stack
""" """
# Serveur DHCP des différent vlans # Serveur DHCP des différent vlans
dhcp_servers = { dhcp_servers = {
'1':'138.231.136.34', '1':'138.231.136.34',
'3':'138.231.148.34', '3':'138.231.148.34',
@ -187,7 +181,7 @@ exit
* un _tulpe_ de noms de switch => reconfig de ces swiths""" * un _tulpe_ de noms de switch => reconfig de ces swiths"""
self.db = crans_ldap() # connexion LDAP self.db = crans_ldap() # connexion LDAP
if type(truc) == list : if type(truc) == list :
# On enlève les chambres "CRA", "????" et EXT qui n'ont pas besion de config # On enlève les chambres "CRA", "????" et EXT qui n'ont pas besion de config
self.chbres = [ch for ch in truc if (ch not in [ "CRA", "????", "EXT" ]) ] self.chbres = [ch for ch in truc if (ch not in [ "CRA", "????", "EXT" ]) ]
self.switch = None self.switch = None
else : else :
@ -199,10 +193,10 @@ exit
def restart(self) : def restart(self) :
if self.chbre : if self.chbre :
# Tout est déja fait # Tout est déja fait
return return
####### Vu qu'il n'y a pas de serveur tftp ici ####### Vu qu'il n'y a pas de serveur tftp ici
# on excécute pas le truc en dessous # on excécute pas le truc en dessous
#for switch in self.switch : #for switch in self.switch :
# self.aff = anim('\treboot de %s' % switch) # self.aff = anim('\treboot de %s' % switch)
# sw = hptools.switch(switch) # sw = hptools.switch(switch)
@ -217,62 +211,12 @@ exit
for switch in self.switch : for switch in self.switch :
self.configure_switch(switch) self.configure_switch(switch)
@deprecated
def configure_chbre(self,chbre) : def configure_chbre(self,chbre) :
""" Recontigure la chambre fournie chambre """ """ Recontigure la chambre fournie chambre.
try : Déprécié. Tous les switchs possèdent une authentification radius."""
bat = chbre[0].lower()
if bat in bat_switchs :
prise = sw_chbre(chbre)
prise.reconfigure() # Vitesse et nom (juste au cas ou ca aurait changé)
elif bat in bat_manuels :
class prise_non_manageable :
def __init__(self,chbre) :
self.chbre = chbre
def __mail(self,sujet) :
To = "clef%s@crans.org" % self.chbre[0].lower()
From = To
conn=smtplib.SMTP('localhost')
txt_mail = "From: Crans scripts <%(From)s>\n"
txt_mail+= "To: %(To)s\n"
txt_mail+= "Subject: (CRANS) %s\n\nMerci." % sujet
conn.sendmail(From, To , txt_mail % { 'From' : From, 'To' : To })
conn.quit()
def disable(self) :
self.__mail("Chambre %s à débrancher." % self.chbre)
def enable(self) :
self.__mail("Chambre %s à brancher." % self.chbre)
prise=prise_non_manageable(chbre)
else :
# Rien a faire
print OK
return True
a = self.db.search('chbre=%s&paiement=ok' % chbre)
a = a['adherent'] + a['club']
if a and 'bloq' not in a[0].blacklist_actif() :
# Il faut activer la prise
anim('\tactivation chbre %s' % chbre)
prise.enable()
else :
# Il faut désactiver la prise
anim('\tdésactivation chbre %s' % chbre)
prise.disable()
print OK
except :
print ERREUR
if self.debug :
import traceback
traceback.print_exc()
return False return False
return True
def configure_switch(self,switch) : def configure_switch(self,switch) :
self.aff = anim('\tconfiguration de %s' % switch) self.aff = anim('\tconfiguration de %s' % switch)
try: try:
@ -291,9 +235,9 @@ exit
return 1 return 1
def __configure_switch(self,switch) : def __configure_switch(self,switch) :
""" Génère le fichier de conf du switch donné """ """ Génère le fichier de conf du switch donné """
### Récupération données du switch ### Récupération données du switch
# Batiment et numéro du switch # Batiment et numéro du switch
bat = switch[3].lower() bat = switch[3].lower()
sw_num = int(switch[5]) sw_num = int(switch[5])
dhcp_servers = self.dhcp_servers dhcp_servers = self.dhcp_servers
@ -303,12 +247,13 @@ exit
self.aff.cycle() self.aff.cycle()
## On veut par défaut tout confier au serveur radius principal ## On veut par défaut tout confier au serveur radius principal
#shuffle(self.rad_servs) #shuffle(self.rad_servs)
rad = self.rad_template * len(self.rad_servs) rad = self.rad_template * len(self.rad_servs)
params = { 'switch' : switch, 'bat' : bat.upper() , params = { 'switch' : switch, 'bat' : bat.upper() ,
'date_gen': str(datetime.datetime.now()),
'radius_key' : radius_key , 'radius_key' : radius_key ,
'radius-serveurs' : rad[:-1] % tuple(self.rad_servs), 'radius-serveurs' : rad[:-1] % tuple(self.rad_servs),
} }
@ -328,7 +273,7 @@ exit
res, msg = commands.getstatusoutput("scp bat%s-%i:cfg/startup-config %s" % (bat, sw_num, old_config.name)) res, msg = commands.getstatusoutput("scp bat%s-%i:cfg/startup-config %s" % (bat, sw_num, old_config.name))
if res != 0: if res != 0:
raise RuntimeError(u"Erreur : impossible de récupérer l'ancienne configuration du switch") raise RuntimeError(u"Erreur : impossible de récupérer l'ancienne configuration du switch")
params['switch_config_header'] = old_config.readline() params['switch_config_header'] = old_config.readline()
old_config.close() old_config.close()
@ -346,7 +291,7 @@ exit
sys.stderr.write(model) sys.stderr.write(model)
params['switch_config_header']=headers_by_model[model] params['switch_config_header']=headers_by_model[model]
except: except:
sys.stderr.write('Impossible de déterminer le header à utiliser (switch %s)' % switch) sys.stderr.write('Impossible de déterminer le header à utiliser (switch %s)' % switch)
params['switch_config_header']= '; J4899A Configuration Editor; Created on release #H.10.50' params['switch_config_header']= '; J4899A Configuration Editor; Created on release #H.10.50'
model = params['switch_config_header'].split(' ', 2)[1] model = params['switch_config_header'].split(' ', 2)[1]
@ -357,10 +302,10 @@ exit
self.aff.cycle() self.aff.cycle()
# Nombre de prises et modèle # Nombre de prises et modèle
nb_prises = machine.nombrePrises() nb_prises = machine.nombrePrises()
if nb_prises < 0 : if nb_prises < 0 :
raise RuntimeError("Erreur : impossible de déterminer les caractéristiques du switch.") raise RuntimeError("Erreur : impossible de déterminer les caractéristiques du switch.")
has_dhcp_snooping = "2810" not in " ".join(machine.info()) has_dhcp_snooping = "2810" not in " ".join(machine.info())
@ -370,7 +315,7 @@ exit
# Dictionnaire prise -> chambre # Dictionnaire prise -> chambre
prise_chbres = reverse(bat) prise_chbres = reverse(bat)
# Prises occupées par des machines du Cr@ns # Prises occupées par des machines du Cr@ns
crans_prises={} crans_prises={}
for m in self.db.search('prise=%s%i*' % (bat.upper(), sw_num))['machine'] : for m in self.db.search('prise=%s%i*' % (bat.upper(), sw_num))['machine'] :
try: crans_prises[m.prise()].append(m) try: crans_prises[m.prise()].append(m)
@ -378,7 +323,7 @@ exit
self.aff.iter = nb_prises+1 self.aff.iter = nb_prises+1
# Paramètres à affecter # Paramètres à affecter
for key in ( 'uplinks', 'non_uplinks' ) : for key in ( 'uplinks', 'non_uplinks' ) :
params[key] = [] params[key] = []
@ -387,21 +332,21 @@ exit
'adm_tagged' : [] , 'adm_untagged' : [] , 'adm_tagged' : [] , 'adm_untagged' : [] ,
'appts_tagged' : [], 'appts_untagged' : [], 'appts_tagged' : [], 'appts_untagged' : [],
# VLans pour le reste: le vlan des adhérents, des # VLans pour le reste: le vlan des adhérents, des
# inconnus et de ceux qui ne paie pas # inconnus et de ceux qui ne paie pas
'default' : [] } 'default' : [] }
personnels_loges = self.db.search('etudes=Personnel ENS')['adherent'] personnels_loges = self.db.search('etudes=Personnel ENS')['adherent']
prises_appartements= [ p.chbre() for p in personnels_loges ] prises_appartements= [ p.chbre() for p in personnels_loges ]
# Génération de la conf de chaque prise # Génération de la conf de chaque prise
for prise in range(1,nb_prises+1): for prise in range(1,nb_prises+1):
self.aff.cycle() self.aff.cycle()
# Conf par défaut : activée, autonégociation # Conf par défaut : activée, autonégociation
prise_params = { 'prise' : prise , 'speed' : '', prise_params = { 'prise' : prise , 'speed' : '',
'etat' : '', 'no_flowcontrol': '' } 'etat' : '', 'no_flowcontrol': '' }
annu_prise = '%i%02i' % (sw_num, prise) # prise telle que notée dans l'annuaire annu_prise = '%i%02i' % (sw_num, prise) # prise telle que notée dans l'annuaire
if uplink_prises[bat].has_key(int(annu_prise)) : if uplink_prises[bat].has_key(int(annu_prise)) :
### Prise d'uplink ### Prise d'uplink
@ -419,7 +364,7 @@ exit
params['non_uplinks'].append(prise) params['non_uplinks'].append(prise)
if crans_prises.has_key("%s%s" % (bat.upper(), annu_prise)) : if crans_prises.has_key("%s%s" % (bat.upper(), annu_prise)) :
### Prise réservée à l'association ### Prise réservée à l'association
wifi=0 wifi=0
adm=0 adm=0
autres=0 autres=0
@ -466,7 +411,7 @@ exit
# chambres. # chambres.
chbres = prise_chbres.get(annu_prise, []) chbres = prise_chbres.get(annu_prise, [])
# Pour les switchs gigabit, on bloque le gigabit par défaut, sauf # Pour les switchs gigabit, on bloque le gigabit par défaut, sauf
# pour les membres actifs et les clubs (cf plus bas) # pour les membres actifs et les clubs (cf plus bas)
if model in gigabit_models: if model in gigabit_models:
prise_params['speed'] = 'speed-duplex auto-10-100' prise_params['speed'] = 'speed-duplex auto-10-100'
@ -478,7 +423,7 @@ exit
# On selectionne les eventuels adherents y residant # On selectionne les eventuels adherents y residant
residents = self.db.search("chbre=%s%s" % (bat, chb)) residents = self.db.search("chbre=%s%s" % (bat, chb))
for adherent in residents['adherent']: for adherent in residents['adherent']:
if adherent.droits(): #Seuls les membres actifs ont le droit à plus if adherent.droits(): #Seuls les membres actifs ont le droit à plus
prise_params['speed'] = '' prise_params['speed'] = ''
# On selectionne les machines fixes de l'adherent, et on ajoute le nombre au quota # On selectionne les machines fixes de l'adherent, et on ajoute le nombre au quota
nombre_de_machines += len(adherent.machines_fixes()) nombre_de_machines += len(adherent.machines_fixes())
@ -487,9 +432,9 @@ exit
# Authentification RADIUS, pas pour les clubs... # Authentification RADIUS, pas pour les clubs...
if not any("cl" in chbre.lower() for chbre in chbres): if not any("cl" in chbre.lower() for chbre in chbres):
# "unauth-vid" est le vlan sur lequel sont envoyés les machines # "unauth-vid" est le vlan sur lequel sont envoyés les machines
# quand l'authentification RADIUS échoue. On met le VLAN 1 pour # quand l'authentification RADIUS échoue. On met le VLAN 1 pour
# éviter les problèmes quand LDAP se ch@#! dessus. # éviter les problèmes quand LDAP se ch@#! dessus.
params['INTERFACES_CONF'] += """aaa port-access mac-based %(prise)s params['INTERFACES_CONF'] += """aaa port-access mac-based %(prise)s
aaa port-access mac-based %(prise)s addr-limit %(nbmac)s aaa port-access mac-based %(prise)s addr-limit %(nbmac)s
aaa port-access mac-based %(prise)s logoff-period 3600 aaa port-access mac-based %(prise)s logoff-period 3600
@ -497,11 +442,11 @@ aaa port-access mac-based %(prise)s unauth-vid 1
""" % { 'nbmac': 2 + nombre_de_machines, 'prise': prise } """ % { 'nbmac': 2 + nombre_de_machines, 'prise': prise }
# On regle le nombre de machines connectables a la prise au nombre de machines # On regle le nombre de machines connectables a la prise au nombre de machines
# sur cette prise dans l'annuaire plus 2 # sur cette prise dans l'annuaire plus 2
else: # ... et pour les clubs, vlans par défaut else: # ... et pour les clubs, vlans par défaut
vlans['default'].append(prise) vlans['default'].append(prise)
# On donne à la prise un nom qui dépend des chambres # On donne à la prise un nom qui dépend des chambres
# connectés dessus # connectés dessus
if chbres : if chbres :
prise_params['nom'] = 'Chambre' prise_params['nom'] = 'Chambre'
if len(chbres) > 1 : prise_params['nom'] += 's' if len(chbres) > 1 : prise_params['nom'] += 's'
@ -522,7 +467,7 @@ aaa port-access mac-based %(prise)s unauth-vid 1
# Petite verif # Petite verif
if not params['uplinks'] or not params['non_uplinks'] : if not params['uplinks'] or not params['non_uplinks'] :
raise RuntimeError('Switch sans uplink ou sans prise adhérent.') raise RuntimeError('Switch sans uplink ou sans prise adhérent.')
def mk_list(liste_prise) : def mk_list(liste_prise) :
""" """
@ -544,12 +489,12 @@ aaa port-access mac-based %(prise)s unauth-vid 1
if nouveau == groupe[1] + 1 : if nouveau == groupe[1] + 1 :
groupe[1] += 1 groupe[1] += 1
else : else :
# Ajout du groupe au résultat # Ajout du groupe au résultat
if groupe[0] == groupe[1] : if groupe[0] == groupe[1] :
result.append(str(groupe[0])) result.append(str(groupe[0]))
else : else :
result.append('-'.join(map(str,groupe))) result.append('-'.join(map(str,groupe)))
# Réinit de groupe # Réinit de groupe
groupe = [ nouveau, nouveau ] groupe = [ nouveau, nouveau ]
return ','.join(result) return ','.join(result)
@ -563,7 +508,7 @@ aaa port-access mac-based %(prise)s unauth-vid 1
for key, prises in vlans.items() : for key, prises in vlans.items() :
vlans[key]=mk_list(prises) vlans[key]=mk_list(prises)
# Config des vlans spéciaux (adm, wifi et appartements) # Config des vlans spéciaux (adm, wifi et appartements)
for v in ('adm', 'wifi', 'hotspot', 'appts') : for v in ('adm', 'wifi', 'hotspot', 'appts') :
params['prises_%s' % v] = '' params['prises_%s' % v] = ''
for t in ('tagged' , 'untagged') : for t in ('tagged' , 'untagged') :
@ -590,7 +535,7 @@ if __name__ == '__main__' :
opts, args = getopt.getopt(sys.argv[1:], 'hga', ['get-conf', 'help', 'all', 'header=' ]) opts, args = getopt.getopt(sys.argv[1:], 'hga', ['get-conf', 'help', 'all', 'header=' ])
if '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) == 1 : if '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) == 1 :
print "%s [-g|--get-conf] <switch>" % sys.argv[0].split('/')[-1].split('.')[0] print "%s [-g|--get-conf] <switch>" % sys.argv[0].split('/')[-1].split('.')[0]
print "Génération du fichier de configuration des switchs donnés." print "Génération du fichier de configuration des switchs donnés."
sys.exit(255) sys.exit(255)
if args[0] == 'all' or 'a' in opts or '--all' in opts : if args[0] == 'all' or 'a' in opts or '--all' in opts :