#!/usr/bin/env python # -*- coding: utf-8 -*- # # uname_bornes.py # --------------- # Copyright : (c) 2009, Jeremie Dimino # 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 from optparse import OptionParser 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 %(host)s exec %(cmd)s" % locals()) stdin.close() stderr.close() return stdout def munin(config, cmd, process=(lambda x: x)): """plugin munin""" if 'autoconf' in sys.argv: print 'yes' sys.exit(0) names = bornes() if 'config' in sys.argv: print config for borne in names: print "%s.label %s"% (borne, borne) sys.exit(0) outputs = {} for name in names: outputs[name] = ssh_exec(name+".wifi", cmd) for name, res in outputs.iteritems(): value = process(res.read()).split('\n', 1)[0].strip() print '%s.value %s' % (name, value) 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') (options, args) = parser.parse_args() names = bornes() outputs = {} for name in names: outputs[name] = ssh_exec(name+".wifi", 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""" if len(sys.argv[0].split('_', 1)) > 1: plugin = sys.argv[0].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, 'cat /proc/uptime', process=process) else: raise NotImplementedError else: main()