From 27fbf3f5c9a235aa6907f799a6ee07f443ad24b8 Mon Sep 17 00:00:00 2001 From: Daniel STAN Date: Tue, 3 Jun 2014 17:39:38 +0200 Subject: [PATCH] =?UTF-8?q?whodal:=20c=C3=A2bleurs=20au=20d'Alembert=20=3F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gestion/tools/whosthere.py | 196 +++++++++++++++++++++++++++++++++++++ respbats/whodal | 8 ++ 2 files changed, 204 insertions(+) create mode 100755 gestion/tools/whosthere.py create mode 100755 respbats/whodal diff --git a/gestion/tools/whosthere.py b/gestion/tools/whosthere.py new file mode 100755 index 00000000..247c91cb --- /dev/null +++ b/gestion/tools/whosthere.py @@ -0,0 +1,196 @@ +#!/bin/bash /usr/scripts/python.sh +# -*- coding: utf-8 -*- + +'''Ce script permet de savoir s'il y a du monde dans un local donné, +à des fins de perms, et cie, filtre par membres actifs.''' + +import sys +from socket import gethostname +import collections +import os +import xml.dom.minidom + +from gestion.ldap_crans import crans_ldap +from gestion.hptools import hpswitch, ConversationError +from gestion.affich_tools import coul, cprint +from gestion.whos import aff + +# Constantes pour munin. +# L'ordre est important : il détermine comment sont empilés les valeurs +# dans le graphe (mode STACK). Les premières valeurs ont donc intérêts +# à avoir le moins de variations (empilées les premières) +STATE_DESCR = collections.OrderedDict([ + ('unknown_macs', ('machines inconnues de la base', 0xff0000)), + ('crans', ('machines du crans', 0x0000ff)), + ('ma', ('machines de membres actifs', 0x00ff00)), + ('adh', ('autres machines appartenant aux autres adhérents', 0xe5ff00)), +]) + +CLUB_CRANS = 35 +CLUB_BDE = 1 + +def _mucode(u): + """Sad but true: munin ne fait pas d'utf-8 …""" + return u.encode('iso-8859-15', errors='ignore') + +class WhosThere(object): + """: Nom du local, tel qu'il apparaît sur munin, et cie""" + name = u"Unamed Local" + + """: Liste de macs et hostsname qui doivent être ignorées""" + expected = [] + + _ignore_inactive = True + _ignore_wifi_only = False + def set_ignore_inactive(self, ignore, wifi_only=None): + """Définit si l'ajout d'une mac a effectivement lieu pour les + mac à ajouter si elles n'appartiennent pas à un membre actif""" + self._ignore_inactive = ignore + if wifi_only is not None: + self._ignore_wifi_only = wifi_only + + def populate_from_mac(self, mac): + """Rempli à partir de la mac""" + fm = self.db.search("mac=%s" % mac) + res = self._res + if mac in self.expected: + return + if fm['machine']: + m = fm['machine'][0] + if m.nom() in self.expected: + return + proprio = m.proprietaire() + if fm['machineCrans'] or fm["borneWifi"] or (proprio.idn == 'cid' and int(proprio.id()) == CLUB_CRANS): + key = 'crans' + elif hasattr(proprio, 'droits') and proprio.droits(): + key = 'ma' + elif proprio.idn == "cid" and int(proprio.id()) == CLUB_BDE: + key = 'bde' + else: + if self._ignore_inactive: + if fm['machineWifi'] or self._ignore_wifi_only: + return + key = 'adh' + res[key].append(m) + else: + res['unknown_macs'].append(mac) + + def populate_from_switch(self, host, port): + """Rempli les macs à partir de la prise d'un switch""" + sw = hpswitch(host) + try: + macs = sw.show_prise_mac(port) + except ConversationError: + cprint("Impossible de communiquer avec le switch !", 'rouge') + for mac in macs: + self.populate_from_mac(mac) + + def populate_from_ap(self, host): + """Rempli les macs à partir de la prise d'un switch""" + path = os.path.join('/usr/scripts/var/wifi_xml/', host) + '.xml' + with open(path, 'r') as f: + doc = xml.dom.minidom.parse(f) + + for mac in doc.getElementsByTagName('mac'): + self.populate_from_mac(mac.firstChild.nodeValue) + + def do_scan(self): + """Fonction à surcharger pour remplir la liste de personnes présentes. + La fonction pourra faire appel à populate_from_*""" + pass # à surcharger + + _res = None + def query(self): + if self._res: + return self._res + self._res = { + 'ma': [], + 'crans': [], + 'adh': [], + 'bde': [], + 'unknown_macs': [], + 'ttyfound': 0, + } + self.db = crans_ldap() + self.do_scan() + return self._res + + def summary(self): + u"""Réalise un joli aperçu de l'état donné en paramètre.""" + current = self.query() + if current['ma']: + cprint('---=== Machines des membres actifs ===---', 'bleu') + aff(current['ma']) + cprint("---=== Il y a du monde ===---", 'vert') + else: + cprint("---=== Il semble n'y avoir personne ... ===---", 'rouge') + for mac in current['unknown_macs']: + cprint("Machine inconnue: %s" % mac, 'rouge') + if current['crans']: + cprint("---=== Machines Cr@ns ===---", 'bleu') + aff(current['crans']) + if current['bde']: + cprint("---=== Machines du BDE ===---", 'bleu') + aff(current['bde']) + if current['adh']: + cprint("---=== Machines d'adhérents ===---", 'bleu') + aff(current['adh']) + + def munin_config(self): + """Donne la configuration du graphe munin""" + munin_title = u"Fréquentation du local %s" % self.name + print """graph_title %s +graph_vlabel N +graph_category environnement""" % _mucode(munin_title) + + for (name, (descr, color)) in STATE_DESCR.iteritems(): + print """%(name)s.label %(descr)s +%(name)s.draw AREASTACK +%(name)s.colour %(color)06X""" % {'name': name, 'descr': _mucode(descr), 'color': color} + # Dans le doute, n'affichons pas les adhérents + print "adh.graph no" + + def munin_values(self): + res = self.query() + for name in STATE_DESCR.iterkeys(): + print """%(name)s.value %(value)d\n""" % \ + {'name': name, 'value': len(res[name]) } + +class WhoKfet(WhosThere): + name = u"Kfet" + + def do_scan(self): + self.populate_from_switch('backbone.adm.crans.org', 21) + +class Who2B(WhosThere): + name = u"2B" + + expected = ['00:07:cb:b1:99:4e'] # Freebox + + def do_scan(self): + # Tous les gens au 2B sont supposés actifs (local technique quoi) + # mais on cache quand-même les personnes connectées en WiFi + self.set_ignore_inactive(True, wifi_only=True) + self.populate_from_switch('backbone.adm.crans.org', 33) + +class WhoDalembert(WhosThere): + name = u"D'alembert (PR)" + + expected = ['danae.wifi.crans.org'] + + def do_scan(self): + # Tous les gens au 2B sont supposés actifs (local technique quoi) + self.populate_from_ap('danae') + +if __name__ == '__main__': + where = { + 'dalembert': WhoDalembert, + '2b': Who2B, + 'kfet': WhoKfet, + } + for what in sys.argv[1:]: + try: + name = where[what.lower()] + except KeyError: + continue + name().summary() diff --git a/respbats/whodal b/respbats/whodal new file mode 100755 index 00000000..0ca1a602 --- /dev/null +++ b/respbats/whodal @@ -0,0 +1,8 @@ +#!/bin/bash + +if [ `hostname` != "zamok" ]; then + echo "Merci d'executer ce script sur zamok." + exit 1 +fi + +sudo -u respbats /usr/scripts/gestion/tools/whosthere.py dalembert