chambres_vides: refactoring

This commit is contained in:
Daniel STAN 2014-11-07 00:16:49 +01:00
parent 871eb7d3c0
commit 7169e50fd2
4 changed files with 114 additions and 110 deletions

View file

@ -1,134 +1,138 @@
#!/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."""
""" 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>
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 toGeneralizedTimeFormat
conn = lc_ldap.shortcuts.lc_ldap_admin()
from lc_ldap.crans_utils import to_generalized_time_format as to_gtf
import mail as mail_module
import sys
#: envoyer un mail à chaque adhérent concerné
sendmails = False
if "--mail-all" in sys.argv:
sendmails = True
from email.header import Header
from config import demenagement_delai as delai, \
debut_periode_transitoire, periode_transitoire
#: Envoyer un mail à respbats
sendmail_respbats = True
if "--no-mail" in sys.argv:
sendmail_respbats = False
ERASE_DAY = { 'second': 0, 'minute': 0, 'microsecond': 0, 'hour': 0, }
DAY = datetime.timedelta(days=1)
FORMAT_LDAP = '%Y%m%d%H%M%S%z'
DEBUG = False
if "--debug" in sys.argv:
DEBUG = True
RESP = 'respbats@crans.org'
import os
import config
year = config.ann_scol
delai = config.demenagement_delai
FILTER = u'''(&
(aid=*)
(chbre=????)
(finAdhesion>=%(date)s)
(finConnexion>=%(date)s)
)'''
# On récupère ceux qui n'ont pas payé cette année
now = time.time()
if config.periode_transitoire:
bad_boys_e_s = conn.search(u'(&(aid=*)(chbre=????)(|(&(paiement=%d)(!(paiement=%d)))(finAdhesion<=%s)(finConnexion<=%s)))' % (year-1, year, toGeneralizedTimeFormat(now), toGeneralizedTimeFormat(now)))
else:
bad_boys_e_s = conn.search(u'(&(aid=*)(chbre=????)(|(paiement=%d)(finAdhesion>=%s)(finConnexion>=%s)))' % (year, toGeneralizedTimeFormat(now), toGeneralizedTimeFormat(now)))
now = datetime.datetime.now().replace(**ERASE_DAY)
to_print = []
to_error = []
for clandestin in bad_boys_e_s:
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 clandestin['historique'][::-1]:
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:
kickout_date = x.group(1)
exchambre = x.group(2)
return (l.get_datetime(), x.group(2))
raise IndexError('Adh jamais expulse')
machine_liste = clandestin.machines()
# On lui accorde un délai
kickout_date = time.mktime(time.strptime(kickout_date, "%d/%m/%Y %H:%M"))
delta = now - kickout_date
ttl = delai*86400 - delta
if ttl > 0:
if (sendmails and machine_liste != [] or DEBUG) and (ttl >= (delai - 1)*86400 or 0 < ttl <= 86400):
# On lui envoie un mail pour le prévenir
to = clandestin['mail'][0]
mail = mail_module.generate('demenagement', {"from" : "respbats@crans.org",
"chambre" : exchambre,
"jours" : int(ttl/86400) + 1,
"to" : to,
"prenom" : clandestin["prenom"][0],
"nom" : clandestin["nom"][0],
"lang_info":"English version below"}
).as_string()
if DEBUG:
print mail
mailer = os.popen("/usr/sbin/sendmail -t", "w")
mailer.write(mail + "\n.")
mailer.close()
def warn_or_delete(smtp, clandestin, fail, done):
"""Avertit l'adhérent ou supprime ses machines si nécessaire"""
date, exchambre = get_kickout(clandestin)
else:
for m in machine_liste:
try:
# 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
with conn.search(u'mid=%s' % m['mid'][0], mode='w')[0] as m2:
m2.delete(reason)
to_print.append( (clandestin['aid'][0], m['ipHostNumber'][0], m['mid'][0], m['host'][0]) )
for m in clandestin.machines(mode='rw'):
try:
with m:
m.delete(reason)
done.append(m)
except Exception as e:
to_error.append((clandestin['aid'][0], m['ipHostNumber'][0], m['mid'][0], m['host'][0], 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())
message = u""
if to_print != []:
# Il s'est passé quelque chose, donc on envoie un mail
# On regarde le plus grand hostname
hostnamemaxsize = max([len(str(i[3])) for i in to_print])
template = u"| %%4s | %%-15s | %%4s | %%-%ss |\n" % (hostnamemaxsize)
message += u"\nListe des machines supprimées pour chambre invalide depuis plus de %s jours :\n" % delai
tiret_line = u"+------+-----------------+------+-%s-+\n" % ("-" * hostnamemaxsize)
message += tiret_line
message += template % ("aid", " ip", "mid", (" " * (max((hostnamemaxsize-8)/2,0)) + "hostname"))
message += tiret_line
for aid, ip, mid, hostname in to_print:
message += template % (aid, ip, mid, hostname)
def format_entry(m):
"""Renvoie une ligne de tableau, pour une machine"""
return [
unicode(m['host'][0]),
unicode(' '.join(m.dn.split(',')[:2])),
]
message += tiret_line
message += u"\nScore de cette nuit : %s" % (len(to_print))
if to_error != []:
hostnamemaxsize = max([len(str(i[3])) for i in to_error])
errormaxsize = max([len(str(i[4])) for i in to_error])
template = u"| %%4s | %%-15s | %%4s | %%-%ss | %%-%ss |\n" % (hostnamemaxsize, errormaxsize)
message += u"\n"
tiret_line = u"+------+-----------------+------+-%s-+-%s-+\n" % ("-" * hostnamemaxsize, "-" * errormaxsize)
message += u"\nListe des machines dont la supression à échoué :\n"
message += tiret_line
message += template % ("aid", " ip", "mid", (" " * (max((hostnamemaxsize-8)/2,0)) + "hostname"), (" " * (max((errormaxsize-6)/2,0)) + "erreur"))
for aid, ip, mid, hostname, error in to_error:
message += template % (aid, ip, mid, hostname, error)
message += tiret_line
if to_print != [] or to_error != []:
headers = u"From: respbats@crans.org\nSubject: %s\n" % Header("Machines supprimées pour chambre invalide", "utf8").encode()
headers += u"Content-Type: text/plain; charset=UTF-8\n"
headers += u"X-Mailer: /usr/scripts/gestion/chambres_vides.py\n"
headers += u"To: respbats@crans.org\n"
mail = headers + "\n" + message
if sendmails:
mailer = os.popen("/usr/sbin/sendmail -t", "w")
mailer.write(mail.encode("utf-8") + "\n.")
mailer.close()
def spaces(x):
"""Ajoute des espaces en plus sur un tableau de tableau de strings"""
if type(x) == list:
return map(spaces, x)
else:
print mail
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())

