
* échappement correct des commandes * possibilité d'utiliser des areas darcs-hash:20091018233758-bd074-8601fa332e20a74b01df218afa6283d50673c4d3.gz
236 lines
7.4 KiB
Python
Executable file
236 lines
7.4 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").splitlines():
|
|
# 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] = '0'
|
|
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():
|
|
macs = map(lambda x: x.split(), output.readlines())
|
|
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
|
|
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():
|
|
value = process(res).split('\n', 1)[0].strip()
|
|
if buckets: bins[buckets[value]] += 1
|
|
else: print '%s.value %s' % (name, value)
|
|
|
|
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('-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 -l 0
|
|
graph_vlabel uptime in days"""
|
|
def process(uptime):
|
|
if uptime: return str(float (uptime.split()[1]) / (24 * 3600))
|
|
else: return '0'
|
|
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)
|
|
else: raise NotImplementedError
|
|
|
|
else:
|
|
main()
|