--- /dev/null
+MANIFEST.in
+Makefile
+README
+apache.conf
+auf-refer
+auf-refer.conf
+aufrefer.py
+setup.py
+debian/auf-refer.8
+debian/changelog
+debian/compat
+debian/control
+debian/copyright
+debian/cron.d
+debian/dirs
+debian/lintian-overrides
+debian/manpages
+debian/postinst
+debian/postrm
+debian/pycompat
+debian/pyversions
+debian/rules
--- /dev/null
+include *.txt
+recursive-include examples *.txt *.py
+prune examples/sample?/build
+include auf-refer *.conf README
+include Makefile MANIFEST.in
+recursive-include debian *
all: build
build:
+ sed -i "/ version=/s/='[^']*'/='$(VERSION)'/" setup.py
install:
- install -m 0755 -d $(DESTDIR)/usr/sbin
- install -m 0755 auf-refer $(DESTDIR)/usr/sbin/
- install -m 0755 -d $(DESTDIR)/etc/auf-refer
- install -m 0644 *.conf $(DESTDIR)/etc/auf-refer/
- install -m 0755 -d $(DESTDIR)/var/lib/auf-refer
clean:
-#!/usr/bin/env python
+#!/usr/bin/python
# -*- coding: utf-8 -*-
-"""Copie et mise à jour des référentiels AuF.
+"""Outil de copie et mise à jour des référentiels AuF.
Copyright ©2009 Agence universitaire de la Francophonie
Licence : GPL version 3
Dépendances Debian : python >= 2.5, python-simplejson
"""
-PROG_NAME = 'auf-refer'
RUN_USER = 'auf-refer'
-DIR_BASE = '/var/lib/auf-refer/'
-URL_BASE = 'http://intranet.auf/auf-refer/'
-f = file('/etc/auf-refer/auf-refer.conf')
-lines = filter(lambda l: not l.startswith('#'), f.readlines())
-config = dict(map(lambda l: map(lambda s: s.strip(), l.split('=')), lines))
+__all__ = ( 'RUN_USER' )
-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") :
+USAGE = """Usages (nécessite parfois "root", par exemple via "sudo") :
auf-refer [-f] -a <ref> - copie un nouveau référentiel
- auf-refer -d <ref> - supprime un référentiel
+ auf-refer -r <ref> - supprime un référentiel
auf-refer [-f] -u - met à jour les référentiels
auf-refer -l - liste les référentiels copiés
- auf-refer -L - liste les référentiels disponibles
+ auf-refer [-f] -L - liste les référentiels disponibles
auf-refer [-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(unicode(msg))
- 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 = 'auf-refer.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
+from os import getuid, setgid, setuid
+import aufrefer
if __name__ == '__main__':
# interdiction formelle de tourner sous 'root'
if getuid() == 0:
- switch_user()
+ try:
+ pw = getpwnam(RUN_USER)
+ except KeyError:
+ raise RuntimeError, u"L'utilisateur '%s' n'existe pas." % RUN_USER
+ 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' !" % RUN_USER
try:
- opts, args = getopt(argv[1:], 'hfa:d:ulLA', ['help', 'force',
- 'add=', 'delete=', 'update', 'list',
+ opts, args = getopt(argv[1:], 'hfa:r:ulLA', ['help', 'force',
+ 'add=', 'remove=', 'update', 'list',
'list-available', 'add-available'])
except GetoptError:
print USAGE
else:
try:
if opt in ('-a', '--add'):
- add_referentiel(arg, force=force)
- elif opt in ('-d', '--delete'):
- delete_referentiel(arg)
+ aufrefer.add(arg, force=force)
+ elif opt in ('-r', '--remove'):
+ aufrefer.remove(arg)
elif opt in ('-u', '--update'):
- update_referentiels(force=force)
+ aufrefer.update(force=force)
elif opt in ('-l', '--list'):
- list_referentiels()
+ for referentiel in aufrefer.list():
+ print referentiel
elif opt in ('-L', '--list-available'):
- list_referentiels_available(force=force)
+ list = aufrefer.list_available(force=force)
+ for referentiel in sorted(list):
+ print "%-16s : %s" % (referentiel, list[referentiel])
elif opt in ('-A', '--add-available'):
- add_referentiels_available(force=force)
+ aufrefer.add_available(force=force)
except RuntimeError, msg:
print >>stderr, u'%s' % msg
+DIR_BASE=/var/lib/auf-refer
URL_BASE=http://intranet.auf/auf-refer
+AVAILABLE_LIST=auf-refer.json
--- /dev/null
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""Librairie de copie et mise à jour des référentiels AuF.
+
+Copyright ©2009 Agence universitaire de la Francophonie
+Licence : LGPL version 3
+Auteur : Progfou <jean-christophe.andre@auf.org>
+
+Dépendances Debian : python >= 2.5, python-simplejson
+"""
+
+CONFIG_FILE = '/etc/auf-refer/auf-refer.conf'
+
+DIR_BASE = '/var/lib/auf-refer'
+URL_BASE = 'http://intranet.auf/auf-refer'
+AVAILABLE_LIST = 'auf-refer.json'
+
+lines = filter(lambda l: not l.startswith('#'), file(CONFIG_FILE))
+config = dict(map(lambda l: map(lambda s: s.strip(), l.split('=')), lines))
+
+DIR_BASE = config.get('DIR_BASE', DIR_BASE).rstrip('/')
+URL_BASE = config.get('URL_BASE', URL_BASE).rstrip('/')
+AVAILABLE_LIST = config.get('AVAILABLE_LIST', AVAILABLE_LIST)
+
+__all__ = ( 'DIR_BASE', 'URL_BASE', 'AVAILABLE_LIST' )
+
+TIME_FORMAT = '%a, %d %b %Y %H:%M:%S GMT'
+
+from os import 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:
+ file(filename, 'a').close()
+ except IOError, msg:
+ raise RuntimeError, \
+ u"La création du référentiel '%s' a été refusée :\n %s" \
+ % (referentiel, 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'.\n" \
+ u"URL concernée : %s" % (i.type, url)
+ 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.\n" \
+ u"URL concernée : %s" % url
+ # si on est arrivé jusqu'ici c'est que tout va bien... on enregistre !
+ try:
+ f = file(filename, 'wb')
+ except IOError, msg:
+ raise RuntimeError, \
+ u"L'écriture du référentiel '%s' a été refusée :\n %s" \
+ % (referentiel, 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, 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 remove(referentiel):
+ if not referentiel in listdir(DIR_BASE):
+ raise RuntimeError, u"Le référentiel '%s' est absent." % referentiel
+ try:
+ unlink(join(DIR_BASE, referentiel))
+ except (IOError, OSError), msg:
+ raise RuntimeError, \
+ u"La suppression du référentiel '%s' a été refusée :\n %s" \
+ % (referentiel, msg)
+
+def update(referentiel=False, force=False):
+ if referentiel:
+ update_referentiel(referentiel, force)
+ return
+ error_messages = []
+ for referentiel in listdir(DIR_BASE):
+ try:
+ update_referentiel(referentiel, force)
+ except Exception, msg:
+ error_messages.append(unicode(msg))
+ if error_messages:
+ raise RuntimeError, u'\n'.join(error_messages)
+
+def list():
+ return listdir(DIR_BASE)
+
+def list_available(force=False):
+ filename = join(DIR_BASE, AVAILABLE_LIST)
+ if not exists(filename):
+ update_referentiel(AVAILABLE_LIST, 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 de forcer une mise à jour."
+ f.close()
+ return referentiels
+
+def add_available(force=False):
+ referentiels = list_available(force)
+ referentiels = set(referentiels) - set(listdir(DIR_BASE))
+ for referentiel in referentiels:
+ update_referentiel(referentiel, force)
+
.SH SYNOPSIS
\fBauf-refer\fP [\fB-f\fP] \fB-a\fP \fIreferentiel\fP
.br
-\fBauf-refer\fP \fB-d\fP \fIreferentiel\fP
+\fBauf-refer\fP \fB-r\fP \fIreferentiel\fP
.br
\fBauf-refer\fP \fB-h\fP | \fB-l\fP
.br
.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
+.B \-r, \-\-remove
Supprime un référentiel.
.SH FILES
.TP
+auf-refer (1.0.0) jaunty; urgency=low
+
+ * Réécriture complète dans l'optique d'un module réutilisable.
+
+ -- Progfou <jean-christophe.andre@auf.org> Mon, 10 Aug 2009 06:34:57 +0700
+
auf-refer (0.5) jaunty; urgency=low
* Le projet "auf-referentiels" devient "auf-refer", comprend qui peut... ;-)
Section: auf
Priority: optional
Maintainer: Progfou <jean-christophe.andre@auf.org>
-Build-Depends: cdbs, debhelper (>= 5.0.0)
+Build-Depends: cdbs (>= 0.4.49), debhelper (>= 5), python, python-support (>= 0.7)
Standards-Version: 3.7.3
Homepage: http://git.auf.org/?p=auf-poste-client;a=tree;f=auf-refer
Package: auf-refer
Architecture: all
-Depends: ${misc:Depends}, adduser, python (>= 2.5), python-simplejson
-Provides: auf-referentiels
+Depends: adduser, python (>= 2.5), python-simplejson, ${misc:Depends}
Replaces: auf-referentiels
Conflicts: auf-referentiels
Description: outil de copie et mise à jour des réferentiels AuF
#!/usr/bin/make -f
+DEB_PYTHON_SYSTEM=pysupport
-DEB_MAKE_INSTALL_TARGET=install DESTDIR=$(DEB_DESTDIR)
include /usr/share/cdbs/1/rules/debhelper.mk
-include /usr/share/cdbs/1/class/makefile.mk
-include /usr/share/cdbs/1/rules/utils.mk
+include /usr/share/cdbs/1/class/python-distutils.mk
+
+# Don't compress .py files
+DEB_COMPRESS_EXCLUDE := .py
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from distutils.core import setup
+
+setup(name='auf-refer',
+ version='1.0.0',
+ author='Progfou',
+ author_email='jean-christophe.andre@auf.org',
+ url='http://git.auf.org/?p=auf-refer.git',
+ description='AuF utility to optimize access to reference data',
+ long_description='Ce paquet fournit un outil permettant de copier puis de mettre régulièrement à jour une sélection des référentiels AuF.',
+ license='LGPL',
+ download_url='git://git.auf.org/auf-refer.git',
+ classifiers=[
+ 'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
+ 'License :: OSI Approved :: GNU General Public License (GPL)',
+ 'Programming Language :: Python',
+ 'Topic :: Database :: Database Front-Ends',
+ 'Natural Language :: French',
+ ],
+ requires=['simplejson'],
+ py_modules=['aufrefer'],
+ data_files=[
+ ('/etc/auf-refer',['auf-refer.conf','apache.conf']),
+ ('/usr/sbin',['auf-refer']),
+ ],
+ )
+