#!/bin/bash /usr/scripts/python.sh # -*- coding: utf-8 -*- # # Basic trigger host, will be imported from any other # Contains a TriggerFactory, which records the host functions # decorated with @record. # Contains a trigger which calls good functions from factory. # # Author : Pierre-Elliott Bécue # License : GPLv3 # Date : 28/04/2014 """This module provides host functions for trigger, such as the TriggerFactory which stores parsers and services metadata. """ import collections import functools import gestion.config.trigger as trigger_config from gestion.trigger.producer import EventProducer # Clogger import cranslib.clogger as clogger LOGGER = clogger.CLogger("trigger", "host.py/ack", trigger_config.log_level, trigger_config.debug) PRODUCER = EventProducer("trigger.civet") class TriggerFactory(object): """Factory containing which function is part of the trigger set """ _services = {} _parsers = collections.defaultdict(list) @classmethod def register_service(cls, key, value): """Stores the appropriate service in the factory""" cls._services[key] = value @classmethod def get_service(cls, key): """Retrieves the appropriate service""" return cls._services.get(key, None) @classmethod def get_services(cls): """Retrieves the list of all services""" return cls._services.values() @classmethod def register_parser(cls, keys, parser): """Stores the attributes to watch and the function""" for key in keys: cls._parsers[key].append(parser) @classmethod def get_parser(cls, keyword): """Restitutes the parser using keywords""" return cls._parsers[keyword] def record_service(ack=True): """Records in the triggerfactory the function The function provided are services to regen """ def enhance_func(func): """Creates an enhanced function which tests if ack is True and creates an ack if it's the case.""" @functools.wraps(func) def enhanced_func(*args, **kwargs): """Dummy""" # The first arg is ob_id, execpt if kwargs. if args: __ob_id = args[0] else: __ob_id = kwargs['ob_id'] # The function does not return. func(*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. # Thus, ack service does not need any parser. routing_key = "ack" body = (__ob_id, func.func_name) LOGGER.debug("[%r] Ack %r.", __ob_id, body) PRODUCER.send_message("trigger.%s" % (routing_key,), body) TriggerFactory.register_service(func.func_name, enhanced_func) return enhanced_func return enhance_func def trigger_service(what): """Calls the appropriate service""" return TriggerFactory.get_service(what) def record_parser(*args): """Stores the function in TriggerFactory, using args as keys for the dict""" def find_parser(func): """Adds the chaining_pos at the end of the return of functions.""" @functools.wraps(func) def enhanced_func(*args, **kwargs): """dummy""" __ob_id = args[0] ret = func(*args, **kwargs) LOGGER.debug("[%r] In record_parser.find_parser, ran %r(%r, %r). Got %r.", __ob_id, func.func_name, args, kwargs, ret) if ret is not None: ret = [elem for elem in ret] + [getattr(func, "chaining_pos", 0)] LOGGER.debug("[%r] In record_parser.find_parser, for %r got chaining_pos %r", __ob_id, func.func_name, ret[-1]) return ret TriggerFactory.register_parser(args, enhanced_func) return enhanced_func return find_parser def chaining(pos): """Allows chaining of operations, by adding a position marker on the function.""" def add_pos(func): """Adds the chaining_pos variable to func""" setattr(func, "chaining_pos", pos) return func return add_pos