Gnration fichier de conf switchs

darcs-hash:20040912202209-41617-78c98e9bee1b4ff36b33330890962a67e78ebe9d.gz
This commit is contained in:
pauget 2004-09-12 22:22:09 +02:00
parent 3872766bef
commit 711f723af7

View file

@ -17,24 +17,99 @@
import string, sys, os, commands, smtplib
sys.path.append('/CRANS/code')
#sys.path.append('/home/fred/Crans/zamok/CRANS/code')
from hptools import hp
import snmp
sys.path.append('/usr/scripts/gestion')
from ldap_crans import crans_ldap, ann_scol
from annuaires import chbre_prises #, uplink_prises, reverse
from gen_confs import gen_config, OK, ERREUR, anim
from annuaires import chbre_prises, uplink_prises, reverse
from gen_confs import *
from time import localtime
# from qqch import switchs # Liste des switchs
bat_switchs = [ 'b', 'c', 'h', 'i', 'g' ]
sys.path.append('/CRANS/code')
from hptools import hp
class switch(gen_config) :
def __init__(self,chbres):
""" Chbre doit être une liste de chambres """
self.db = crans_ldap()
# On enlève la chambre "CRA"
self.chbres = [ch for ch in chbres if ch != "CRA"]
# Répertoire ou écire les fichiers de conf
CONF_REP='/var/tftp_switchs/' # avec un / derrière
config = """; J4899A 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
%(MAC_FILTER)s
;-------------------------------------------------------- Accès d'adminsitration
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
;-------------------------------------------------------- Avec mot de passe ;)
password manager
"""
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 nom de switch => reconfig de ce swith"""
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'
@ -44,10 +119,15 @@ class switch(gen_config) :
pass
def gen_conf(self) :
if self.chbres :
self.chbres.sort()
for chbre in self.chbres :
if chbre == '????' :
continue
self.configure_chbre(chbre)
elif self.switch :
self.configure_switch(self.switch)
def configure_chbre(self,chbre) :
""" Recontigure la chambre fournie chambre """
bat = chbre[0].lower()
a = self.db.search('chbre=%s' % chbre)['adherent']
action = ''
@ -94,228 +174,99 @@ class switch(gen_config) :
if self.debug :
import traceback
traceback.print_exc()
return False
### BROUILLON POUR PLUS TARD
return True
class switch2(gen_config) :
# Répertoire ou écire les fichiers de conf
CONF_REP='/tmp/' # avec un / derrière
config = """; J4899A 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 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
;-------------------------------------------------------- Avec mot de passe ;)
password manager
"""
interface_template = """interface %(prise)i\n%(etat)s
name %(nom)s
flow-control%(speed)s
no lacp
exit
"""
filtre_mac_template = "port-security %(prise)i learn-mode static address-limit 3 mac-address%(macs)s\n"
nom = 'switchs'
def __str__(self) :
return self.nom
def __init__(self,qqch='') :
"""
Si qqch='' : reconfigure tous les switchs
Si qqch=<nom d'un switch> (batX-N) : reconfigure que ce switch
Si qqch=<chambre> (XNNN) : regénère le fichier de conf du switch correspondant
et reconfigure uniquement la prise """
# Traitement argument
if not qqch :
self.__params = {}
elif qqch in switchs :
self.__params = { 'bat' : qqch[3].lower() ,
'sw_num' : qqch[5] ,
'switch' : qqch.lower() }
self.nom = 'switch %(switch)s' % self.__params
else :
# Ca doit être une chambre
bat = qqch[0].lower()
if bat in mail_bats :
# Pas de switch à reconfigurer
self.__params = { 'chbre' : qqch.capitalize() ,
'bat' : bat }
else :
def configure_switch(self,switch) :
self.aff = anim('\tconfiguration de %s' % switch)
try :
prise = chbre_prises[bat][qqch[1:]]
self.__params = { 'nom_prise' : qqch.capitalize() ,
'sw_prise' : int(prise[1:]) ,
'bat' : bat ,
'sw_num': int(prise[0]),
'switch': 'bat%s-%s' % (bat, prise[0]) }
self.nom = 'prise %s%s (chbre %s)' % (bat.upper(), prise,qqch)
warn = self.__configure_switch(switch)
self.aff.reinit()
if warn :
print WARNING
if self.debug :
sys.stderr.write(warn)
else :
print OK
except :
# Prise inconnue
raise RuntimeError("Impossible d'associer une prise à la chambre.")
self.aff.reinit()
print ERREUR
self._restore()
return 1
def gen_conf(self) :
""" Génération configuration :
* soit d'un switch si présent dans self.__params
* soit de tous les switchs si aucun présent dans self.__params
* soit d'aucun switch si chbre dans bat non manageable, dans ce cas
envoi un mail quand il faut aller débrancher et retourne 2
En cas d'erreur retourne 1
def __configure_switch(self,switch) :
""" Génère le fichier de conf du switch donné """
warn = ''
conn = snmp.hptools(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 self.__params.has_key('chbre') :
# Pas de switch manageable, il suffit de mailer
anim('\tmail à bat%(bat)s' % self.__params)
print 'TODO'
return 2
self.lock()
if self.__params.has_key('switch') :
# Regénération de la conf d'un switch
self.__gen_switch(self.__params)
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 :
# Regénération de la conf de tous les switchs
for switch in switchs :
params = { 'bat' : switch[3].lower() ,
'sw_num' : int(switch[5]) ,
'switch' : switch.lower() }
self.__gen_switch(params)
self.unlock()
def restart(self) :
"""
Si l'instance à été initialisée avec une chbre reconfigure cette chambre
Sinon reconfigure le switch founi, si aucun fourni, les reconfigure tous
"""
if self.__params.has_key('chbre') :
# Rien à faire, le mail doit être envoyé
return
self.lock()
if self.__params.has_key('sw_prise') :
# Utiliser la classe hptools et/ou faire du snmp
anim('\treconfiguration prise' )
elif self.__params.has_key('switch') :
# Restart d'un seul switch
self.__restart_switch(self.__params['switch'])
dict[key] += ',%i' % prise
else :
# Restart tous les switchs
for switch in switchs :
self.__restart_switch(switch)
# de la forme xxx,l1
if int(l1)+1 == prise :
dict[key] += '-%i' % prise
else :
dict[key] += ',%i' % prise
else :
dict[key] = str(prise)
self.unlock()
return dict
def __gen_switch(self,params) :
""" params est un dictionnaire avec les keys bat, sw_num et switch """
aff = anim('\tgénération de %(switch)s.conf' % params)
### Récupération données du switch
# Bat
bat = switch[3].lower()
params = { 'switch' : switch, 'bat' : bat.upper() }
# Numéro du switch
try :
bat = params['bat']
sw_num = int(switch[5])
except :
sw_num = 0
# Nombre de prises
nb_prises = """
METTRE CA DANS LA CLASSE S'OCCUPANT DU SNMP
try :
nb = int(sys.argv[2])
except :
a=os.popen("snmpget -c public %s system.sysDescr.0 2>/dev/null" % switch)
try :
version = string.strip(string.split(string.split(a.readlines()[0],',')[0],'=')[1])
except :
version = ''
a.close()
if version == 'HP J4900A ProCurve Switch 2626' :
nb=26
elif version == 'HP J4899A ProCurve Switch 2650' :
nb=50
else :
print "Erreur : impossible de déterminer le nombre de ports"
sys.exit(1)
"""
nb_prises = 50
nb_prises = conn.nb_prises()
if not nb_prises :
raise RuntimeError("Erreur : impossible de déterminer le nombre de ports")
params['nb_prises'] = nb_prises
# Récupération IP
# IP
params['ip'] = commands.getoutput("host %s" % switch).split()[-1]
### Configuration prises
params['INTERFACES_CONF'] = ''
params['MAC_FILTER'] = ''
# Dictionnaire prise -> chambre
prise_chbres = reverse(bat)
# Configuration des prises
mac_filter=[]
aff.iter = nb_prises+1
self.aff.iter = nb_prises+1
for prise in range(1,nb_prises+1):
aff.cycle()
self.aff.cycle()
prise_params = { 'prise' : prise , 'speed' : '', 'etat' : '' }
annu_prise = '%i%02i' % (params['sw_num'], prise)
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)]
try : params['uplinks'] += ',%i' % prise
except : params['uplinks'] = str(prise)
params = add_prise(params,'uplinks',prise)
else :
### Prise adhérent
try : params['non_uplinks'] += ',%i' % prise
except : params['non_uplinks'] = str(prise)
params = add_prise(params,'non_uplinks',prise)
if prise_chbres.has_key(annu_prise) :
chbres = prise_chbres[annu_prise]
@ -326,27 +277,39 @@ except :
else :
# Prise non référencée dans l'annuaire
prise_params['nom'] = "Pas_dans_l'annuaire"
prise_params['etat']=' disable\n'
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'
if len(chbres) > 1 : prise_params['nom'] += 's'
macs = ''
for chbre in chbres :
prise_params['nom'] += '_' + chbre
# Etat
macs = ''
machines = self.base.search('chbre=%s%s' % (bat.upper(), chbre) )['machine']
for m in machines :
if 'bloq' in m.blacklist_actif() : continue
macs += ' ' + m.mac()
if not macs :
prise_params['etat']=' disable\n'
# Macs sur la prise
nb = 0
adh = self.db.search('chbre=%s%s' % (bat.upper(), chbre) )['adherent']
if nb>=3 :
warn += 'Trop de macs sur la prise %i\n' % prise
continue
if not adh :
continue
elif len(adh) == 1 :
adh = adh[0]
if 'bloq' in adh.blacklist_actif() : continue
for m in adh.machines() :
macs += ' ' + m.mac().encode('iso-8859-15').replace(':','')
nb += 1
else :
params['MAC_FILTER'] += self.filtre_mac_template % vars()
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
@ -354,25 +317,18 @@ except :
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 = self._open_conf(self.CONF_REP + switch + '.conf')
fd.write(self.config % params)
fd.close()
aff.reinit()
print OK
return warn
except :
aff.reinit()
self._restore()
return 1
if __name__ == '__main__' :
if '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) != 2 :
print "%s <switch>" % sys.argv[0].split('/')[-1].split('.')[0]
print "Génération du fichier de configuration de switch donnée."
sys.exit(255)
def __restart_switch(self,switch) :
anim('\trestart %s' % switch)
try :
print 'TODO'
except :
print ERREUR
if self.debug :
import traceback
traceback.print_exc()
return 1
sw = switch(sys.argv[1])
sw.debug = 1
sw.reconfigure()