service.py 3.1 KB
Newer Older
1 2 3 4 5 6 7 8
#!/bin/bash /usr/scripts/python.sh
# -*- coding: utf-8 -*-

"""
This module provides a basic service class to other services. It should *NOT*
be referenced in configuration of trigger.
"""

9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
import collections

import cranslib.clogger as clogger
import gestion.config.trigger as trigger_config
from gestion.trigger.host import TriggerFactory

logger = clogger.CLogger("trigger", "service", "debug", trigger_config.debug)

class MetaService(type):
    """Metaclass designed to handle all services.

    """

    def __new__(mcs, cname, cpar, cattrs):
        """Method producing the new class itself
        At first, I wanted to put the changes_trigger modification in __new__,
        using direct modification of cattrs['changes_trigger'] by pointing the
        required methods (classmethods). The problem was that these methods were
        bound at the return of type.__new__, for a reason I could not exactly
        explain.

        I found a workaround using __init__, so the point would be to remove
        __new__, and directly use type.__new__, but this comment seems useful,
        so __new__ will survive.

        """
        return super(MetaService, mcs).__new__(mcs, cname, cpar, cattrs)

    def __init__(cls, cname, cpar, cattrs):
        """Used to register the generated classes in TriggerFactory, and modify the behavior of
        changes_trigger by pointing functions instead of their names. This allows to cancel any
        positional requirement in class definition.

        Do NEVER return something in __init__ function.

        """
        if not cname == "BasicService":
            TriggerFactory.register(cname.lower(), cls)
        changes_trigger = collections.defaultdict(list)
        # I love getattr
        text_changes_trigger = getattr(cls, "changes_trigger", {})
        for (ldap_attr_name, funcs_name) in text_changes_trigger.items():
            for func_name in funcs_name:
                # I really love getattr.
                get = getattr(cls, func_name, None)
                if get is None:
                    logger.critical("Fatal, bad function (%r) reference in %r.", func_name, cname)
                    continue
                changes_trigger[ldap_attr_name].append(get)
        setattr(cls, "changes_trigger", changes_trigger)
        super(MetaService, cls).__init__(cname, cpar, cattrs)

61 62 63 64 65
class BasicService(object):
    """Basic service handler. Other services should inherit fron this one.

    """

66 67
    __metaclass__ = MetaService

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
    changes_trigger = {}

    @classmethod
    def get_changes(cls, body, diff):
        """Looks for changes and creates messages to send back

        """
        # list of all messages to send.
        msg_list = []

        # lists all functions to call
        func_list = set()
        for (attrib, functions) in cls.changes_trigger.iteritems():
            if attrib in diff:
                func_list.update(functions)
        for function in func_list:
            msg_list.append(function(body, diff))
        return msg_list

    @classmethod
    def regen(cls, body):
        """This method is referenced to avoid uncaught exceptions

        """
        pass