+++ /dev/null
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-"""Copie et mise à jour des référentiels AuF.
-
-Copyright ©2009 Agence universitaire de la Francophonie
-Licence : GPL version 3
-Auteur : Progfou <jean-christophe.andre@auf.org>
-
-Dépendances Debian : python >= 2.5, python-simplejson
-"""
-
-PROG_NAME = 'auf-referentiels'
-RUN_USER = 'auf-referentiels'
-DIR_BASE = '/usr/share/auf-referentiels/'
-URL_BASE = 'http://intranet.auf/auf-referentiels/'
-
-f = file('/etc/auf-referentiels/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") :
- 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
- auf-referentiels [-f] -A - copie tous les référentiels disponibles
-
-L'option -f permet de forcer le rechargement à travers un proxy/cache.
-"""
-
-TIME_FORMAT = '%a, %d %b %Y %H:%M:%S GMT'
-
-from sys import argv, exit, stderr
-from getopt import getopt, GetoptError
-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, URLError
-from cStringIO import StringIO
-from gzip import GzipFile
-from simplejson import loads
-
-def update_referentiel(referentiel, force=False):
- headers = {}
- headers['Accept-Encoding'] = 'x-gzip'
- if force:
- headers['Pragma'] = 'no-cache'
- filename = join(DIR_BASE, referentiel)
- if exists(filename):
- # n'effectuer le chargement qu'en cas de nouvelle version
- mtime = gmtime(getmtime(filename))
- headers['If-Modified-Since'] = strftime(TIME_FORMAT, mtime)
- else:
- # fichier vide à date très ancienne pour déclencher la synchro
- try:
- switch_user()
- file(filename, 'a').close()
- except IOError, msg:
- raise RuntimeError, \
- u"La création du référentiel a été refusée : %s" % msg
- utime(filename, (0, 0))
- url = URL_BASE + referentiel
- req = Request(url, None, headers)
- try:
- u = urlopen(req)
- except HTTPError, e:
- if e.code == 304:
- return
- 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"Le type des données chargées n'est pas JSON mais '%s'." % i.type
- data = u.read()
- if i.get('content-encoding') == 'x-gzip':
- data = GzipFile('', 'r', 0, StringIO(data)).read()
- u.close()
- if referentiel.endswith('.json'):
- try:
- loads(data, encoding='utf-8')
- except ValueError:
- 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, msg:
- raise RuntimeError, \
- u"L'écriture du référentiel a été refusée : %s" % msg
- f.write(data)
- f.close()
- # on fixe la date donnée par le serveur, le cas échéant
- mtime = i.getdate('last-modified')
- if mtime:
- mtime = timegm(mtime)
- utime(filename, (mtime, mtime))
-
-def add_referentiel(referentiel, force=False):
- if referentiel in listdir(DIR_BASE):
- raise RuntimeError, \
- u"Le référentiel '%s' avait déjà été ajouté." % referentiel
- update_referentiel(referentiel, force)
-
-def delete_referentiel(referentiel):
- if not referentiel in listdir(DIR_BASE):
- raise RuntimeError, u"Le référentiel '%s' est absent." % referentiel
- try:
- switch_user()
- unlink(join(DIR_BASE, referentiel))
- except IOError, msg:
- raise RuntimeError, \
- u"La suppression du référentiel '%s' a été refusée :\n %s" \
- % (referentiel, msg)
-
-def update_referentiels(force=False):
- 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 listdir(DIR_BASE):
- print referentiel
-
-def get_referentiels_available(force=False):
- referentiel = 'referentiels.json'
- filename = join(DIR_BASE, referentiel)
- if not exists(filename):
- update_referentiel(referentiel, force)
- try:
- f = open(filename, 'rb')
- except IOError:
- raise RuntimeError, u"La liste des référentiels est indisponible."
- try:
- referentiels = loads(f.read(), encoding='utf-8')
- except ValueError:
- raise RuntimeError, \
- u"La liste des référentiels n'est pas au format JSON.\n" \
- u"Essayez les options -f et -u pour la mettre à jour."
- f.close()
- return referentiels
-
-def list_referentiels_available(force=False):
- referentiels = get_referentiels_available(force)
- for referentiel in sorted(referentiels):
- print "%-16s : %s" % (referentiel, referentiels[referentiel])
-
-def add_referentiels_available(force=False):
- referentiels = get_referentiels_available(force)
- referentiels = set(referentiels) - set(listdir(DIR_BASE))
- for referentiel in referentiels:
- update_referentiel(referentiel, force)
-
-_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:ulLA', ['help', 'force',
- 'add=', 'delete=', 'update', 'list',
- 'list-available', 'add-available'])
- except GetoptError:
- print USAGE
- exit(1)
-
- force = False
- for opt, arg in opts:
- if opt in ('-h', '--help'):
- print USAGE
- exit(0)
- elif opt in ('-f', '--force'):
- force = True
- else:
- try:
- if opt in ('-a', '--add'):
- add_referentiel(arg, force=force)
- elif opt in ('-d', '--delete'):
- delete_referentiel(arg)
- elif opt in ('-u', '--update'):
- update_referentiels(force=force)
- elif opt in ('-l', '--list'):
- list_referentiels()
- elif opt in ('-L', '--list-available'):
- list_referentiels_available(force=force)
- elif opt in ('-A', '--add-available'):
- add_referentiels_available(force=force)
- except RuntimeError, msg:
- print >>stderr, u'%s' % msg
-
- if not opts:
- print USAGE
- exit(0)
-
+++ /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-h\fP | \fB-l\fP
-.br
-\fBauf-referentiels\fP [\fB-f\fP] \fB-u\fP | \fB-L\fP | \fB-A\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 \-L, \-\-list-available
-Liste les référentiels disponibles. Cette liste est obtenue depuis un référentiel spécial nommé \fBreferentiels.json\fP. L'option \fB-f\fP permet de forcer le chargement à travers un proxy/cache.
-.TP
-.B \-A, \-\-add-available
-Copie tous les référentiels disponibles. Il seront 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 \-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 \-l, \-\-list
-Liste les référentiel copiés.
-.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 \-d, \-\-delete
-Supprime un référentiel.
-.SH FILES
-.TP
-.B /etc/auf-referentiels/auf-referentiels.conf
-Fichier de configuration de cet outil.
-.br
-On y trouvera en particulier l'option suivante :
-.TP
-.B URL_BASE
-URL de base pour la copie des référentiels. Par défaut cette URL est positionnée sur \fBhttp://intranet.auf/auf-referentiels\fP.
-.SH AUTHOR
-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).