#!/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 ) * upgrade firmware (copy tftp flash 138.231.136.7 ) * reboot (boot) * génération clef ssh (crypto key generate ssh) * copie fichier de conf (copy tftp startup-config 138.231.136.7 ) * 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('/CRANS/code') #sys.path.append('/home/fred/Crans/zamok/CRANS/code') from hptools import hp 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 time import localtime # from qqch import switchs # Liste des switchs bat_switchs = [ 'b', 'c', 'h', 'i', 'g' ] 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"] def __str__(self) : return 'switchs' def restart(self) : # Rien à faire ici pass def gen_conf(self) : self.chbres.sort() for chbre in self.chbres : if chbre == '????' : continue bat = chbre[0].lower() a = self.db.search('chbre=%s' % chbre)['adherent'] action = '' for adh in a : if (((ann_scol in adh.paiement()) or ((ann_scol-1) in adh.paiement() and localtime()[1]==9)) and 'bloq' not in adh.blacklist_actif()) : # Il faut activer la prise anim('\tactivation chbre %s' % chbre) action = 'enable' break if action == '' : # Il faut désactiver la prise anim('\tdésactivation chbre %s' % chbre) action = 'disable' try : if bat in bat_switchs : # Action sur le switch prise = chbre_prises[bat][chbre[1:].lower()] sw=hp(bat,int(prise[0])) r = sw.set_prise(int(prise[1:4]),action) sw.close() if not r : raise RuntimeError('Erreur de communiquation') else : # Mail au bat To = "bat%s@crans.org" % bat From = To conn=smtplib.SMTP('localhost') txt_mail = "From: Crans scripts <%(From)s>\n" txt_mail+= "To: %(To)s\n" txt_mail+= "Subject: (CRANS) Changement d'état d'une chambre !\n\n" if action == 'disable': txt_mail+= "Chambre %s à débrancher." % chbre else: txt_mail+= "Chambre %s à brancher." % chbre conn.sendmail(From, To , txt_mail % { 'From' : From, 'To' : To }) conn.quit() print OK except : print ERREUR if self.debug : import traceback traceback.print_exc() ### BROUILLON POUR PLUS TARD 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= (batX-N) : reconfigure que ce switch Si qqch= (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 : 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) except : # Prise inconnue raise RuntimeError("Impossible d'associer une prise à la chambre.") 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 """ 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) 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']) else : # Restart tous les switchs for switch in switchs : self.__restart_switch(switch) self.unlock() 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) try : bat = params['bat'] # 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 params['nb_prises'] = nb_prises # Récupération IP params['ip'] = commands.getoutput("host %s" % switch).split()[-1] params['INTERFACES_CONF'] = '' params['MAC_FILTER'] = '' # Dictionnaire prise -> chambre prise_chbres = reverse(bat) # Configuration des prises mac_filter=[] aff.iter = nb_prises+1 for prise in range(1,nb_prises+1): aff.cycle() prise_params = { 'prise' : prise , 'speed' : '', 'etat' : '' } annu_prise = '%i%02i' % (params['sw_num'], prise) 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) else : ### Prise adhérent try : params['non_uplinks'] += ',%i' % prise except : params['non_uplinks'] = str(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'] = ' speed-duplex auto-10\n' 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']=' disable\n' chbres = [] if chbres : prise_params['nom'] = 'Chambre' if len(chbres) > 1 : prise_params['nom'] += 's' 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' else : params['MAC_FILTER'] += self.filtre_mac_template % vars() 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() aff.reinit() print OK except : aff.reinit() self._restore() return 1 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