Version plus pythonesque de HPTools. Pleinement fonctionnelle sous jessie.
* Les requêtes de type lecture seule marchent très bien tout court ; * Celles de type écriture sont sans effet sous wheezy. C'est a priori un bug dans python-netsnmp
This commit is contained in:
parent
cd5ae8aaa5
commit
a0f0c80ead
8 changed files with 932 additions and 0 deletions
124
gestion/hptools2/tools.py
Normal file
124
gestion/hptools2/tools.py
Normal file
|
@ -0,0 +1,124 @@
|
|||
#!/bin/bash /usr/scripts/python.sh
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Fournit des outils et fonctions appelables au besoin"""
|
||||
|
||||
from gestion import annuaires_pg
|
||||
from multiprocessing import Process, Manager
|
||||
|
||||
from .switch import HPSwitch
|
||||
from .mac import MACFactory, format_mac
|
||||
|
||||
def filter_uplink(switch, stuff):
|
||||
"""Filtre les prises uplink d'un retour.
|
||||
stuff est une liste de la forme
|
||||
[(port_id, mac), ...]"""
|
||||
sortie = []
|
||||
|
||||
# Retourne "batg", "4.adm.crans.org", par exemple.
|
||||
bat, num = switch.split('-', 1)
|
||||
|
||||
# On filtre ce qui n'est pas utile.
|
||||
bat = bat[-1]
|
||||
num = int(num[0])
|
||||
|
||||
# On récupère les infos utiles.
|
||||
uplink = annuaires_pg.uplink_prises[bat]
|
||||
gen_num_prise = 100 * num
|
||||
|
||||
for (port_id, mac) in stuff:
|
||||
num_prise = gen_num_prise + port_id
|
||||
if not num_prise in uplink:
|
||||
sortie.append((port_id, mac))
|
||||
|
||||
return sortie
|
||||
|
||||
# +--------------------------------------------------------+
|
||||
# | Mac Tracking Functions |
|
||||
# +--------------------------------------------------------+
|
||||
"""Ces fonctions servent à tracker une mac sur le réseau.
|
||||
La fonction trace_mac s'occupe de ce travail. Elle utilise
|
||||
la librairie multiprocessing pour spawner un process par
|
||||
switch, et aller récupérer auprès de ceux-ci la liste des
|
||||
MACs connectées, et les ports allant bien.
|
||||
|
||||
Multiprocessing ne mettant pas en place du partage de variable
|
||||
par défaut, les objets retournés le sont via un Manager, dans
|
||||
un dico, sans structure complexe.
|
||||
|
||||
Une solution dans laquelle les switches seraient renvoyés dans
|
||||
leur structure python existe, mais elle est plus coûteuse,
|
||||
et peu utile dans notre cas. (l'overhead engendré par la méthode
|
||||
à base de dicos et régénération dans le processus parent est
|
||||
epsilonesque)"""
|
||||
|
||||
def fetch_all_ports(switch, output):
|
||||
"""Récupère l'ensemble des ports d'un switch, avec les MACS
|
||||
dessus."""
|
||||
|
||||
sw = HPSwitch(switch)
|
||||
# output est un Manager().dict()
|
||||
__stuff = sw.fetch_all_ports()
|
||||
__stuff = filter_uplink(switch, __stuff)
|
||||
output[switch] = __stuff
|
||||
|
||||
def populate_all_switches():
|
||||
"""Remplit l'ensemble des switches avec les MACS qui sont
|
||||
présentes sur leurs ports"""
|
||||
switches = annuaires_pg.all_switchs()
|
||||
hp_switches = {
|
||||
switch : HPSwitch(switch)
|
||||
for switch in switches
|
||||
}
|
||||
processes = {}
|
||||
|
||||
# La sortie des appels de fetch_all_ports sera écrite dans ce dico.
|
||||
# On évitera la concurrence en utilisant le nom du switch comme
|
||||
# séparateur
|
||||
output = Manager().dict()
|
||||
|
||||
# Dans une première boucle, on crée les switches. Et on met
|
||||
# les processes en mode actif.
|
||||
for switch in switches:
|
||||
hp_switches[switch].flush_ports()
|
||||
processes[switch] = Process(target=fetch_all_ports, args=(switch, output), name=switch)
|
||||
processes[switch].start()
|
||||
|
||||
# On fait la jointure des processes dans une seconde
|
||||
# boucle, pour s'assurer que les processes ont bien
|
||||
# tous été lancés avant de commencer à les sonder.
|
||||
for switch in switches:
|
||||
processes[switch].join()
|
||||
|
||||
for switch in switches:
|
||||
if output[switch] is not None:
|
||||
for (iid, val) in output[switch]:
|
||||
if hp_switches[switch].ports.get(iid, None) is not None:
|
||||
hp_switches[switch].ports[iid].append_mac(val)
|
||||
else:
|
||||
print "Output for switch %s is None." % (switch,)
|
||||
|
||||
def trace_mac(mac, in_all_switches=False):
|
||||
"""Cherche une MAC. Si in_all_switches est à True, commence
|
||||
par instancier tous les switches, et à les peupler.
|
||||
|
||||
Cette méthode est assez agressive, il faut l'utiliser avec
|
||||
précaution."""
|
||||
if in_all_switches:
|
||||
populate_all_switches()
|
||||
|
||||
mac = format_mac(mac)
|
||||
|
||||
# On boucle sur les macs dans la factory
|
||||
__mac = MACFactory.get_mac(mac)
|
||||
if __mac is not None:
|
||||
# On boucle sur les parents (des ports) à la recherche
|
||||
# de ceux qui appartiennent au switch courant.
|
||||
__parents = []
|
||||
for parent in __mac.parents.itervalues():
|
||||
__parents.append(parent)
|
||||
|
||||
# Si on en a trouvé, on les retourne avec la mac.
|
||||
if __parents:
|
||||
return (__mac, __parents)
|
||||
|
||||
return None
|
Loading…
Add table
Add a link
Reference in a new issue