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

@ -23,7 +23,7 @@ services = {
'dhcp' : ["dhcp"], 'dhcp' : ["dhcp"],
'dyson' : ["autostatus"], 'dyson' : ["autostatus"],
'isc' : ["dhcp"], 'isc' : ["dhcp"],
'komaz' : ["firewall", "secours"], 'odlyd' : ["firewall", "secours"],
'owl' : ["users"], 'owl' : ["users"],
'redisdead' : ["mailman", "modif_ldap", "solde", "users", "secours"], 'redisdead' : ["mailman", "modif_ldap", "solde", "users", "secours"],
'sable' : ["dns"], 'sable' : ["dns"],
@ -35,4 +35,4 @@ services = {
# XXX - Uncomment this when in prod # XXX - Uncomment this when in prod
#all_services = set([service for service in itertools.chain(*services.values())]) #all_services = set([service for service in itertools.chain(*services.values())])
all_services = ['dhcp', 'firewall'] all_services = ['dhcp', 'firewall', 'secours']

View file

@ -125,6 +125,7 @@ def chaining(pos):
def add_pos(func): def add_pos(func):
"""Adds the chaining_pos variable to func""" """Adds the chaining_pos variable to func"""
LOGGER.debug("%r chaining pos : %r", func.func_name, pos)
setattr(func, "chaining_pos", pos) setattr(func, "chaining_pos", pos)
return func return func

View file

@ -13,10 +13,11 @@ This currently is used for mac/IP updates of LDAP database.
""" """
import lc_ldap.attributs 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) @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 """Computes mac_ip data to send from body and diff
The dict contains lists of tuples, so we can iterate on them 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 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) @record_parser(lc_ldap.attributs.macAddress.ldap_name, lc_ldap.attributs.ipHostNumber.ldap_name)
@chaining(0)
def send_mac_ip(ob_id, body, diff): def send_mac_ip(ob_id, body, diff):
"""Computes mac_ip data to send from body and 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 import cranslib.clogger as clogger
# Trigger features # Trigger features
import gestion.secrets_new as secrets
import gestion.config.trigger as trigger_config import gestion.config.trigger as trigger_config
logger = clogger.CLogger("trigger", "EventProducer", trigger_config.log_level, trigger_config.debug) 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. Tous les fichiers sont renseignés depuis /usr/scripts.
* gestion/trigger/trigger.py est un fichier python qui importe un consumer de * 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 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 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 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) @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é 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 à 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 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): 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 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 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 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 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 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. 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 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 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: if todo is None:
todo = EventTracker.get_off_record(ob_id) todo = EventTracker.get_off_record(ob_id)
logger.info("Emptied one list in the chain %r. Trying to continue. Got %r", ob_id, todo) logger.info("Emptied one list in the chain %r. Trying to continue. Got %r", ob_id, todo)
else:
todo = []
if todo: if todo:
for msg in todo: for msg in todo:
logger.info("Sending %r on the road \\o/", msg) logger.info("Sending %r on the road \\o/", msg)
# XXX - uncomment this when in production # XXX - uncomment this when in production
trigger_send(*msg) trigger_send(*msg)
else:
logger.info("Aaaaaand, nothing.")

View file

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

View file

@ -123,7 +123,7 @@ class EventTracker(object):
if dico == True: if dico == True:
return [] return []
if isinstance(bool, dico): if isinstance(dico, bool):
dico = {} dico = {}
return [ return [
@ -257,9 +257,10 @@ def event(ob_id, before, after, more):
#In [16]: b #In [16]: b
#Out[16]: [('7', 3), (5, 6), ('lol', 'lal'), (3, 'lol')] #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])) 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 # 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] 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) 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): def trigger_send(ob_id, routing_key, body):
"""Sends a message via civet/trigger""" """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) PRODUCER.send_message("trigger.%s" % (routing_key,), body)

View file

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