[hptools] éviter les collisions de mac
La fonction walk de hptools fait appel au binaire snmpwalk. Celui-ci renvoi (dans le cas d'une demande des hpSwitchPortFdbAddress) des lignes de la forme: STATISTICS-MIB::hpSwitchPortFdbAddress.$(numerodeport).'$(mac en binaire)' "$(mac en hexa) " Par $(mac en binaire), je désigne une représentation où chaque octet de l'adresse mac est représenté par le caractère ascii correspondant. Cependant, il existe plus d'un caractère ascii non-représentable, et ces caractères sont tous remplacés par des ".". Cela donne des résultats avec plusieurs fois le même oid (quand présents sur la même prise): STATISTICS-MIB::hpSwitchPortFdbAddress.25.'......' "D4 BE D9 80 CD F8 " STATISTICS-MIB::hpSwitchPortFdbAddress.25.'......' "DC 9F DB 07 D9 12 " STATISTICS-MIB::hpSwitchPortFdbAddress.25.'......' "DC 9F DB 07 DA A8 " STATISTICS-MIB::hpSwitchPortFdbAddress.25.'......' "DC 9F DB 07 DB 1B " (^^^^ ex ici avec des bornes wifi sur le port 25) Cela pose un problème certain car la fonction walk renvoie un dictionnaire indexé par les oid, ce qui écrase donc les données précédentes. On patche en utilisant une lib snmp sachant traiter des oid binaires arbitraires. Comme cela change un peu la sortie de la fonction walk, j'ai préféré garder l'ancienne version, tout en permettant l'utilisation de la nouvelle via un argument optionnel de compatibilité.
This commit is contained in:
parent
6c54abcbf6
commit
e05c4be14c
1 changed files with 46 additions and 7 deletions
|
@ -8,6 +8,8 @@ Donne la classe switch qui permet d'effectuer les opérations
|
|||
élémentaires sur les switchs manageable HP 26xx.
|
||||
|
||||
Frédéric PAUGET
|
||||
TODO réécrire ce script (la moitié des fonctions ne marchent plus,
|
||||
l'autre ferait bien d'utiliser netsnmp ou équivalent)
|
||||
"""
|
||||
from time import sleep
|
||||
from sys import stderr, path
|
||||
|
@ -15,10 +17,12 @@ from commands import getstatusoutput
|
|||
from annuaires_pg import chbre_prises, all_switchs
|
||||
from os.path import exists
|
||||
from os import system
|
||||
import os
|
||||
import sys
|
||||
from re import findall
|
||||
import re
|
||||
from config import vlans
|
||||
import netsnmp
|
||||
|
||||
path.append('/usr/scripts/gestion')
|
||||
from ldap_crans import crans_ldap
|
||||
|
@ -123,6 +127,7 @@ class snmp :
|
|||
"""
|
||||
self.host = host
|
||||
self.version = version
|
||||
self.community = community
|
||||
|
||||
if version == '1' or version == '2c' :
|
||||
self.options = "-v %s -c '%s' %s " % ( version, community, host )
|
||||
|
@ -179,10 +184,12 @@ class snmp :
|
|||
"""
|
||||
return self.__exec('snmpset -O vq %s %s %s %s' % (self.options, oid, typ, val ) )
|
||||
|
||||
def walk(self,base_oid) :
|
||||
def walk(self,base_oid, bin_comp=False) :
|
||||
""" Retourne le résultat de snmpwalk
|
||||
le retour est un dictionnaire { oid : valeur }
|
||||
"""
|
||||
if bin_comp:
|
||||
return snmp.bin_walk(self, base_oid)
|
||||
lignes = self.__exec('snmpwalk -Ox %s %s' % (self.options, base_oid ) ).split('\n')
|
||||
result = {}
|
||||
for ligne in lignes:
|
||||
|
@ -193,6 +200,37 @@ class snmp :
|
|||
pass
|
||||
return result
|
||||
|
||||
def bin_walk(self, base_oid):
|
||||
""" Retourne le résultat de snmpwalk
|
||||
le retour est un dictionnaire { oid : valeur }
|
||||
TODO: prendre en compte l'auth et le snmp vn, n>1
|
||||
TODO: malheureusement, la plupart des fonctions faisant appel
|
||||
à walk ne marchent pas out-of-the-box, il faut donc
|
||||
d'abord les convertir avant de leur faire utiliser cette nouvelle
|
||||
fonction
|
||||
"""
|
||||
try:
|
||||
prefix, b_oid = base_oid.split('::', 1)
|
||||
except ValueError:
|
||||
raise NotImplementedError('Merci de préciser un MIB')
|
||||
|
||||
os.environ['MIBS'] = prefix
|
||||
# ^^^ Je suis triste de faire ça
|
||||
|
||||
oid_obj = netsnmp.VarList(netsnmp.Varbind(b_oid))
|
||||
# oid_obj est remple des réponses du snmpwalk
|
||||
netsnmp.snmpwalk(oid_obj,
|
||||
Version = int(self.version),
|
||||
DestHost=self.host,
|
||||
Community=self.community,
|
||||
)
|
||||
#UseLongNames=1, #ceci devrait marcher selon la doc
|
||||
#en pratique, non (cf /usr/lib/python2.7/dist-packages/netsnmp/client.py)
|
||||
|
||||
# On renvoie un résultat ressemblant à ce que fait le snmpwalk shell
|
||||
return { '%s::%s.%s' % (prefix, res.tag, res.iid): res.val
|
||||
for res in oid_obj }
|
||||
|
||||
#############################################################################################
|
||||
### Gestion des switchs proprement dite
|
||||
|
||||
|
@ -228,13 +266,13 @@ class hpswitch :
|
|||
if not prise : prise = self.prise
|
||||
if self.__debug : self.__logDest.write("HP DEBUG : show_prise_mac(prise=%s)\n" % prise)
|
||||
try:
|
||||
data = self.walk('STATISTICS-MIB::hpSwitchPortFdbAddress.%d' % int(prise))
|
||||
data = self.walk('STATISTICS-MIB::hpSwitchPortFdbAddress.%d' % int(prise),
|
||||
bin_comp=True)
|
||||
macs = []
|
||||
for value in data.itervalues():
|
||||
mac = value.replace(' ', '').lower().replace('"', '')
|
||||
if not re.match('([0-9a-f]{2}){6}', mac):
|
||||
mac = mac.encode('hex').lower()
|
||||
mac = "%s:%s:%s:%s:%s:%s" % (mac[0:2], mac[2:4], mac[4:6], mac[6:8], mac[8:10], mac[10:12])
|
||||
if len(value) != 6:
|
||||
continue # Should not happen
|
||||
mac = ':'.join('%02x' % ord(c) for c in value)
|
||||
macs.append(mac)
|
||||
return macs
|
||||
except ValueError:
|
||||
|
@ -247,7 +285,8 @@ class hpswitch :
|
|||
mac = mac.lower()
|
||||
# On interroge le switch
|
||||
try:
|
||||
data = self.walk('STATISTICS-MIB::hpSwitchPortFdbAddress')
|
||||
data = self.walk('STATISTICS-MIB::hpSwitchPortFdbAddress',
|
||||
bin_comp=True)
|
||||
except ValueError:
|
||||
print >> sys.stderr, "Le switch %s fait du caca..." % self.switch
|
||||
return None
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue