scripts/wifi/bornes.py
Antoine Durand-Gasselin fcdf94565f [wifi/bornes.py] cosmétique pour munin
darcs-hash:20100211123656-bd074-4520fb1b9ff2c436770bf1da9b9a4b54cfd6729d.gz
2010-02-11 13:36:56 +01:00

245 lines
7.8 KiB
Python
Executable file

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# uname_bornes.py
# ---------------
# Copyright : (c) 2009, Jeremie Dimino <jeremie@dimino.org>
# Licence : BSD3
"""Script qui fait un uname sur toute les bornes à la fois.
La sortie est la sortie de `uname -v` sur chaque borne."""
import sys, os, commands, re, time
from optparse import OptionParser
LOG = "/var/log/wifi/wifi.log"
DELTA = 60*60
def bornes():
"""Renvoie la liste des bornes
Moyen rapide, mais peut-être un peu crade pour récupérer la liste des bornes:
on regarde les machines présentes dans 138.231.148.1/24"""
names = []
for line in commands.getoutput("host -l wifi.crans.org sable.crans.org").splitlines()[5:]:
# Chaque ligne est de la forme:
# "truc.wifi.crans.org has address 138.231.148.42"
fields = line.split()
name = fields[0].split(".")[0]
ip = fields[3]
network = ip.rsplit(".", 1)[0]
# On ne prend que les machines du réseau 138.231.148.0/24, à part
# ragnarok:
if network == "138.231.148" and ip != "138.231.148.1":
names.append(name)
return names
def ssh_exec(host, cmd):
"""Execute une commande en ssh sur une machine et renvoie le résultat"""
(stdin, stdout, stderr) = os.popen3("ssh -T -x -o BatchMode=yes -o ConnectTimeout=5 -o StrictHostKeyChecking=no %(host)s %(cmd)s" % locals())
stdin.close()
stderr.close()
return stdout
def bornes_canal():
names = bornes()
outputs = {}
for name in names:
outputs[name] = ssh_exec(name+".wifi", 'iwlist wl0 channel')
count = 0
total = len(names)
while count < total:
try: os.wait()
except OSError: break
# On lit tout les résultats:
results = {}
for name, output in outputs.iteritems():
curoutput = output.read().strip()
if 'Current Channel' in curoutput:
results[name] = curoutput.split(':')[-1].strip()
else:
results[name] = None
output.close()
return results
def bornes_clients():
names = bornes()
outputs = {}
for name in names:
outputs[name] = ssh_exec(name+".wifi", 'brctl showmacs br-crans')
count = 0
total = len(names)
while count < total:
try: os.wait()
except OSError: break
# On lit tout les résultats:
results = {}
for name, output in outputs.iteritems():
lines = output.readlines()
if lines:
macs = map(lambda x: x.split(), lines)
results[name] = str(len([x for x in macs if x[0] == '2' and x[2] != 'yes']))
output.close()
return results
def bornes_uptime():
names = bornes()
outputs = {}
for name in names:
outputs[name] = ssh_exec(name+".wifi", 'cat /proc/uptime')
count = 0
total = len(names)
while count < total:
try: os.wait()
except OSError: break
# On lit tout les résultats:
results = {}
for name, output in outputs.iteritems():
uptime = output.read().strip()
if uptime:
results[name] = str(float(uptime.split()[1]) / (24*3600))
else:
results[name] = '0'
output.close()
return results
def munin(config, cmd=None, process=(lambda x: x), results=None, buckets=None, stack=None):
"""plugin munin"""
if 'autoconf' in sys.argv:
print 'yes'
sys.exit(0)
names = bornes()
if 'config' in sys.argv:
print config
print "graph_category wifi"
if buckets:
for i, (val, lbl) in enumerate(buckets.items()):
print "%s.label %s" % (lbl, val)
if stack:
if i == 0: print "%s.draw %s" % (lbl, stack)
else: print "%s.draw STACK" % lbl
else:
for i, borne in enumerate(names):
print "%s.label %s" % (borne, borne)
if stack:
if i == 0: print "%s.draw %s" % (borne, stack)
else: print "%s.draw STACK" % borne
sys.exit(0)
if not results:
res = results = {}
for name in names: res[name] = ssh_exec(name+".wifi", cmd)
for name in names: results[name] = res[name].read()
if buckets:
bins = {}
for (lbl, val) in buckets.iteritems(): bins[val] = 0
for name, res in results.iteritems():
try:
value = process(res).split('\n', 1)[0].strip()
if buckets: bins[buckets[value]] += 1
else: print '%s.value %s' % (name, value)
except: pass
if buckets:
for name, res in bins.iteritems():
print '%s.value %s' % (name, res)
def main():
parser = OptionParser(usage=usage)
parser.add_option('-v', '--uname', help=u"renvoie le uname -v",
action='store_const', const='uname -v', dest='cmd', default='uname -v')
parser.add_option('-u', '--uptime', help=u"renvoie l'uptime",
action='store_const', const='uptime', dest='cmd')
parser.add_option('-w', '--mac-wifi',
help=u"renvoie l'addresse MAC de l'access point",
action='store_const', dest='cmd',
const="iwconfig wl0 | sed -n 's/^.*00:/00:/p'")
parser.add_option('-c', '--custom', help=u'exécute une commande custom',
action='store', dest='cmd')
(options, args) = parser.parse_args()
names = bornes()
outputs = {}
for name in names:
outputs[name] = ssh_exec(name+".wifi", commands.mkarg(options.cmd))
# On attend que tous les fils qu'on a lancé terminent, avec une petite
# animation si la sortie est un terminal:
count = 0
total = len(names)
show_anim = sys.stderr.isatty()
message = "Réception des résultats: %d/%d"
if show_anim: sys.stderr.write(message % (count, total))
while count < total:
try: os.wait()
except OSError: break
count += 1
if show_anim: sys.stderr.write("\r" + message % (count, total))
if show_anim: sys.stderr.write("\n")
# On lit tout les résultats:
results = {}
for name, output in outputs.iteritems():
results[name] = output.read().strip()
output.close()
results = results.items()
results.sort(key=lambda x: x[0])
for name, result in results:
if not result:
print "%-15s failure" % (name + ":")
for name, result in results:
if result:
print "%-15s %s" % (name + ":", result)
if __name__ == "__main__":
usage = u"""usage: %prog [OPTION]
Récupère la liste des bornes et récupère le résultat d'une commande sur
toutes les bornes"""
prog = os.path.basename(sys.argv[0])
if len(prog.split('_', 1)) > 1:
plugin = prog.split('_', 1)[0]
if plugin == 'uptime':
config = """graph_title Uptime Bornes
graph_args --base 1000 --logarithmic
graph_vlabel uptime in days"""
def process(uptime):
if uptime: return str(float (uptime.split()[1]) / (24 * 3600))
else: return None
munin(config, cmd = 'cat /proc/uptime', process=process)
elif plugin == 'clients':
config = """graph_title Clients connectés
graph_args --base 1000 -l 0
graph_vlabel Clients connectés"""
munin(config, results=bornes_clients(), stack="AREA")
elif plugin == 'canal':
config = """graph_title Canaux utilisés
graph_args --base 1000 -l 0"""
buckets = {'1': 'un', '2': 'deux', '3': 'trois', '4': 'quatre',
'5': 'cinq', '6': 'six', '7': 'sept', '8': 'huit',
'9': 'neuf', '10': 'dix', '11': 'onze', '12': 'douze',
'13': 'treize', '14': 'quatorze', '0': 'echec' }
munin(config, results=bornes_canal(), buckets= buckets, stack="AREA")
else: raise NotImplementedError
else:
main()