Modifications entre les versions 8 et 9
Version 8 à la date du 2006-12-11 16:50:31
Taille: 10184
Éditeur: ThomasNoël
Commentaire: Reprise après erreur : journalisation des problèmes
Version 9 à la date du 2006-12-11 16:51:42
Taille: 10207
Éditeur: ThomasNoël
Commentaire: un ptit sommaire car la page commence à devenir longue (on la découpera plus tard)
Texte supprimé. Texte ajouté.
Ligne 6: Ligne 6:

[[TableOfContents]]

Cette page contient la documentation technique du code du logiciel GUIA.

Les sources sont disponibles ici : http://trac.sn.auf.org/guia

Le code est développé par OusmaneWilane. JérômeSantini, JeanChristopheAndré et ThomasNoël définissent avec lui le cahier des charges, et le font/feront évoluer au fur et à mesure des besoins.

TableOfContents

Vue générale (rappel)

L'application est bâtie autour de trois composantes principales:

  • Noyau de l'application : il gère les données de base, c'est-à-dire les données fonctionnelles comme définit dans l'analyse (utilisateur, groupe, abonnement, groupes, extra_*, etc.).

  • Interface utilisateur : il s'agit de l'interface de gestion des données de base. Pour l'instant c'est surtout l'interface Web qui nous intéresse, mais toute l'API est disponible en Python pour d'autres interfaces.

  • Greffons : les application ajoutées pour les traitements métiers associés aux données de base. Par exemple : la gestion de la base MySQL pour l'authentification, la gestion d'une base MySQL pour la messagerie, etc.

Le noyau et ses greffons communiquent via des signaux (noyau vers greffon) et exceptions (greffon vers noyau).

GUIA est développé en ["Python"] dans le cadre de travail ["Django"]. Ce cadre nous permet d'éviter de perdre du temps en réinventant la roue.

Greffons

Principes

Chaque greffon dispose d'un sous-répertoire contenant un constructeur __init__.py pour l'initialisation de la classe métier principale.

La classe principale du greffon est liée à la classe utilisateur par un lien foreign key Django.

Si elle doit gérer des champs extra, elle invoque la classe extra_utilisateur pour la persistance des données (variable/valeur) en invoquant la méthode save() de celle-ci et en inhibant la sienne.

Ensuite la classe définit sa logique métier qu'elle connaît mieux que personne dans son usine (usine.py justement).

Chargement des greffons par le noyau

Lors du démarrage de l'application, tous les greffons sont chargés [http://trac.sn.auf.org/guia/browser/branches/wilane/main/models.py main/models.py] par :

  • # à la fin de main/models.py :
    modules = map(__import__, greffons.GREFFONS_INSTALLES)

