#!/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('/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 # Liste des switchs bat_switchs = [ 'b', 'c' , 'h' , 'i' , 'g' , 'j' ] 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 """ 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() prise = sw_chbre(chbre) a = self.db.search('chbre=%s&paiement=ok' % chbre) a = a['adherent'] + a['club'] sujet = '' if a and 'bloq' not in a[0].blacklist_actif() : # Il faut activer la prise anim('\tactivation chbre %s' % chbre) if bat in bat_switchs : prise.enable() else : sujet = "Chambre %s à brancher." % chbre else : # Il faut désactiver la prise anim('\tdésactivation chbre %s' % chbre) if bat in bat_switchs : prise.disable() else : sujet = "Chambre %s à débrancher." % chbre if sujet : # Il faut envoyer un mail To = "clef%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) %s\n\nMerci." % sujet 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() 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' % (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 " % 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()