View file

@ -1 +1 @@
{{to}}
"{{adh|name}}" <{{to}}>

View file

@ -1,4 +1,4 @@
Hi {{prenom}} {{nom}}!
Hi {{ adh|name }}!
A new member of Crans has declared to live in the room {{chambre}} you were
previously registered in. This means we do not have your residency information
@ -10,7 +10,7 @@ campus.
If you do not wish to keep your Crans Internet access, a simple message from
you is enough to delete all your computers from our database. This deletion
will automatically take place in {{jours}} day(s) if you do not answer.
will automatically take place in {{jours}} day{% if jours > 1 %}s{%endif%} if you do not answer.
If you do have a Crans account, you will keep an unlimited acces to it, as well
as all the associated services such as your email firstname.lastname@crans.org.

View file

@ -1,4 +1,4 @@
Bonjour {{prenom}} {{nom}},
Bonjour {{ adh|name }},
Un adhérent du Crans a déclaré résider dans la chambre {{chambre}},
que tu occupais précédemment. Cela signifie que nous ne disposons
@ -10,7 +10,7 @@ si tu as quitté le campus.
Si tu ne souhaites pas conserver ton accès Internet, un simple message de
ta part et nous supprimerons les machines que tu possèdes de notre base de
données. Cette suppression aura automatiquement lieu dans {{jours}} jour(s) en
données. Cette suppression aura automatiquement lieu dans {{jours}} jour{% if jours > 1%}s{%endif%} en
l'absence de réponse.
Si tu possèdes un compte Crans, tu conserves un accès à celui-ci sans limite de