[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.
|
élémentaires sur les switchs manageable HP 26xx.
|
||||||
|
|
||||||
Frédéric PAUGET
|
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 time import sleep
|
||||||
from sys import stderr, path
|
from sys import stderr, path
|
||||||
|
@ -15,10 +17,12 @@ from commands import getstatusoutput
|
||||||
from annuaires_pg import chbre_prises, all_switchs
|
from annuaires_pg import chbre_prises, all_switchs
|
||||||
from os.path import exists
|
from os.path import exists
|
||||||
from os import system
|
from os import system
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
from re import findall
|
from re import findall
|
||||||
import re
|
import re
|
||||||
from config import vlans
|
from config import vlans
|
||||||
|
import netsnmp
|
||||||
|
|
||||||
path.append('/usr/scripts/gestion')
|
path.append('/usr/scripts/gestion')
|
||||||
from ldap_crans import crans_ldap
|
from ldap_crans import crans_ldap
|
||||||
|
@ -123,6 +127,7 @@ class snmp :
|
||||||
"""
|
"""
|
||||||
self.host = host
|
self.host = host
|
||||||
self.version = version
|
self.version = version
|
||||||
|
self.community = community
|
||||||
|
|
||||||
if version == '1' or version == '2c' :
|
if version == '1' or version == '2c' :
|
||||||
self.options = "-v %s -c '%s' %s " % ( version, community, host )
|
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 ) )
|
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
|
""" Retourne le résultat de snmpwalk
|
||||||
le retour est un dictionnaire { oid : valeur }
|
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')
|
lignes = self.__exec('snmpwalk -Ox %s %s' % (self.options, base_oid ) ).split('\n')
|
||||||
result = {}
|
result = {}
|
||||||
for ligne in lignes:
|
for ligne in lignes:
|
||||||
|
@ -193,6 +200,37 @@ class snmp :
|
||||||
pass
|
pass
|
||||||
return result
|
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
|
### Gestion des switchs proprement dite
|
||||||
|
|
||||||
|
@ -228,13 +266,13 @@ class hpswitch :
|
||||||
if not prise : prise = self.prise
|
if not prise : prise = self.prise
|
||||||
if self.__debug : self.__logDest.write("HP DEBUG : show_prise_mac(prise=%s)\n" % prise)
|
if self.__debug : self.__logDest.write("HP DEBUG : show_prise_mac(prise=%s)\n" % prise)
|
||||||
try:
|
try:
|
||||||
data = self.walk('STATISTICS-MIB::hpSwitchPortFdbAddress.%d' % int(prise))
|
data = self.walk('STATISTICS-MIB::hpSwitchPortFdbAddress.%d' % int(prise),
|
||||||
|
bin_comp=True)
|
||||||
macs = []
|
macs = []
|
||||||
for value in data.itervalues():
|
for value in data.itervalues():
|
||||||
mac = value.replace(' ', '').lower().replace('"', '')
|
if len(value) != 6:
|
||||||
if not re.match('([0-9a-f]{2}){6}', mac):
|
continue # Should not happen
|
||||||
mac = mac.encode('hex').lower()
|
mac = ':'.join('%02x' % ord(c) for c in value)
|
||||||
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])
|
|
||||||
macs.append(mac)
|
macs.append(mac)
|
||||||
return macs
|
return macs
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -247,7 +285,8 @@ class hpswitch :
|
||||||
mac = mac.lower()
|
mac = mac.lower()
|
||||||
# On interroge le switch
|
# On interroge le switch
|
||||||
try:
|
try:
|
||||||
data = self.walk('STATISTICS-MIB::hpSwitchPortFdbAddress')
|
data = self.walk('STATISTICS-MIB::hpSwitchPortFdbAddress',
|
||||||
|
bin_comp=True)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print >> sys.stderr, "Le switch %s fait du caca..." % self.switch
|
print >> sys.stderr, "Le switch %s fait du caca..." % self.switch
|
||||||
return None
|
return None
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue