Dépendances Debian : python >= 2.5
"""
-URL_BASE = 'http://intranet.auf/cgi-bin/auf/'
+PROG_NAME = 'auf-referentiels'
+RUN_USER = 'auf-referentiels'
DIR_BASE = '/usr/share/auf-referentiels/'
+URL_BASE = 'http://intranet.auf/auf-referentiels/'
-__all__ = ( 'URL_BASE', 'DIR_BASE' )
+f = file('/etc/auf-referentiels.conf')
+lines = filter(lambda l: not l.startswith('#'), f.readlines())
+config = dict(map(lambda l: map(lambda s: s.strip(), l.split('=')), lines))
+
+URL_BASE = config.get('URL_BASE', URL_BASE).rstrip('/') + '/'
+
+__all__ = ( 'RUN_USER', 'DIR_BASE', 'URL_BASE' )
USAGE = """Usages (à lancer en tant que "root", par exemple via "sudo") :
- update-auf-referentiels -a <ref> - copie un nouveau référentiel
- update-auf-referentiels -d <ref> - supprime un référentiel
- update-auf-referentiels -u - met à jour les référentiels
- update-auf-referentiels -l - liste les référentiels copiés
- update-auf-referentiels -L - liste les référentiels disponibles
+ auf-referentiels [-f] -a <ref> - copie un nouveau référentiel
+ auf-referentiels -d <ref> - supprime un référentiel
+ auf-referentiels [-f] -u - met à jour les référentiels
+ auf-referentiels -l - liste les référentiels copiés
+ auf-referentiels -L - liste les référentiels disponibles
L'option -f permet de forcer le rechargement à travers un proxy/cache.
"""
from sys import argv, exit, stderr
from getopt import getopt, GetoptError
-from os import listdir, utime, unlink
+from pwd import getpwnam
+from os import getuid, setgid, setuid, listdir, utime, unlink
from os.path import join, exists, getmtime
from time import gmtime, strftime
from calendar import timegm
-from urllib2 import Request, urlopen, HTTPError
+from urllib2 import Request, urlopen, HTTPError, URLError
from cStringIO import StringIO
from gzip import GzipFile
from simplejson import loads
else:
# fichier vide à date très ancienne pour déclencher la synchro
try:
+ switch_user()
file(filename, 'a').close()
- except IOError:
- raise RuntimeError, u"Écriture refusée, réessayez avec 'sudo' !"
+ except IOError, msg:
+ raise RuntimeError, u"Création refusée : %s" % msg
utime(filename, (0, 0))
url = URL_BASE + referentiel
req = Request(url, None, headers)
except HTTPError, e:
if e.code == 304:
return
- raise RuntimeError, u"Impossible d'ouvrir l'URL '%s'." % url
+ raise RuntimeError, \
+ u"L'URL suivante renvoie un code d'erreur %s :\n %s" \
+ % (e.code, url)
+ except URLError:
+ raise RuntimeError, u"L'URL suivante est inaccessible :\n %s" % url
i = u.info()
if referentiel.endswith('.json') and i.type != 'application/json':
u.close()
raise RuntimeError, u"Les données ne sont pas au format JSON."
# si on est arrivé jusqu'ici c'est que tout va bien... on enregistre !
try:
+ switch_user()
f = file(filename, 'wb')
- except IOError:
- raise RuntimeError, u"Écriture refusée, réessayez avec 'sudo' !"
+ except IOError, msg:
+ raise RuntimeError, u"Écriture refusée : %s" % msg
f.write(data)
f.close()
# on fixe la date donnée par le serveur, le cas échéant
mtime = timegm(mtime)
utime(filename, (mtime, mtime))
-def referentiels_list():
- referentiels = []
- for referentiel in listdir(DIR_BASE):
- if referentiel.endswith('.json'):
- referentiels.append(referentiel)
- return referentiels
-
def add_referentiel(referentiel, force=False):
- if referentiel in referentiels_list():
+ if referentiel in listdir(DIR_BASE):
raise RuntimeError, \
u"Référentiel '%s' déjà ajouté auparavant." % referentiel
update_referentiel(referentiel, force)
def delete_referentiel(referentiel):
- if not referentiel in referentiels_list():
+ if not referentiel in listdir(DIR_BASE):
raise RuntimeError, u"Référentiel '%s' absent." % referentiel
- unlink(join(DIR_BASE, referentiel))
+ try:
+ switch_user()
+ unlink(join(DIR_BASE, referentiel))
+ except IOError, msg:
+ raise RuntimeError, u"Suppression refusée : %s" % msg
def update_referentiels(force=False):
- for referentiel in referentiels_list():
- update_referentiel(referentiel, force)
+ error_messages = []
+ for referentiel in listdir(DIR_BASE):
+ try:
+ update_referentiel(referentiel, force)
+ except Exception, msg:
+ error_messages.append(msg.__str__())
+ if error_messages:
+ raise RuntimeError, u'\n'.join(error_messages)
def list_referentiels():
- for referentiel in referentiels_list():
+ for referentiel in listdir(DIR_BASE):
print referentiel
def list_referentiels_available():
for referentiel in sorted(referentiels):
print "%-16s : %s" % (referentiel, referentiels[referentiel])
+_user_switched = False
+def switch_user(username=RUN_USER):
+ global _user_switched
+ if _user_switched:
+ return
+ try:
+ pw = getpwnam(username)
+ except KeyError:
+ raise RuntimeError, u"L'utilisateur '%s' n'existe pas." % username
+ try:
+ setgid(pw.pw_gid)
+ setuid(pw.pw_uid)
+ except OSError:
+ raise RuntimeError, \
+ u"Impossible de basculer vers l'utilisateur '%s'.\n" \
+ u"Réessayez avec 'sudo' !" % username
+ _user_switched = True
+
if __name__ == '__main__':
+ # interdiction formelle de tourner sous 'root'
+ if getuid() == 0:
+ switch_user()
+
try:
opts, args = getopt(argv[1:], 'hfa:d:ulL', ['help', 'force',
'add=', 'delete=', 'update', 'list', 'list-available'])
elif opt in ('-L', '--list-available'):
list_referentiels_available()
except RuntimeError, msg:
- print >>stderr, u'ATTENTION : %s' % msg
+ print >>stderr, u'%s' % msg
if not opts:
print USAGE
--- /dev/null
+.TH AUF-REFERENTIELS 8 "25 juin 2009"
+.\"
+.\" Some roff macros, for reference:
+.\" .nh disable hyphenation
+.\" .hy enable hyphenation
+.\" .ad l left justify
+.\" .ad b justify to both left and right margins
+.\" .nf disable filling
+.\" .fi enable filling
+.\" .br insert line break
+.\" .sp <n> insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+auf-referentiels \- outil de copie et mise à jour des réferentiels AuF
+.SH SYNOPSIS
+\fBauf-referentiels\fP [\fB-f\fP] \fB-a\fP \fIreferentiel\fP
+.br
+\fBauf-referentiels\fP \fB-d\fP \fIreferentiel\fP
+.br
+\fBauf-referentiels\fP [\fB-f\fP] \fB-u\fP
+.br
+\fBauf-referentiels\fP \fB-h\fP | \fB-l\fP | \fB-L\fP
+.SH DESCRIPTION
+Cette page de manuel documente brièvement la commande \fBauf-referentiels\fP.
+.PP
+.SH OPTIONS
+Ce programme suit la syntaxe habituelle d'une ligne de commande GNU,
+avec des options longues commençant par deux tirets (`-').
+.TP
+.B \-h, \-\-help
+Montre un résumé des options.
+.TP
+.B \-a, \-\-add
+Copie un nouveau référentiel. Il sera ensuite mis à jour, soit automatiquement à 7h et 13h (en heure locale), soit manuellement avec l'option \fB-u\fP. L'option \fB-f\fP permet de forcer le chargement à travers un proxy/cache.
+.TP
+.B \-d, \-\-delete
+Supprime un référentiel.
+.TP
+.B \-u, \-\-update
+Met à jour les référentiels immédiatement. L'option \fB-f\fP permet de forcer le chargement à travers un proxy/cache.
+.TP
+.B \-l, \-\-list
+Liste les référentiel copiés.
+.TP
+.B \-L, \-\-list-available
+Liste les référentiel disponibles. Cette liste est obtenue depuis un référentiel spécial nommé \fBreferentiels.json\fP.
+.SH AUTEUR
+L'outil auf-referentiels a été écrit par Progfou <jean-christophe.andre@auf.org>.
+.PP
+Cette page de manuel a été écrite par Progfou <jean-christophe.andre@auf.org>,
+pour le projet Debian (mais peut être utilisé par d'autres).