scripts/gestion/chambres_vides.py
2014-11-26 16:16:53 +01:00

138 lines
4.3 KiB
Python
Executable file

#!/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
<daniel.stan@crans.org>
<legallic@crans.org>
<samir@crans.org>
"""
import sys
import os
import datetime
import time
import re
import affichage
import lc_ldap.shortcuts
from lc_ldap.crans_utils import to_generalized_time_format as to_gtf
import mail as mail_module
from config import demenagement_delai as delai, \
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
data = {
"from" : RESP,
"chambre" : exchambre,
"jours" : (date_suppr - now).days+1,
"to" : mail_addr,
"adh": clandestin,
"lang_info": "English version below",
}
mail = mail_module.generate('demenagement', data)
smtp.sendmail(RESP, [mail_addr], mail.as_string())
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 = to_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())