scripts/gestion/gen_confs/switchs.py
pauget 0084764d78 Envoi de mail que si dans bon batiment.
darcs-hash:20050422123506-41617-417079cb91e826efe039220dcbff6a37d7cb8780.gz
2005-04-22 14:35:06 +02:00

387 lines
11 KiB
Python
Executable file

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
""" 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
argument : nom du switch
procédure de configuration initiale :
* mot de passe admin (password manager user-name <username>)
* upgrade firmware (copy tftp flash 138.231.136.7 <file>)
* reboot (boot)
* génération clef ssh (crypto key generate ssh)
* copie fichier de conf (copy tftp startup-config 138.231.136.7 <file>)
* faire le stacking et le snmpv3 à la main
pour les reconfiguration juste copier le fichier de conf
"""
import string, sys, os, commands, smtplib
sys.path.append('/usr/scripts/gestion')
from hptools import hpswitch, sw_chbre
from ldap_crans import crans_ldap
from annuaires import chbre_prises, uplink_prises, reverse
from random import shuffle
from gen_confs import *
from time import localtime
from annuaires import bat_switchs
class switch(gen_config) :
# Répertoire ou écire les fichiers de conf
CONF_REP='/var/tftp_switchs/' # avec un / derrière
config = """; %(modele)s Configuration Editor; Created on release #H.08.53
hostname "%(switch)s"
;-------------------------------------------------------- Snmp
snmp-server contact "root@crans.org"
snmp-server location "Batiment %(bat)s"
;A faire à la main
snmpv3 enable
snmpv3 restricted-access
;snmpv3 user "initial"
snmpv3 user "crans"
snmpv3 group ManagerPriv user "crans" sec-model ver3
snmp-server community "public" Operator
;-------------------------------------------------------- Réglage heure/date
time timezone 60
time daylight-time-rule Western-Europe
sntp server 138.231.136.6
timesync sntp
sntp unicast
;-------------------------------------------------------- Misc
console inactivity-timer 30
;-------------------------------------------------------- Logs
logging 138.231.136.7
;-------------------------------------------------------- Logs
%(INTERFACES_CONF)s
;-------------------------------------------------------- IP du switch
ip default-gateway 138.231.136.4
vlan 1
name "DEFAULT_VLAN"
untagged 1-%(nb_prises)d
ip address %(ip)s 255.255.248.0
ip igmp
no ip igmp querier
exit
vlan 2
name "Wifi"
tagged %(ports_wifi)s
ip igmp blocked %(ports_wifi)s
exit
;-------------------------------------------------------- Accès d'adminsitration
no telnet-server
no web-management
aaa authentication ssh login public-key
aaa authentication ssh enable public-key
ip ssh
ip ssh version 2
ip authorized-managers 138.231.136.0 255.255.255.0
ip authorized-managers 138.231.137.216
ip authorized-managers 138.231.137.215
;-------------------------------------------------------- Spanning-tree
spanning-tree
; Config des uplinks
no spanning-tree %(uplinks)s edge-port
; Config des prises adhérent
spanning-tree %(non_uplinks)s point-to-point-mac auto
spanning-tree %(non_uplinks)s priority 15
;-------------------------------------------------------- Serveurs radius
radius-server dead-time 2
radius-server key %(radius_key)s
%(radius-serveurs)s
;-------------------------------------------------------- Filtrage mac
aaa port-access mac-based %(non_uplinks)s
aaa port-access mac-based %(non_uplinks)s addr-limit 32
aaa port-access mac-based %(non_uplinks)s logoff-period 9999999
aaa port-access mac-based addr-format multi-colon
;-------------------------------------------------------- Bricoles
no cdp run
no stack
"""
interface_template = """interface %(prise)i%(etat)s
name "%(nom)s"
flow-control%(speed)s
no lacp
exit
"""
# Serveurs radius
rad_servs = [ '138.231.136.10' , '138.231.136.18', '138.231.136.6' ]
rad_template = "radius-server host %s\n"
def __init__(self,truc):
""" truc est soit :
* une _liste_ de chambres => reconfig de ces chambres
* un _tulpe_ de noms de switch => reconfig de ces swiths"""
self.db = crans_ldap() # connexion LDAP
if type(truc) == list :
# 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.switch = None
else :
self.chbres = None
self.switch = truc
def __str__(self) :
return 'switchs'
def restart(self) :
if self.chbre :
# Tout est déja fait
return
####### Vu qu'il n'y a pas de serveur tftp ici
# on excécute pas le truc en dessous
#for switch in self.switch :
# self.aff = anim('\treboot de %s' % switch)
# sw = hptools.switch(switch)
# sw.update()
def gen_conf(self) :
if self.chbres :
self.chbres.sort()
for chbre in self.chbres :
self.configure_chbre(chbre)
elif self.switch :
for switch in self.switch :
self.configure_switch(switch)
def configure_chbre(self,chbre) :
""" Recontigure la chambre fournie chambre """
try :
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 True
def configure_switch(self,switch) :
self.aff = anim('\tconfiguration de %s' % switch)
try :
warn = self.__configure_switch(switch)
self.aff.reinit()
if warn :
print WARNING
if self.debug :
sys.stderr.write(warn)
else :
print OK
except :
self.aff.reinit()
print ERREUR
self._restore()
return 1
def __configure_switch(self,switch) :
""" Génère le fichier de conf du switch donné """
warn = ''
conn = hpswitch(switch)
### Récupération données du switch
# Bat
bat = switch[3].lower()
from secrets import radius_key
shuffle(self.rad_servs)
rad = self.rad_template * len(self.rad_servs)
params = { 'switch' : switch, 'bat' : bat.upper() ,
'uplinks' : [] , 'non_uplinks' : [] ,
'radius_key' : radius_key ,
'radius-serveurs' : rad[:-1] % tuple(self.rad_servs)}
# Numéro du switch
try :
sw_num = int(switch[5])
except :
sw_num = 0
# Nombre de prises et modèle
nb_prises = conn.nb_prises()
modele = conn.version()
if not nb_prises or not modele :
raise RuntimeError("Erreur : impossible de déterminer les caractéristiques du switch.")
params['nb_prises'] = nb_prises
params['modele'] = modele.split()[1]
# IP
params['ip'] = commands.getoutput("host %s" % switch).split()[-1]
### Configuration prises
params['INTERFACES_CONF'] = ''
# Dictionnaire prise -> chambre
prise_chbres = reverse(bat)
self.aff.iter = nb_prises+1
for prise in range(1,nb_prises+1):
self.aff.cycle()
prise_params = { 'prise' : prise , 'speed' : '', 'etat' : '' }
annu_prise = '%i%02i' % (sw_num, prise) # prise telle que notée dans l'annuaire
if uplink_prises[bat].has_key(int(annu_prise)) :
### Prise d'uplink
prise_params['nom'] = uplink_prises[bat][int(annu_prise)]
params['uplinks'].append(prise)
else :
### Prise adhérent
params['non_uplinks'].append(prise)
# Interrogation de l'annuaire
if prise_chbres.has_key(annu_prise) :
chbres = prise_chbres[annu_prise]
elif prise_chbres.has_key(annu_prise+'-') :
# Prise en 10
prise_params['speed'] = '\n speed-duplex auto-10'
chbres = prise_chbres[annu_prise+'-']
else :
# Prise non référencée dans l'annuaire
prise_params['nom'] = "Pas_dans_l'annuaire"
prise_params['etat']='\n disable'
chbres = []
## Configuration de la prise adhérent
if chbres :
# Nom
prise_params['nom'] = 'Chambre'
if len(chbres) > 1 : prise_params['nom'] += 's'
for chbre in chbres :
prise_params['nom'] += '_' + chbre
# Besoin d'activer la prise ?
act = 0
for chbre in chbres :
res = self.db.search('chbre=%s%s&paiement=ok' % (bat.upper(), chbre) )
for res in res['adherent'] + res['club'] :
if 'bloq' not in res.blacklist_actif() :
act = 1
break
if not act :
# Peut être une borne wifi ?
if not self.db.search('prise=%s%s' % (bat.upper(), annu_prise))['machine'] :
prise_params['etat']='\n disable'
params['INTERFACES_CONF'] += self.interface_template % prise_params
# Petite verif
if not params['uplinks'] or not params['non_uplinks'] :
raise RuntimeError('Switch sans uplink ou sans prise adhérent.')
def mk_list(liste_prise) :
"""
transforme une liste de prises en une chaine pour le switch
exemple : 1, 3, 4, 5, 6, 7, 9, 10, 11, 12 => 1,3-7,9-12
"""
liste_prise.sort()
# initialisation
i = liste_prise.pop(0)
groupe = [ i, i ]
result = []
liste_prise.append(9999) # apparaitra jamais dans la liste
while liste_prise :
nouveau = liste_prise.pop(0)
if nouveau == groupe[1] + 1 :
groupe[1] += 1
else :
# Ajout du groupe au résultat
if groupe[0] == groupe[1] :
result.append(str(groupe[0]))
else :
result.append('-'.join(map(str,groupe)))
# Réinit de groupe
groupe = [ nouveau, nouveau ]
return ','.join(result)
params['ports_wifi'] = list(params['uplinks'])
# Borne wifi sur la prise ?
for m in self.db.search('host=*.wifi.crans.org&prise=%s%i*' % (bat.upper(), sw_num))['machine'] :
params['ports_wifi'].append(int(m.prise()[2:]))
params['inv_ports_wifi'] = []
for prise in range(1,nb_prises+1) :
if prise not in params['ports_wifi'] :
params['inv_ports_wifi'].append(prise)
# Conversion des listes
for key in [ 'ports_wifi', 'inv_ports_wifi', 'uplinks', 'non_uplinks' ] :
params[key] = mk_list(params[key])
params['INTERFACES_CONF'] = params['INTERFACES_CONF'][:-1]
fd = self._open_conf(self.CONF_REP + switch + '.conf')
fd.write(self.config % params)
fd.close()
return warn
if __name__ == '__main__' :
if '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) == 1 :
print "%s <switch>" % sys.argv[0].split('/')[-1].split('.')[0]
print "Génération du fichier de configuration des switchs donnés."
sys.exit(255)
if sys.argv[1] == 'all' :
switchs = ( 'batg-6', 'batg-5', 'batg-4', 'batg-2', 'batg-1', 'batg' ,
'batj-2', 'batj-1', 'batj' ,
'bati-2', 'bati-1', 'bati' ,
'bath-1', 'bath' ,
'batc-2', 'batc-1', 'batc' ,
'batb-3', 'batb-2', 'batb-1', 'batb' )
else :
switchs = tuple(sys.argv[1:])
sw = switch(switchs)
sw.debug = 1
sw.reconfigure()