Généralités
Le coeur du système repose sur une base LDAP ainsi que sur les scripts contenus dans le répertoire /usr/scripts/gestion.
La base LDAP
La base principale est stockée sur vert, elle est répliquée sur sila. Ces bases sont accessibles par un socket ou alors en ldap sur le vlan adm. Le choix d'utilisation de la base se fait préférentiellement comme suit :
sur vert : utilisation du socket /var/run/ldapi pour toute opération
sur sila : utilisation du socket /var/run/ldapi pour lecture et ldap://ldap.adm.crans.org pour écriture
sur les autres machines : ldap://ldap.adm.crans.org pour lecture et écriture
L'utilisation de ldap ou du socket pour écriture requière une authentification (bind) par utilisateur et mot de passe. Celle-ci est inutile pour lecture, les droits étant gérés au niveau du socket.
Gestion des groupes et utilisateurs
La base LDAP est également interfacée au niveau du système grâce à nsswitch (annuaire des utilisateurs et groupes) et pam (authentification des utilisateurs). Seulement des accès de lecture sont effectués par ces sytèmes.
Scripts de gestion (/usr/scripts/gestion)
Le but premier de la base étant une centralisation des données il est apparu naturel de faire de même pour les scripts et donc de les centraliser. Ils sont montés en nfs sur tous nos serveurs.
Le language de programmation utilisé est le python, c'est un langage objet. Un minimum de prérequis sur la programmation objet (vraiment minimum) est donc requis pour la compréhension de la suite.
Seules les principales fonctions, classes et méthodes seront présentées ici, le seul but de cette documentation est de donner les bases nécessaires pour la compréhension de l'esprit de la programmation. Pour une utilisation plus approfondie des objets définis ici (description exhaustive des méthodes de chaque classe) utiliser pydoc.
Base du système : ldap_crans.py
Ce fichier transpose les divers objets de la base ldap en objets python facilement manipulables :
crans_ldap : parent de toutes les autres classes, les méthodes à remarquer sont :
search : permet une recherche dans la base, retourne un dictionnaire : { 'machine' : [ instances de la classe machine ] , 'club' : [ instances de la classe club ], 'adherent' : [ instances de la classe adherent ] }
services_to_restart : cf la partie génération des fichiers de conf
adherent : un adhérent du crans
club : un club "hébergé" par le crans
crans : l'association elle-même
machine : une machine
Les classes adherent, club et crans seront qualifées de "propriétaire". Une classe "propriétaire" possèdera une méthode machines qui retournera la liste des machines associées (instances de la classe machine). A l'inverse les machines auront une méthode proprietaire qui retournera leur "propriétaire" (instance de la classe qui va bien).
Les classes adherent, club et machine possèdent une méthode par caractéristique à prendre en compte. Cette méthode appelée sans argument retournera simplement la valeur de la caractéristique, si appelée avec argument elle affectera cette caractéristique en vérifiant que l'argumenent est correct vis à vis de la caractéristique. Exemple de manipulation de la classe adherent :
$ python Python 2.3.4 (#2, Sep 24 2004, 08:39:09) [GCC 3.3.4 (Debian 1:3.3.4-12)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import ldap_crans >>> adh = ldap_crans.adherent()
Création d'une nouvelle instance de la classe adhérent (un nouvel adhérent donc)
>>> adh.nom() u''
Le nom n'est vide, à noter que le retour des différentes méthodes sont des unicodes et non pas des chaîne.
>>> adh.nom('test qui va foirer car le nom est incorrect$$$') Traceback (most recent call last): [...] ValueError >>> adh.nom('test') 'Test' >>> adh.nom() u'Test'
On a bien attribué Test comme nom à ce nouvel adhérent, à noter l'apparition de la majuscule au nom.
A ce stade il n'y a rien d'écrit dans la base. Les classes nommées ci-dessus possèdent également une méthode save pour enregistrer l'entrée dans la base LDAP (une fois que les différentes caractéristiques ont été renseignées) et delete pour supprimer l'entrée de la base.
ldap_crans.py peut aussi se lancer en ligne de commande :
Usage /usr/scripts/gestion/ldap_crans.py [ACTION] --lock : donne la liste des locks actifs --purgelock : supprime tous les locks de la base LDAP --menage : supprime les machines des anciens adhérents
Affichage des données : whos.py
Ce module contient tout le nécessaire pour mettre en forme et afficher les données de la base. La principale fonction est aff, l'utilisation est simplissime : aff(<une liste d'objets : adhérents, machines ou clubs>) affiche sur la sortie standard les caractéristiques de chacun des objets fournis.
Ce module peut être excécuté et dans ce cas effectue une recherche dans la base et affiche la résultat. (whos -h pour plus d'infos à ce sujet)
Interface utilisateur : gest_crans.py
Ce script permet la modification des différentes caractéristiques des objets grâce à une interface ncurses intuitive.
Génération de la configuration des divers services (package gen_confs)
A chaque enregistrement dans la base ldap (méthode save des différents objets) une base de services à reconfigurer est tenue à jour. Celle ci est simplement accessible par la méthode services_to_restart de crans_ldap. Cette méthode retourne un dictionnaire : { 'nom du service' : [ 'arguements eventuels' ], ....}
Le script central : generate.py
Deux modes de fonctionnement :
sans arguments : reconfiguration des services mentionnés dans la base
- avec argument : reconfiguration uniquement du service mentionné
La reconfiguration d'un service se passe généralement comme suit :
1 supression du service de la base des services à redémarrer
2 import de la classe correspondant au service
3 initialisation d'un instance de celle-ci
4 appel de la méthode reconfigure
5 si une erreur c'est produite lors de l'exécution (exception) on remet le service dans la base des services à redémarrer
Le script aura une liste de service différent suivant la machine sur laquelle il est exécuté (un seul script mais condition sur le nom de machine). Si certains services demandent un redémarrage sur plusieurs machines (firewall par exemple) le diagramme de reconfiguration ci-dessus ajoutera sur zamok à la base des services à redémarrer des clefs spécifques pour les autres machines (entre 1 et 2).
Les classes de reconfiguration des services
Elles héritent généralement de la classe gen_config (dans le fichier __init__.py) cette classe définit les méthodes suivantes (principales méthodes) :
_open_conf : à utiliser à la place de l'instruction open : retourne comme open un descripteur de fichier mais ajoute des commentaires indiquant de ne pas modifier le fichier et permet une concervation de l'ancienne config en cas d'erreur lors de la génération.
reconfigure : entraine la génération du ou des fichiers de conf. En cas d'echec remet la config originale (su utilisation de _open_conf). En cas de réussite redémarre du service. Gère aussi l'affichage de ce qui est fait, les exceptions rencontrées ainsi qu'un lock pour éviter que deux processus de reconfiguration du même service puissent être lancés en même temps.
Pour un fonctionnement correct de la méthode reconfigure il faut que la classe fille possède les caractéristiques suivantes :
méthode _gen : appel par reconfigure pour génération de la conf
méthode __str__ : retourne une chaîne (juste pour l'esthétique)
chaine restart_cmd : commande à exécuter pour le restart (si vide ne fera rien)
Juste pour l'esthétisme, la méthode _gen peut utiliser une animation : la variable anim de la classe contient une instance de la classe anim du module affich_tools
Les programmes basiques
ldapsearch
Il permet d'effectuer une recherche dans la base de données :
Syntaxe de base : ldapsearch -b "base" -x -LLL "critère" champs à afficher
-b base : dn de base dans lequel on recherche des enregistrements (ex : dc=crans,dc=org)
critère : critère sur les enregritrements à selectionner (ex : (&(paiement=2004)(carteEtudiant=2004)))
champs à afficher : selectione que certains champs (ex : uid nom prenom)
L'option -x sert à ne pas utiliser SASL et -LLL à ne pas afficher les bilan de la recherche (nombre d'enregistrements...)
Pour obtenir la liste des nounous on peut donc effectuer les opérations :
ldapsearch -b "ou=Group,dc=crans,dc=org" -x -LLL "(cn=adm)"
ou
ldapsearch -b "ou=data,dc=crans,dc=org" -x -LLL "(droits=Nounou)" uid nom prenom