[trigger] Réinventer la roue alors qu'on l'a déjà créée dans le dossier.

* Ça sert à rien de créer un transcriptor spécifique alors qu'on a déjà
 tout ce qu'il faut avec trigger.py pour gérer le bouzin. Il suffit
 d'une méthode event décorée avec record dans event.py...
This commit is contained in:
Pierre-Elliott Bécue 2014-06-12 17:38:00 +02:00
parent 9cac0c2531
commit 9346d174e2
2 changed files with 25 additions and 80 deletions

View file

@ -1,4 +1,29 @@
Documentation succincte de trigger
==================================
Tous les fichiers sont renseignés depuis /usr/scripts/gestion.
Trigger est une sorte de librairie de remplacement de generate et des services dans la base LDAP, qui marchent mal et qui sont une suite de patches.
Trigger est le fruit d'une longue et intelligente (quelle modestie) réflexion, et donc nous allons ici décrire son fonctionnement.
* trigger/trigger.py est un fichier python qui importe un consumer de la librairie cmb. Il marche de manière asynchrone, c'est-à-dire qu'il attend et traîte les messages un par un. Dans config/trigger.py, il y a la liste des services que chaque hôte gère. Ainsi, 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, trigger/trigger.py importe trigger/hosts/dhcp.py, qui décrit la gestion des services sur dhcp.
* Dans le fichier d'un hôte, on importe toujours trigger/host.py, qui fournit la méthode trigger(about)(body). About doit renseigner une méthode accessible par trigger/hosts/dhcp.py, et décorée avec "record" (chargée depuis trigger/host.py). record met dans une factory la méthode, et la rend accessible via la méthode trigger(about), qui retourne ladite méthode. body est donc passé en argument.
Ajouter un nouveau service
==========================
Si c'est un service partagé par plusieurs hôtes, il vaut mieux créer tout ce qu'il faut dans trigger/nomduservice.py, écrire tout ce dont on a besoin, décorer la méthode (dont le nom est celui du service, donc si ça parle de dhcp, appeler la fonction dhcp, et mettre dhcp dans config/trigger.py) par un @record (penser à importer record depuis trigger/host.py). Une fois le service au point, importer les méthodes "recordées", et la méthode trigger depuis trigger/host.py.
Si c'est un service simple utilisé que par un seul hôte, vous pouvez le mettre directement dans la description de l'hôte dans hosts/nomdelhôte.py. La nomenclature des noms de fonctions et de @record ne change pas.
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
==================
civet est un hôte spécial, qui gère un service spécial : le transcripteur. Le transcripteur est une fonction event, dans trigger/event.py, qui reçoit des messages sur la queue trigger-civet-event. C'est lui qui, fonction des messages reçus, les répartis tous vers les autres queues avec clef de routage.
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.

View file

@ -1,80 +0,0 @@
#!/bin/bash /usr/scripts/python.sh
# -*- coding: utf-8 -*-
#
# Author : Pierre-Elliott Bécue <becue@crans.org>
# License : GPLv3
# Date : 29/04/2014
import argparse
import cranslib.clogger as clogger
import cmb
import cPickle
import socket
import gestion.config.trigger as trigger_config
import gestion.affichage as affichage
import sys
logger = clogger.CLogger("transcriptor", "info")
def process_event(body):
"""
Makes the transcription between the ldap modlist generated
by lc_ldap and sent to the event queue and the message one
have to send to the services.
Example :
{}
"""
class EvenementListener(cmb.AsynchronousConsumer):
"""
Gestionnaire d'événement
"""
def on_message(self, channel, basic_deliver, properties, body):
"""Invoked by pika when a message is delivered from RabbitMQ. The
channel is passed for your convenience. The basic_deliver object that
is passed in carries the exchange, routing key, delivery tag and
a redelivered flag for the message. The properties passed in is an
instance of BasicProperties with the message properties and the body
is the message that was sent.
:param pika.channel.Channel channel: The channel object
:param pika.Spec.Basic.Deliver: basic_deliver method
:param pika.Spec.BasicProperties: properties
:param str|unicode body: The message body
"""
origin = properties.app_id
message_id = properties.message_id
logger.info('Received message # %s from %s: %s',
basic_deliver.delivery_tag, properties.app_id, body)
body = cPickle.loads(body)
process_event(body)
self.acknowledge_message(basic_deliver.delivery_tag)
def run(self):
"""Run the example consumer by connecting to RabbitMQ and then
starting the IOLoop to block and allow the SelectConnection to operate.
"""
logger.info("""Crans Message Broker
+--------------------------------------------+
| Welcome on Transcriptor |
+--------------------------------------------+""")
self._connection = self.connect()
self.add_queue("trigger-event", "trigger.event")
self._connection.ioloop.start()
def daemonize():
listener = EvenementListener(trigger_config.master, "trigger", "topic")
try:
listener.run()
except KeyboardInterrupt:
logger.warning("Caught SIGINT, will now go for shutdown.")
listener.stop()
if __name__ == '__main__':
# Daemonize the trigger app, in order to listen and execute commands from civet.
daemonize()