346 lines
10 KiB
Python
Executable file
346 lines
10 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 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.07.32
|
|
|
|
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
|
|
;-------------------------------------------------------- Accès d'adminsitration
|
|
no telnet-server
|
|
no web-management
|
|
aaa authentication ssh login 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
|
|
;STACKING_CONF
|
|
;-------------------------------------------------------- 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
|
|
no cdp run
|
|
no stack
|
|
"""
|
|
|
|
interface_template = """interface %(prise)i%(etat)s
|
|
name "%(nom)s"
|
|
flow-control%(speed)s
|
|
no lacp
|
|
exit
|
|
"""
|
|
filtre_mac_template = "port-security %i learn-mode static address-limit 3 mac-address%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 la chambre "CRA" et "????"
|
|
self.chbres = [ch for ch in truc if (ch != "CRA" and ch!= "????") ]
|
|
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é)
|
|
else :
|
|
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)
|
|
|
|
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)
|
|
def add_prise(dict, key, prise) :
|
|
""" ajoute la prise à la liste de prise du dictionnaire dict
|
|
dict[key] est ensuite de la forme 1,3-7,9-12 (ajout des prises
|
|
1, 3, 4, 5, 6, 7, 9, 10, 11, 12 dans l'ordre)
|
|
"""
|
|
if dict.has_key(key) :
|
|
l1 = dict[key].split(',')[-1]
|
|
l2 = dict[key].split('-')[-1]
|
|
if len(l1)>len(l2) :
|
|
# de la forme xxx-l2
|
|
if int(l2)+1 == prise :
|
|
dict[key] = '-'.join(dict[key].split('-')[:-1]) + '-%i'% prise
|
|
else :
|
|
dict[key] += ',%i' % prise
|
|
else :
|
|
# de la forme xxx,l1
|
|
if int(l1)+1 == prise :
|
|
dict[key] += '-%i' % prise
|
|
else :
|
|
dict[key] += ',%i' % prise
|
|
else :
|
|
dict[key] = str(prise)
|
|
|
|
return dict
|
|
|
|
### Récupération données du switch
|
|
# Bat
|
|
bat = switch[3].lower()
|
|
params = { 'switch' : switch, 'bat' : bat.upper() }
|
|
|
|
# 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'] = ''
|
|
params['MAC_FILTER'] = '' # Pas pour l'instant
|
|
|
|
# Dictionnaire prise -> chambre
|
|
prise_chbres = reverse(bat)
|
|
|
|
mac_filter=[]
|
|
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 = add_prise(params,'uplinks',prise)
|
|
else :
|
|
### Prise adhérent
|
|
params = add_prise(params,'non_uplinks',prise)
|
|
|
|
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 :
|
|
prise_params['nom'] = 'Chambre'
|
|
if len(chbres) > 1 : prise_params['nom'] += 's'
|
|
|
|
macs = ''
|
|
for chbre in chbres :
|
|
prise_params['nom'] += '_' + chbre
|
|
|
|
# Macs sur la prise
|
|
nb = 0
|
|
res = self.db.search('chbre=%s%s&paiement=ok' % (bat.upper(), chbre) )
|
|
res = res['adherent'] + res['club']
|
|
if nb>=3 :
|
|
warn += 'Trop de macs sur la prise %i\n' % prise
|
|
continue
|
|
if not res :
|
|
continue
|
|
elif len(res) == 1 :
|
|
res = res[0]
|
|
if 'bloq' in res.blacklist_actif() : continue
|
|
for m in res.machines() :
|
|
macs += ' ' + m.mac().encode('iso-8859-15').replace(':','')
|
|
nb += 1
|
|
else :
|
|
warn += 'Plusieurs adherents dans la chambre %s%s\n' % (bat.upper(), chbre)
|
|
if not macs :
|
|
prise_params['etat']='\n disable'
|
|
else :
|
|
params['MAC_FILTER'] += self.filtre_mac_template % ( prise, macs )
|
|
|
|
params['INTERFACES_CONF'] += self.interface_template % prise_params
|
|
|
|
# Petites verif
|
|
if not params.has_key('uplinks') or not params.has_key('non_uplinks') :
|
|
raise RuntimeError('Switch sans uplink ou sans prise adhérent.')
|
|
|
|
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-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()
|