
* Grâce à cela, populate_all_switches peut être restreint à une liste spécifique de switches pour éviter de forcément tout peupler.
130 lines
4.3 KiB
Python
130 lines
4.3 KiB
Python
#!/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(switches=None):
|
|
"""Remplit l'ensemble des switches avec les MACS qui sont
|
|
présentes sur leurs ports.
|
|
|
|
Peut également ne remplir qu'une liste spécifique si fournie
|
|
en argument."""
|
|
|
|
if switches == None:
|
|
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
|