Auteur : PEB 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)