Correctifs pour le commit précédent, et de quoi tester le chaînage.

This commit is contained in:
Pierre-Elliott Bécue 2015-03-10 20:06:18 +01:00
parent 201377528c
commit f228493399
12 changed files with 99 additions and 16 deletions

View file

@ -81,7 +81,7 @@ def record_service(ack=True):
# The function does not return.
func(*args, **kwargs)
LOGGER.debug("[%r] Ran %r on (%r, %r)", __ob_id, func.func_name, args, kwargs, )
LOGGER.debug("[%r] Ran %r on (%r, %r)", __ob_id, func.func_name, args, kwargs,)
if ack:
# We send directly with routing key trigger.ack on the way.
@ -125,6 +125,7 @@ def chaining(pos):
def add_pos(func):
"""Adds the chaining_pos variable to func"""
LOGGER.debug("%r chaining pos : %r", func.func_name, pos)
setattr(func, "chaining_pos", pos)
return func

View file

@ -13,10 +13,11 @@ This currently is used for mac/IP updates of LDAP database.
"""
import lc_ldap.attributs
from gestion.trigger.host import record_parser
from gestion.trigger.host import record_parser, chaining
@record_parser(lc_ldap.attributs.macAddress.ldap_name, lc_ldap.attributs.ipHostNumber.ldap_name)
def send_mac_ip(ob_id, body, diff):
@chaining(1)
def dhcp(ob_id, body, diff):
"""Computes mac_ip data to send from body and diff
The dict contains lists of tuples, so we can iterate on them

View file

@ -11,9 +11,10 @@ This is the parser for firewall service.
"""
import lc_ldap.attributs
from gestion.trigger.host import record_parser
from gestion.trigger.host import record_parser, chaining
@record_parser(lc_ldap.attributs.macAddress.ldap_name, lc_ldap.attributs.ipHostNumber.ldap_name)
@chaining(0)
def send_mac_ip(ob_id, body, diff):
"""Computes mac_ip data to send from body and diff

View file

@ -0,0 +1,38 @@
#!/bin/bash /usr/scripts/python.sh
# -*- coding: utf-8 -*-
#
# Parser for firewall service.
#
# Author : Pierre-Elliott Bécue <becue@crans.org>
# Licence : GPLv3
# Date : 15/06/2014
"""
This is the parser for firewall service.
"""
import lc_ldap.attributs
from gestion.trigger.host import record_parser, chaining
@record_parser(lc_ldap.attributs.macAddress.ldap_name, lc_ldap.attributs.ipHostNumber.ldap_name)
@chaining(0)
def secours(ob_id, body, diff):
"""Computes mac_ip data to send from body and diff
Body is a couple of two dicts (before, after)
"""
macs = tuple([body[i].get(lc_ldap.attributs.macAddress.ldap_name, [''])[0] for i in xrange(0, 2)])
ips = tuple([body[i].get(lc_ldap.attributs.ipHostNumber.ldap_name, [''])[0] for i in xrange(0, 2)])
# Mise à jour du parefeu mac_ip
if not macs[0]:
# Création d'une nouvelle machine.
fw_dict = {'add': [(macs[1], ips[1])]}
elif not macs[1]:
# Destruction d'une machine.
fw_dict = {'delete': [(macs[0], ips[0])]}
else:
# Mise à jour.
fw_dict = {'update': [(macs[0], ips[0], macs[1], ips[1])]}
return ("secours", ("mac_ip", fw_dict))

View file

@ -19,6 +19,7 @@ import pika
import cranslib.clogger as clogger
# Trigger features
import gestion.secrets_new as secrets
import gestion.config.trigger as trigger_config
logger = clogger.CLogger("trigger", "EventProducer", trigger_config.log_level, trigger_config.debug)

View file

@ -24,7 +24,7 @@ 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 asynchrone, c'est-à-dire qu'il attend et
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
@ -64,9 +64,10 @@ par exemple, pour un parser :
{{{
@record_parser(lc_ldap.attributs.macAddress.ldap_name, lc_ldap.attributs.ipHostNumber.ldap_name)
def send_mac_ip(body, diff):
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
@ -80,6 +81,8 @@ Pour un service, voici un exemple :
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
@ -88,6 +91,7 @@ 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

View file

@ -39,12 +39,11 @@ def ack(ob_id, service_name):
if todo is None:
todo = EventTracker.get_off_record(ob_id)
logger.info("Emptied one list in the chain %r. Trying to continue. Got %r", ob_id, todo)
else:
todo = []
if todo:
for msg in todo:
logger.info("Sending %r on the road \\o/", msg)
# XXX - uncomment this when in production
trigger_send(*msg)
else:
logger.info("Aaaaaand, nothing.")

View file

@ -41,7 +41,7 @@ else:
dhcp_omapi_key = None
ldap_conn = None
@record_service
@record_service()
def dhcp(ob_id, body=None):
"""Regenerates dhcp service taking body into account.

View file

@ -123,7 +123,7 @@ class EventTracker(object):
if dico == True:
return []
if isinstance(bool, dico):
if isinstance(dico, bool):
dico = {}
return [
@ -257,9 +257,10 @@ def event(ob_id, before, after, more):
#In [16]: b
#Out[16]: [('7', 3), (5, 6), ('lol', 'lal'), (3, 'lol')]
functions = list(set([function for function in itertools.chain(*[TriggerFactory.get_parser(key) for key in diff]) if function is not None]))
LOGGER.debug("[%r] in service event, functions are %r.", ob_id, functions)
# Compute the whole list of messages. This returns a list of 2-tuples. We remove None messages, which
# may occur, since there is chained-services.
# should not occcur... But, whatever.
msgs_to_send = [msg for msg in [function(ob_id, (before, after), diff) for function in functions] if msg is not None]
LOGGER.debug("[%r] in service event, messages are %r.", ob_id, msgs_to_send)
@ -278,5 +279,5 @@ def event(ob_id, before, after, more):
def trigger_send(ob_id, routing_key, body):
"""Sends a message via civet/trigger"""
body = tuple([ob_id] + [elem for elem in body])
body = tuple([ob_id] + [body])
PRODUCER.send_message("trigger.%s" % (routing_key,), body)

View file

@ -41,7 +41,7 @@ class FwFactory(object):
def fwrecord(fun):
FwFactory.register(fun.func_name, fun)
@record_service
@record_service()
def firewall(ob_id, body=()):
"""Regens the specific service

View file

@ -0,0 +1,37 @@
#!/bin/bash /usr/scripts/python.sh
# -*- coding: utf-8 -*-
#
# Service in charge of firewall for trigger.
# Contains multiple subservices for each special
# part of firewall.
#
# Author : Pierre-Elliott Bécue <becue@crans.org>
# Licence : GPLv3
# Date : 15/06/2014
"""
Firewall service module. is uses the firewall library as it's, it
is not designed to replace it, just to call specific functions from
it to regenerate what needs to.
"""
import cranslib.clogger as clogger
import gestion.config.trigger as trigger_config
logger = clogger.CLogger("trigger", "secours", trigger_config.log_level, trigger_config.debug)
import lc_ldap.shortcuts
from gestion.trigger.host import record_service
import gestion.trigger.firewall4.firewall4 as firewall4
@record_service()
def secours(ob_id, body=()):
"""Regens the specific service
"""
if len(body) != 2:
logger.warning("Received body %r, this format is incorrect, discarding.", body)
return
(service, data) = body
logger.info("Calling service %s for data %r", service, data)
# XXX - Uncomment when in prod
#FwFactory.get(service)(data)