#!/bin/bash /usr/scripts/python.sh # -*- encoding: utf-8 -*- """ Pour détecter les gens en chambre invalide, les prévenir, et supprimer leurs machines en l'absence de réponse. Récupérer des IPs, c'est cool. Codé par b2moo, commenté par 20-100, cr{itiqu|on}é par Nit """ import sys import os import datetime import time import re import affichage import lc_ldap.shortcuts import mail as mail_module from config import demenagement_delai as delai, \ gtf_debut_periode_transitoire, periode_transitoire ERASE_DAY = { 'second': 0, 'minute': 0, 'microsecond': 0, 'hour': 0, } DAY = datetime.timedelta(days=1) FORMAT_LDAP = '%Y%m%d%H%M%S%z' RESP = 'respbats@crans.org' FILTER = u'''(& (aid=*) (chbre=????) (finAdhesion>=%(date)s) (finConnexion>=%(date)s) )''' # On récupère ceux qui n'ont pas payé cette année now = datetime.datetime.now().replace(**ERASE_DAY) def get_kickout(adh): """Renvoie la date et la chambre de la dernière expulsion""" # On cherche la dernière fois qu'il s'est retrouvé en chambre ???? for l in adh['historique'][::-1]: # On récupère la date du dernier changement de chambre # (l'historique est enregistré par ordre chronologique) x = re.match("(.*),.* : chbre \((.*) -> \?\?\?\?\)", str(l)) if x <> None: return (l.get_datetime(), x.group(2)) raise IndexError('Adh jamais expulse') def warn_or_delete(smtp, clandestin, fail, done): """Avertit l'adhérent ou supprime ses machines si nécessaire""" date, exchambre = get_kickout(clandestin) # Date de suppression prévue date_suppr = date + delai*DAY if date_suppr < now: # A expiré reason = u'Adhérent sans chambre valide depuis %d jours' % delai for m in clandestin.machines(mode='rw'): try: with m: m.delete(reason) done.append(m) except Exception as e: fail.append((m, e)) elif date_suppr < now + DAY or now - date < DAY: # Expire dans un jour ou vient tout juste de se faire virer mail_addr = clandestin.get_mail() if not clandestin.machines() or not mail_addr: return # Si pas de machine, on s'en fout. Si pas de mail, inutile try: data = { 'dn': clandestin.dn.split(',')[0], 'when': now.strftime('%Y/%M/%D %H:%m:%S:%s'), 'chbre' : exchambre, } chbre_url = mail_module.validation_url('demenagement', data, True) chbre_url_error = u"" except Exception as error: chbre_url_error = u"[[erreur de génération: %r]]" % error chbre_url = u"" data = { "from" : RESP, "chambre" : exchambre, "jours" : (date_suppr - now).days+1, "to" : mail_addr, "adh": clandestin, "chbre_url" : chbre_url, "chbre_url_error" : chbre_url_error, "lang_info": "English version below", } smtp.send_template('demenagement', data) def format_entry(m): """Renvoie une ligne de tableau, pour une machine""" return [ unicode(m['host'][0]), unicode(' '.join(m.dn.split(',')[:2])), ] def spaces(x): """Ajoute des espaces en plus sur un tableau de tableau de strings""" if type(x) == list: return map(spaces, x) else: return u' ' + unicode(x) + u' ' if __name__ == '__main__': conn = lc_ldap.shortcuts.lc_ldap_admin() if periode_transitoire: date = gtf_debut_periode_transitoire else: date = now.strftime(FORMAT_LDAP) + 'Z' bad_boys_e_s = conn.search(FILTER % {'date': date}) fail = [] done = [] with mail_module.ServerConnection() as smtp: for clandestin in bad_boys_e_s: warn_or_delete(smtp, clandestin, fail, done) if fail or done: done = spaces([format_entry(m) for m in done]) fail = spaces([format_entry(m) + [e] for (m,e) in fail]) data = { 'from': RESP, 'to': RESP, 'delai': delai, 'fail': fail, 'done': done, 'done_tab': affichage.tableau( done, titre=[u'Hôte', u'Référence'], alignement=['d', 'd'], ), 'fail_tab': affichage.tableau( fail, titre=[u'Hôte', u'Référence', u'Erreurs'], alignement=['d', 'd', 'd'], ), } with mail_module.ServerConnection() as smtp: mail = mail_module.generate('demenagement_stats', data) smtp.sendmail(RESP, [RESP], mail.as_string())