sachant de greffons.GREFFONS_INSTALLES est défini dans [http://trac.sn.auf.org/guia/browser/branches/wilane/main/greffons/__init__.py main/greffons/init.py]

Coté interface admin : ce qu'affiche le greffon

Les greffons sont des applications Django, plus exactement des modèles Django. Comme Django est intelligent, si le modèle du greffon est lié à un objet du noyau par une clé distante, l'interface admin de l'objet noyau sera automatiquement complétée par les champs proposée par le modèle du greffon. C'est tout. C'est un peu magique, c'est Django.

Voir par exemple : [http://trac.sn.auf.org/guia/browser/branches/wilane/noyau/greffons/auth/__init__.py noyau/greffons/auth/init.py]

Réaction d'un greffon lors d'une action sur le noyau : émission de signaux par le noyau

L'usine reçoit les notifications de modifications d'objets leurs pemettant de réagir. Ces notifications sont acheminés via des [http://code.djangoproject.com/wiki/Signals signaux], qui peuvent être ceux intégrés à Django (pre_save, post_save, etc.) ou des signaux personnalisés. Chaque signal vient avec l'objet qui a émit le signal.

Pour recevoir un signal, les méthodes de l'usine s'enregistrent au niveau du signal auquel elles veulent réagir. Par exemple, au niveau de l'usine du greffon «auth» :

  • dispatcher.connect(Passwd, sender=utilisateur, signal=signals.models.post_save)

Dans cet exemple, à chaque fois qu'un utilisateur sera enregistré (c'est-à-dire après l'appel à utilisateur.save) la methode Passwd du greffon sera lancée. Cette méthode recevra en argument l'objet modifié, et devra alors faire son traitement métier ; dans le cas présent mettre à jour la base nss-mysql.

L'émission de signaux reste dans le seul sens (coeur => greffons) et chaque greffon utilise un mécanisme adapté de mise à jour asynchrones de ses données pour éviter que le coeur plante à cause des problèmes des greffons.

Les greffons sont autonomes en termes de gestion de leurs données internes, la seule contrainte qu'on leurs impose est la cohérence des interfaces qu'ils fournissent au modèle de base. Autrement dis ils sont libres d'organiser leurs objets comme ils veulent. Ils peuvent stocker leurs données de configuration générale dans la base principale de l'API tant qu'ils sont les seuls à y accéder.

En cas de problème sur un greffon : levée d'une exception par le greffon

/!\ en cours de programmation, très susceptible d'être très modifié

Si un greffon rencontre un problème lors de son travail, il peut lever une exception. Le noyau est programmer pour réagir :

  1. il renseigne une table "plantages" pour signaler que l'objet a connu un soucis avec le greffon.
  2. le noyau enregistre cependant ses données (par exemple l'utilisateur sera bien créé au niveau du noyau)
  3. lorsqu'un objet noyau sera affiché, s'il existe un enregistrement le concernant au niveau de la table "plantages", un bandeau rouge sera affiché par le noyau sur la page d'admin pour indiquer que l'objet n'est pas n'est pas "fonctionnel".

La table "plantages" permet ensuite de savoir si un objet noyau a eu des soucis lors de sa gestion par un greffon. Dans ce cas, on pourra relancer la création/modification de l'utilisateur en appelant le/les greffons qui a/ont planté (ou tous les greffons, pour aller plus vite).

La table "plantages" pourra également être considérée comme une file d'attente des soucis à régler.

En cas de plantage, on pourra faire appel à la synchro différée.

Synchronisation différée (reprise après erreur)

Les greffons doivent tous proposer une methode "synchro" afin de re-synchroniser un objet du noyau (utilisateur, groupe, abonnement, etc). Cette méthode sera utilisée pour réparer un problème signalé au niveau de la table "plantages".

Cela permettra également d'ajouter un greffon en cours de route : lors de son ajout, on déclenchera la synchro sur tous les objets noyau pour qu'ils soient tous prise en compte par le greffon.

On peut aussi imaginer que chaque greffon propose une méthode "vérification" (sans action de correction) afin de pouvoir faire un "check" de la cohérence... /!\ A étudier.

Reprise après erreur : journalisation des problèmes

Principe : le noyau maintient un journal des erreurs survenues lors de l'appel aux greffons. Pour cela, lors de chaque émission d'un signal vers les greffon, si une exception est retournée par un greffon, le noyau stocke dans le journal :

  • le type d'objet en cause : utilisateur, groupe, abonnement, ...
  • l'identifiant concerné (autrement dit, on ne stocke par l'objet lui-même mais une référence vers cet objet)
  • le greffon qui a provoqué l'erreur
  • le signal qui a provoqué l'erreur, c'est-à-dire l'action demandée au greffon : ajout/modification, suppression, ...

<!> à vérifier : chaque triplet { ref_objet , greffon , action } doit être unique dans le journal (la clé). Si un objet a provoqué une erreur lors de deux appels consécutifs identiques à un greffon, on ne doit stocker que la dernière erreur survenue.

Le journal est un ensemble d'objets "journal" décrit dans le modèle Django du noyau. Cet objet possède une méthode synchro(self) qui sait rappeler le greffon en cause en lui renvoyant l'objet et l'action à effectuer (via un signal, comme toujours). Si ce nouvel appel se passe bien, l'entrée du journal se supprime elle-même (ou bien se met à "ok" via un flag).

Les greffons doivent donc savoir qu'ils peuvent recevoir un signal pour un objet qui avait échoué (il faut faire un peu attention dans la programmation des actions des greffons, qu'ils soient bien protégés à ce niveau).

A coté de cela :

  • lors de la suppression d'un objet du noyau (méthode delete), celui-ci doit vider les entrées du journal correspondantes à l'objet, s'il y en a

  • si un objet dans le noyau est créé ou modifié (méthode save) et que cela ne soulève aucune exception de la part des greffons, il faut également vider le journal des entrées correspondantes

  • on pourra disposer au niveau du noyau d'une fonction reprise_totale qui effectuera une reprise sur chaque élément signalé du journal, c'est-à-dire qu'on considère le journal comme une liste de tâches à reprendre

Accès ligne de commande (CLI)

Les outils lignes de commande, programmés en Python, accèdent directement au modèle proposé par Django. Les signaux sont donc automatiquement déclenchés pour la notification des greffons et chaque greffon prend ses responsabilités.

Dans un premier temps nous fournissons toutes les commandes type adduser, addgroup et passwd les plus proches possibles des classiques, fournissant les propriétés intéressantes ajoutées au modèle de données que vous avez retenu. Ces commandes sont écrites de sortes qu'elles puissent être invoquées comme commande ou comme modules à importer dans d'autres applications Python (et toujours aucun soucis à se faire pour la propagation des signaux).

Les systèmes d'extraction

À partir d'un système comme Django, on peut extraire les données assez facilement via des templates. Pour la plupart des extractions il ne sera pas nécessaire à l'administrateur système de savoir programmer en Python.

Chaque système d'extraction disposera d'un fichier de configuration par défaut. Par exemple pour un système qui générera le fichier /etc/passwd via une extraction, on indiquera le shell par défaut. Ce shell par défaut pourra être éventuellement écrasé pour tel ou tel utilisateur s'il existe des informations spécifiques pour cet utilisateur (voir plus loin la notion de champ extra dans la base de donnée).

Projet/GUIA/Code (dernière édition le 2008-02-21 22:09:39 par localhost)