126 lines
6 KiB
Text
126 lines
6 KiB
Text
Auteur : PEB <becue@crans.org>
|
|
Date : 09/03/2015
|
|
Licence : GPLv3
|
|
|
|
What the fuck is happening?
|
|
===========================
|
|
|
|
Trigger est une sorte de librairie de remplacement de generate et des services
|
|
dans la base LDAP, qui fonctionnent avec bien trop de délai.
|
|
|
|
Trigger est le fruit d'une longue et intelligente (quelle modestie) réflexion,
|
|
et donc nous allons ici décrire son fonctionnement.
|
|
|
|
Mise à jour LDAP : the fuck is happening?
|
|
=========================================
|
|
|
|
Le binding envoit un tuple contenant en première entrée un hash, en deuxième entrée
|
|
un dico contenant les attributs avant modif par le binding, en troisième entrée un
|
|
dico contenant les attributs après modif, en quatrième entrée des données additionnelles
|
|
(inchangées durant tout le processing).
|
|
|
|
Documentation succincte de trigger
|
|
==================================
|
|
|
|
Tous les fichiers sont renseignés depuis /usr/scripts.
|
|
* gestion/trigger/trigger.py est un fichier python qui importe un consumer de
|
|
la librairie cmb. Il marche de manière synchrone, c'est-à-dire qu'il attend et
|
|
traîte les messages un par un. Dans gestion/config/trigger.py, il y a la liste
|
|
des services que chaque hôte gère. Ainsi, gestion/trigger/trigger.py sait, en
|
|
fonction de l'hôte sur lequel il se trouve, comment il doit se comporter, et ce
|
|
qu'il doit importer. Par exemple, sur l'hôte dhcp, le seul service présent est
|
|
dhcp, et donc trigger va aller chercher gestion/trigger/service/dhcp.py, et
|
|
travailler avec.
|
|
* gestion/trigger/trigger.py importe des services, qui sont dans le dossier
|
|
services, et eux importent une méthode depuis gestion/trigger/host.py, qui leur
|
|
permet d'enregistrer des triggers. Cette méthode permet d'aller puiser dans une
|
|
factory portant le nom TriggerFactory les références vers les services utiles.
|
|
Cela permet ensuite de les régénérer à la volée.
|
|
|
|
* Le dossier gestion/trigger/services contient la liste des services existants
|
|
pour trigger. Le fonctionnement des services sera détaillé ci-après.
|
|
|
|
Fonctionnement des services
|
|
===========================
|
|
|
|
Un service est un fichier dans le dossier gestion/trigger/services. Il contient
|
|
une fonction décorée avec record_service. C'est une fonction qui sera appelée quand
|
|
trigger recevra une demande sur un serveur fournissant ledit service.
|
|
|
|
Pour que civet sache si un service doit être régénéré, et donc qu'il lui envoie
|
|
un message, il faut définir un parser. Ces parsers sont contenus dans
|
|
gestion/trigger/parsers/, et portent le nom du service associé. Ils contiennent
|
|
au moins une fonction décorée avec record_parser (dont les arguments sont des
|
|
attributs ldap à surveiller). Quand civet reçoit des modifs des bindings, il regarde
|
|
pour chaque attribut ayant changé s'ils sont surveillés par des parsers, et le cas
|
|
échéant demande la régénération des services associés.
|
|
|
|
Ajouter un nouveau service
|
|
==========================
|
|
|
|
Pour ajouter un service, il faut créer un fichier adapté dans trigger/services/,
|
|
et un dans trigger/parsers/. Il faut écrire des fonctions adaptées (le nom est libre),
|
|
par exemple, pour un parser :
|
|
|
|
{{{
|
|
@record_parser(lc_ldap.attributs.macAddress.ldap_name, lc_ldap.attributs.ipHostNumber.ldap_name)
|
|
def send_mac_ip(ob_id, body, diff):
|
|
}}}
|
|
|
|
ob_id est un hash (??)
|
|
body est le message reçu par civet sans transformation. diff est le diff calculé
|
|
à la volée. Le nom de la fonction n'est pas important. Le décorateur prend les
|
|
noms d'attributs à surveiller en paramètre. La fonction doit retourner un tuple
|
|
dont le premier élément est le nom du service à régénérer (par exemple, "dhcp"),
|
|
et le second les choses que le service devra lire et gérer pour se régénérer.
|
|
|
|
Pour un service, voici un exemple :
|
|
|
|
{{{
|
|
@record_service
|
|
def dhcp(body=None):
|
|
}}}
|
|
|
|
on devrait appeler "body" autrement, pour éviter de confusionner avec le body
|
|
obtenu à l'étape précédente -- Daniel
|
|
body contient le "body" construit dans un parseur. La fonction est décorée, et
|
|
son nom est stocké dans la TriggerFactory. Comme souligné précédemment, le nom
|
|
de la fonction est important, au même titre que le nom des fichiers dans
|
|
trigger/parsers et triggers/services.
|
|
|
|
Il faut ensuite référencer le service dans config/trigger.py pour les serveurs
|
|
où il est important, et relancer trigger sur ces machines. Lors des tests, il ne
|
|
faut pas hésiter à passer trigger en debug dans le fichier config/trigger.py.
|
|
Utilises testing.sh (en rajoutant une variable d'env pour ça), stp. -- Daniel
|
|
|
|
Parmi les choses importantes, l'idéal est d'avoir des dépendances les plus
|
|
paresseuses possibles d'un point de vue évaluation. Ainsi, civet qui ne fait
|
|
qu'importer le fichier et utiliser les fonctions d'analyse listées dans
|
|
changes_trigger peut éviter de jouer avec ce qui ne le concerne pas.
|
|
|
|
Enfin, si vous avez des questions, posez-les avant, pas après.
|
|
|
|
Pour chaque service, une "file d'attente" rabbitmq est créée ayant le nom
|
|
trigger-nomdel'hôte-nomduservice, et une clef de routage du type
|
|
trigger.nomduservice est mise en place pour que les messages envoyés vers
|
|
trigger.nomduservice soient dispatchés sur l'ensemble des queues
|
|
trigger-*-nomduservice.
|
|
|
|
Un service spécial
|
|
==================
|
|
|
|
Le service event est celui qui utilise les parseurs pour savoir quels services
|
|
doivent être régénérés. Quand il reçoit le body, il fait un calcul des différences
|
|
entre body[1] et body[2] (les deux dicos), et fournit ces différences aux parseurs,
|
|
qui lui rendent des messages à envoyer.
|
|
|
|
L'intérêt est d'assurer une indépendance maximale entre binding ldap et la
|
|
librairie trigger : le binding doit juste envoyer avec clef de routage
|
|
trigger.event les modifs qu'il fait, et c'est la librairie elle-même qui gère
|
|
les envois en son sein.
|
|
|
|
Cela permet aussi d'avoir des définitions de services précises d'un point de vue
|
|
spécification, et une portabilité plus que correcte de trigger d'un binding vers
|
|
un autre. (les seules données ldap qui l'intéressent sont les noms des
|
|
attributs, définis dans le schéma de la base ldap, il faut donc que le binding
|
|
fournisse ses données avec les mêmes noms)
|