Posté par Stéphane Klein le mercredi 10 mars 2010 dans
les catégories
Informatique, WSGI, WebDAV, Python, Web-dev, Projets, Développement
| View Comments
Plus de six mois après avoir publié mon dernier billet au sujet des serveurs
WebDAV basés sur protocole WSGI
(sous Python), il est tant pour moi de faire un nouveau point sur la situation.
1. J'ai choisi WsgiDAV
Au mois d'août dernier, je n'avais pas encore choisi entre le projet
pywebdav et wsgidav.
Depuis, j'ai fait mon choix, j'ai choisi wsgidav. Qu'est ce qui a motivé ce choix ?
- l'architecture de wsgidav est modulaire, je trouve que l'utilisation de
plusieurs middleware wsgi pour ajouter des fonctionnalités est une chose intéressante
- comme son nom l'indique WsgiDAV est orienté
WSGI ce qui est avantageux pour moi car
c'est mon objectif premier et donc cela me donne moins de travail par rapport à
pywebdav
2. Changements apportés à WsgiDAV
Lorsque je travaillais sur le projet pywebdav j'avais comme objectif
d'apporter des modifications au code pour fournir une classe application ou
middleware WSGI. Je n'ai plus à me préocuper de ce point car WsgiDAV est
nativement orienté WSGI.
Par contre, depuis août j'ai tout de même apporté des améliorations à
WsgiDAV. Ma plus importante contribution est la compatibilité avec le client
WebDAV Finder de Apple.
2.1. Compatibilité avec Apple Finder WebDAV Client
C'est la tâche qui m'a pris le plus de temps et posé le plus de difficulté...
bien que cela soit surtout dû à un manque de méthode et un surplus de
procrastination.
Au niveau de la méthode, j'ai procédé à tâton pendant un certain moment. Je
plaçais des logs, activais
PDB...
et j'essayais de de comprendre les causes d'incompatibilités avec
Apple
Finder.
J'ai ensuite utilisé
Wireshark
pour analyser les échanges TCP/IP... ce qui fut une très bonne idée car en
quelques heures j'ai trouvé et corrigé les erreurs que je n'arrivais pas à
déceler auparavant.
Parlons maintenant de ma procrastination... on va dire que j'ai tourné autour du
problème pendant trois ou quatre mois, de septembre à décembre 2009.
Étant donné que je ne procédais pas avec la bonne méthode, je n'étais pas très
motivé pour travailler sur cette tâche. J'avais toujours une bonne excuse pour
travailler sur d'autres choses. Comme très souvent, la cause première de la
procrastination est la peur de l'échec.
La bonne nouvelle est que maintenant les problèmes de compatibilités avec Apple
Finder sont réglés. D'autre part, ces corrections ont aussi corrigé d'autres
erreurs... avec Windows Vista si mes souvenirs sont bons.
3. Chantiers en cours
Depuis que les problèmes de compatibilités avec Apple Finder sont résolus, j'ai
débuté d'autres chantiers...
3.1. Amélioration des tests
J'en ai marre de devoir utiliser Wireshark, un client WebDAV... pour tester
mon code... j'ai donc décidé pour gagner du temps et de la qualité en regardant
du coté des test fonctionnels... ce que j'aurais dû faire depuis le début !
En gros, WsgiDAV utilise trois types de tests :
- un fichier de commande à lancer avec litmus (programme pour tester des serveurs
Webdav)
- utilisation de la librairie davclient
- utilisation de paste.fixture.TestApp mais ce
type de test est limité aux requêtes HTTP classiques GET, PUT, DELETE
Autre informations :
- les tests utilisent le module standard unittest
- il n'est pas toujours possible de lancer des tests individuellement, par
exemple avec test_wsgidav_app.py il est obligatoire de lancer
l'intégralité des fonctions de tests et dans le bon ordre
Mes objectifs et tâches en cours au niveau des tests :
- utiliser l'outils Nose pour lancer les
tests et supprimer petit à petit l'utilisation du module unittest
- permettre de lancer les tests individuellement
- fournir une classe davclient.TestApp dérivée de paste.fixture.TestApp
qui permet de tester l'intégralité des fonctions Webdav.
Pour le moment ces tâches ne me posent pas trop de difficultés.
3.2. Support d'un provider "Mixin"
Dans un de mes projets d'utilisation de WsgiDAV, j'ai besoin de "monter" un
dossier accessible via une url du type "http://exemple.com/dav/".
Petit détail, j'aimerais pouvoir voir le dossier "dav" (dossier virtuel nommé
aussi "share_name") lorsque je me connecte à "http://exemple.com/". Cette
fonctionnalité n'est pas existante actuellement.
Ce point est important pour deux choses :
- simplifier la "découverte" des points de montages
- Gnome Nautilus ne
permet pas de visualiser une resource si la racine du domaine ne contient pas
son dossier parent (c'est un bug que j'aimerais corriger à l'avenir). C'est à
dire qu'il n'est pas possible d'accéder à "http://exemple.com/dav/" si la
requête PROPFIND sur "http://exemple.com/" ne liste pas le dossier
"dav"
Pour résoudre ce problème, j'ai décidé de créer un nouveau provider, que j'ai
nommé "MixinProvider". Ce provider permet de "mixer" plusieurs "provider" en un
seul.
Exemple d'utilisation :
provider = MixinProvider((
("/", FilesystemProvider('/tmp/root1/')),
("/", FilesystemProvider('/tmp/root2/')),
("/dav", FilesystemProvider('/tmp/root3/')),
("/foo/bar/", FilesystemProvider('/tmp/root3/'))
})
Note :
- il est tout à fait possible de mélanger d'autres types de provider que
FilesystemProvider
- les providers sont traités dans l'ordre d'apparition de la liste (ici un
tuple), c'est à dire que dans cet exemple, si les dossiers '/tmp/root1/' et
'/tmp/root2/' contiennent tous les deux un fichier nommé "foobar.txt", si
l'utilisateur exécute la requête GET '/foobar.txt', c'est le contenu du
fichier '/tmp/root1/foobar.txt' qui sera retourné.
Actuellement, la classe MixinProvider est presque fonctionnelle.
3.3. Support d'un provider "Dummy"
Pour la réalisation de la classe MixinProvider j'ai eu besoin de créer un provider
permettant de créer des ressources mais aussi surtout des dossiers fictifs… d'où
le nom « Dummy ».
Voici un exemple d'utilisation de cette classe :
dummy_provider = DummyProvider(
resources = ('/file1.txt', '/folder_a/file2.txt', '/file3.txt',),
collections = ('/folder_b/', '/folder_c/folder_d/',)
)
Remarque : la classe MixinProvider crée automatiquement un provider
"dummy" pour permettre la visualisation des points de montages lors de l'exécution de
requêtes PROPFIND.
4. Chantiers futurs
Voici une liste d'autres chantiers futurs :
- amélioration de la documentation : basé sur Sphinx, qui devra être hébergé sur
http://packages.python.org/wsgidav/
- amélioration des tests..., mise en place d'un buildbots...
- rédiger une procédure de sortie de release : liste d'instructions à réaliser
après chaque release stable. L'une de ces instructions serait de mettre à jour
un tableau qui liste les clients webdav avec lesquels wsgidav est compatible.
5. En annexe du projet
À la marge du projet, j'ai réalisé un provider basé sur ZODB. Il fonctionne
plutôt bien. Ce provider n'est pas libre pour le moment.
C'est dans le cadre de ce projet que j'ai eu besoin de créer le provider
MixinProvider.
6. Temps passé sur le projet
Depuis août, on peut dire que j'ai travaillé en moyenne 3h par mois sur le
projet... le problème est que j'y ai surtout passé de multiples petits moments... ce
qui n'est pas ce qu'il y a de plus efficace... car la plupart du temps j'avais
juste le temps de me replonger dans le code... avant d'arrêter.
Dans les semaines qui viennent, j'espère pouvoir travailler chaque dimanche
quatre heures sur le projet afin de rapidement finir la partie provider Mixin
(ce qui est presque réalisé).
Posté par Stéphane Klein le mercredi 19 août 2009 dans
les catégories
Informatique, WSGI, WebDAV, Python, Web-dev, Projets, Développement
| View Comments
1. Le besoin
Dans un certain nombre de projets web, j'ai besoin d'utiliser un
serveur
WebDAV.
J'ai besoin d'utiliser ce protocole pour permettre "au monde extérieur"
d'accéder simplement à mes applications en utilisant des fichiers accessibles
directement sur leur
sytème de fichier,
de la même manière qu'ils accèdent à des fichiers classiques. Ceci est
réalisé par des points de montage WebDAV.
Étant donné que ces dévelopements web sont basés sur sur l'interface
WSGI
(c'est du Python) c'est tout naturellement que je désire utiliser un serveur
WebDAV écrit en Python qui s'interface sur WSGI.
Mes contraintes, désires concernant le serveur WebDAV que je recherche :
- peu de dépendances
- un code assez compréhensible
- basé sur WSGI afin de :
- n'avoir qu'un seul serveur à lancer pour servir les pages web et
répondre aux requêtes WebDAV
- avoir tout sur le même port
- pouvoir utiliser le serveur WebDAV en middleware WSGI
2. État des lieux
Il y a six mois, j'ai fait une recherche dans ce sens. Voici un peu mes
conclusions :
- il existe un certain nombre de modules DAV basés sur le framework Twisted;
- il existe zanshin qui
est un serveur WebDAV développé pour l'application chandler;
- il existe plein de choses à propos de WebDAV dans Zope 3;
- il existe PyWebDAV qui est basé sur
BaseHTTPServer.
Une recherche sur Python Package Index
vous permet de trouver pas mal de choses. On y trouve à la fois des packages liés
à des clients et des serveurs WebDAV.
Il y a six mois je n'ai pas trouvé de serveurs WebDAV basés sur WSGI. À la fois
au niveau de mes recherches sur le web, que mes questions sur IRC. Je ne sais
plus si j'ai posé la question sur une mailing list… il va falloir que je
recherche et si ce n'est pas le cas… c'est mal !
3. Mon choix initial
Au mois de mai dernier, mon choix s'est porté sur PyWebDAV. Pourquoi ?
- parce que au moment où je l'avais testé avec Nautilus et
Apple Finder, il semblait bien fonctionner
- car il était facile à tester (peu de dépendances…)
- j'arrive à facilement comprendre le code source de ce projet
- les développeurs de PyWebDAV sont intéressés pour avoir une version WSGI
de leur serveur
4. Après une petite étude, voici ce que je devais améliorer sur PyWebDAV
- adapter PyWebDAV à WSGI
- ajouter des tests unitaires et fonctionnels
- ajouter de la documentation
- tester les performances
Je pensais aussi utiliser les dépendances suivantes :
5. Ce que j'ai fait
5.1. Prototype rapide de conversion de PyWebDAV en WSGI
Tout d'abord, j'ai commencer à expérimenter si j'allais réussir à
convertir PyWebDAV à WSGI.
Pour cela, je me suis basé sur WebOB. Le travail a principalement
consisté à convertir les appels à l'API BaseHTTPRequestHandler à
WebOB. Globalement je n'ai pas eu de trop grosses difficultés.
Cela m'a aussi permit d'approfondir un peu mes connaissances dans
le protocole WebDAV.
Les premières expérimentations ont plutôt bien fonctionné. J'effectuais mes
tests avec Cadaver.
Par contre je me suis très rapidement rendu compte que PyWebDAV rencontrait
des problèmes de performances lors des transferts de gros fichiers.
Ensuite j'ai rencontré de nombreux problèmes avec le client Apple Finder. Je
me suis rendu compte que ces problèmes impactaient pas seulement ma
transformation de PyWebDAV en WSGI mais aussi la version d'origine de
PyWebDAV.
À ce stade, j'ai pu conclure que j'arrivais à convertir PyWebDAV à WSGI et j'ai
donc décidé de commencer par corriger un certain nombre de bugs dans la version
d'origine de PyWebDAV basé sur BaseHTTPServer.
5.2. Mes changements effectués sur PyWebDAV d'origine
Voici la liste des choses que je désirais corriger et
améliorer sur PyWebDAV d'origine :
- correction d'un certain nombre de petites erreurs que je ne vais pas
lister ici (voir le
Changes log de PyWebDAV
et son bug tracker)
- corriger les erreurs liées à l'utilisation de Apple Finder
- utiliser les iterateurs aux niveaux de la lecture et de l'écriture des
fichiers afin de régler les problèmes de performances (consommation mémoire)
lors des transferts de gros fichiers
- ajout de tests unitaires et fonctionnels
- ajout de documentations
Après l'envoie de quelques patchs dans le
bug tracker de PyWebDAV,
un développeur du projet m'a donné un accès en écriture au repository
subversion de PyWebDAV et m'a autorisé d'appliquer directement mes
patchs au trunk. Assez sympathique de sa part, depuis c'est ce que
j'ai fait.
À noter que parallèlement à cela, j'ai une branche expérimental du projet qui
se trouve ici basée
sur Mercurial.
Depuis j'ai corrigé un certain nombre de bugs sur la branche principale de
PyWebDAV.
À coté de celle-ci, ma branche expérimental :
- est parfaitement fonctionnelle avec Nautilus, Cadaver et
Apple Finder. Je n'ai pas effectué de test sous MS Windows
pour le moment.
- le transfert de gros fichier ne pose plus de problèmes de performances
6. En gros ce qu'il reste à faire
Maintenant que PyWebDAV en mode BaseHTTPServer fonctionne correctement avec
différent clients WebDAV, c'est le moment d'effectuer proprement la conversion à
WSGI.
Mais avant cela, pour faciliter cette phase de transformation, j'aimerais
réaliser un certain nombre de tests fonctionnelles. Ceci facilitera le travaille
de conversion à WSGI car je n'aurais qu'à lancer la batterie de tests pour voir
si j'ai fait des erreurs ou non.
7. Ce que je découvre le 18 août 2009 !
Hier, peu après mon retour de vacances, en regardant les nouveaux packets
sur "Python Package Index" je
découvre "wsgidav".
Après avoir un peu regardé "wsgidav", voici quelques remarques :
- le projet est bien organisé, avec de la doc, le code source semble assez
simple à comprendre
- le projet utilise plusieurs middleware WSGI pour certaine tâches :
- pour faire du debug
- pour gérer l'authentification
- pour activer "un browser web" : explorer les dossiers… en lecture
seule dans un navigateur
- une solution pour configurer plusieurs points de montage
- …
- lorsque j'ai testé un transfert de gros fichiers (500Mo) il a le même
problème de performance qu'avait "PyWebDAV"
8. Et maintenant ? continuer à travailler sur "PyWebDAV" ou travailler sur "WsgiDAV" ?
Pour le moment, je n'ai pas encore pris de décision mais voici comment je
vais faire mon choix :
- je vais tester "WsgiDAV" avec différent clients pour voir son niveau
d'implémentation du protocole
- je vais entrer en communication avec le développeur de "WsgiDAV"
- je vais informer sur "PyWebDAV" l'existence du projet "WsgiDAV"
En fonction de tout cela, je jugerais si pour atteindre mes objectifs de
départ, j'ai plus de travaille à faire avec "PyWebDAV" ou avec "WsgiDAV".