From 091a2d161ed3832dee17ef55b4714c86575769b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Elliott=20B=C3=A9cue?= Date: Thu, 31 Jul 2014 11:50:47 +0200 Subject: [PATCH] [trigger] Going back to simplified version --- gestion/config/trigger.py | 1 + gestion/trigger/host.py | 43 +++- gestion/trigger/services/dhcp.py | 322 ++++++++++++--------------- gestion/trigger/services/event.py | 95 ++++---- gestion/trigger/services/firewall.py | 108 ++++----- gestion/trigger/trigger.py | 10 +- 6 files changed, 287 insertions(+), 292 deletions(-) diff --git a/gestion/config/trigger.py b/gestion/config/trigger.py index 2f748112..38b370d8 100644 --- a/gestion/config/trigger.py +++ b/gestion/config/trigger.py @@ -7,6 +7,7 @@ import itertools debug = True +log_level = "info" # Serveur maître master = "rabbitmq.adm.crans.org" diff --git a/gestion/trigger/host.py b/gestion/trigger/host.py index 067c66e9..7df75e66 100644 --- a/gestion/trigger/host.py +++ b/gestion/trigger/host.py @@ -10,27 +10,50 @@ # License : GPLv3 # Date : 28/04/2014 +import collections + class TriggerFactory(object): """Factory containing which function is part of the trigger set """ - _meths = {} + _services = {} + _parsers = collections.defaultdict(list) @classmethod - def register(cls, key, value): - cls._meths[key] = value + def register_service(cls, key, value): + cls._services[key] = value @classmethod - def get(cls, key): - return cls._meths.get(key, None) + def get_service(cls, key): + return cls._services.get(key, None) @classmethod def get_services(cls): - return cls._meths.values() + return cls._services.values() -def record(cls): - TriggerFactory.register(cls.__name__.lower(), cls) + @classmethod + def register_parser(cls, keys, parser): + for key in keys: + cls._parsers[key].append(parser) -def trigger(what): - return TriggerFactory.get(what) + @classmethod + def get_parser(cls, keyword): + return cls._parsers[keyword] + +def record_service(func): + """Records in the triggerfactory the function + + The function provided are services to regen + + """ + TriggerFactory.register_service(func.func_name, func) + +def trigger_service(what): + return TriggerFactory.get_service(what) + +def record_parser(*args): + def find_parser(func): + TriggerFactory.register_parser(args, func) + return func + return find_parser diff --git a/gestion/trigger/services/dhcp.py b/gestion/trigger/services/dhcp.py index b9d07a98..9b012a9f 100644 --- a/gestion/trigger/services/dhcp.py +++ b/gestion/trigger/services/dhcp.py @@ -18,212 +18,186 @@ import struct import gestion.config.trigger as trigger_config import cranslib.clogger as clogger -logger = clogger.CLogger("trigger", "dhcp", "debug", trigger_config.debug) +logger = clogger.CLogger("trigger", "dhcp", trigger_config.log_level, trigger_config.debug) -hostname = socket.gethostname().split(".")[0] + ".adm.crans.org" +hostname = socket.gethostname().split(".")[0] +hostname_adm = hostname + ".adm.crans.org" import lc_ldap.shortcuts -from gestion.trigger.services.service import BasicService from cranslib.conffile import ConfFile import gestion.config.dhcp as dhcp_config import gestion.secrets_new as secrets_new import gestion.affichage as affichage import gestion.iptools as iptools -from gestion.trigger.pypureomapi import pack_ip, pack_mac, OMAPI_OP_UPDATE -from gestion.trigger.pypureomapi import Omapi, OmapiMessage - - -class Dhcp(BasicService): - """Class responsible of dhcp service. - - """ - - # Class lookup table to define which changes call which function. - changes_trigger = { - lc_ldap.attributs.macAddress.ldap_name: ('send_mac_ip',), - lc_ldap.attributs.ipHostNumber.ldap_name: ('send_mac_ip',), - } +from gestion.trigger.pypureomapi import pack_ip, pack_mac, OMAPI_OP_UPDATE, Omapi, OmapiMessage +from gestion.trigger.host import record_service, record_parser, TriggerFactory +if "dhcp" in trigger_config.services[hostname]: + dhcp_omapi_keyname = secrets_new.get("dhcp_omapi_keyname") + dhcp_omapi_key = secrets_new.get("dhcp_omapi_keys")[hostname_adm] + ldap_conn = lc_ldap.shortcuts.lc_ldap_readonly() +else: dhcp_omapi_keyname = None dhcp_omapi_key = None ldap_conn = None - @classmethod - def send_mac_ip(cls, body, diff): - """Computes mac_ip data to send from body and diff +@record_parser(lc_ldap.attributs.macAddress.ldap_name, lc_ldap.attributs.ipHostNumber.ldap_name) +def send_mac_ip(body, diff): + """Computes mac_ip data to send from body and diff - """ - macs = tuple([body[i].get(lc_ldap.attributs.macAddress.ldap_name, [''])[0] for i in xrange(1, 3)]) - ips = tuple([body[i].get(lc_ldap.attributs.ipHostNumber.ldap_name, [''])[0] for i in xrange(1, 3)]) - hostnames = tuple([body[i].get(lc_ldap.attributs.host.ldap_name, [''])[0] for i in xrange(1, 3)]) + """ + macs = tuple([body[i].get(lc_ldap.attributs.macAddress.ldap_name, [''])[0] for i in xrange(1, 3)]) + ips = tuple([body[i].get(lc_ldap.attributs.ipHostNumber.ldap_name, [''])[0] for i in xrange(1, 3)]) + hostnames = tuple([body[i].get(lc_ldap.attributs.host.ldap_name, [''])[0] for i in xrange(1, 3)]) - # Régénération du DHCP : - if not macs[0]: - # Création d'une nouvelle machine. - dhcp_dict = {'add': [(macs[1], ips[1], hostnames[1])]} - elif not macs[1]: - # Destruction d'une machine. - dhcp_dict = {'delete': [(macs[0], ips[0])]} - else: - # Mise à jour. - dhcp_dict = {'update': [(macs[0], ips[0], macs[1], ips[1], hostnames[1])]} - return ("dhcp", dhcp_dict) + # Régénération du DHCP : + if not macs[0]: + # Création d'une nouvelle machine. + dhcp_dict = {'add': [(macs[1], ips[1], hostnames[1])]} + elif not macs[1]: + # Destruction d'une machine. + dhcp_dict = {'delete': [(macs[0], ips[0])]} + else: + # Mise à jour. + dhcp_dict = {'update': [(macs[0], ips[0], macs[1], ips[1], hostnames[1])]} + return ("dhcp", dhcp_dict) - @classmethod - def regen(cls, body=None): - """Regenerates dhcp service taking body into account. +@record_service +def dhcp(body=None): + """Regenerates dhcp service taking body into account. - """ - cls.check_params() + """ - # http://satyajit.ranjeev.in/2012/01/12/python--dangerous-default-value-as-argument.html - # dict are referenced. - if body is None: - body = {} + # http://satyajit.ranjeev.in/2012/01/12/python--dangerous-default-value-as-argument.html + # dict are referenced. + if body is None: + body = {} - if body and isinstance(body, dict): - for (mac, ip, name) in body.get("add", []): - logger.info("Updating DHCP db by adding %s, %s, %s", mac, ip, name) - # XXX - Uncommend this when we need to start prod - # cls.add_dhcp_host(mac, ip, name) - for (mac, ip) in body.get("delete", []): - logger.info("Updating DHCP db by deleting %s, %s", mac, ip) - # XXX - Uncommend this when we need to start prod - # cls.delete_dhcp_host(mac, ip) - for (rmac, rip, mac, ip, name) in body.get("update", []): - logger.info("Updating DHCP db by modifying %s, %s to %s, %s, %s", rmac, rip, mac, ip, name) - # XXX - Uncommend this when we need to start prod - # cls.delete_dhcp_host(rmac, rip) - # cls.add_dhcp_host(mac, ip, name) - elif body == True: - hosts = {} - host_template = """ - host %(nom)s { - hardware ethernet %(mac)s; - fixed-address %(ip)s; - option host-name "%(host)s"; - } + if body and isinstance(body, dict): + for (mac, ip, name) in body.get("add", []): + logger.info("Updating DHCP db by adding %s, %s, %s", mac, ip, name) + # XXX - Uncommend this when we need to start prod + # add_dhcp_host(mac, ip, name) + for (mac, ip) in body.get("delete", []): + logger.info("Updating DHCP db by deleting %s, %s", mac, ip) + # XXX - Uncommend this when we need to start prod + # delete_dhcp_host(mac, ip) + for (rmac, rip, mac, ip, name) in body.get("update", []): + logger.info("Updating DHCP db by modifying %s, %s to %s, %s, %s", rmac, rip, mac, ip, name) + # XXX - Uncommend this when we need to start prod + # delete_dhcp_host(rmac, rip) + # add_dhcp_host(mac, ip, name) + elif body == True: + hosts = {} + host_template = """ +host %(nom)s { + hardware ethernet %(mac)s; + fixed-address %(ip)s; + option host-name "%(host)s"; +} """ - affichage.prettyDoin("Chargement des machines", "...") - machines = cls.ldap_conn.allMachines() - affichage.prettyDoin("Chargement des machines", "Ok") - animation = affichage.Animation(texte="Génération de la configuration", - nb_cycles=len(machines), - couleur=True, - kikoo=True) + affichage.prettyDoin("Chargement des machines", "...") + machines = ldap_conn.allMachines() + affichage.prettyDoin("Chargement des machines", "Ok") + animation = affichage.Animation(texte="Génération de la configuration", + nb_cycles=len(machines), + couleur=True, + kikoo=True) - for machine in machines: - for net in dhcp_config.reseaux.keys(): - ip = str(machine['ipHostNumber'][0]) - mac = str(machine['macAddress'][0]) - nom = str(machine['host'][0]) - if '' not in [ip, mac] and iptools.AddrInNet(ip, net): - d = {'nom' : nom, - 'host' : nom.split(".", 1)[0], - 'mac' : mac, - 'ip' : ip, - } - try: - hosts[net] += host_template % d - except: - hosts[net] = host_template % d - animation.new_step() - # Put a \n after the last iteration. - animation.end() + for machine in machines: + for net in dhcp_config.reseaux.keys(): + ip = str(machine['ipHostNumber'][0]) + mac = str(machine['macAddress'][0]) + nom = str(machine['host'][0]) + if '' not in [ip, mac] and iptools.AddrInNet(ip, net): + d = {'nom' : nom, + 'host' : nom.split(".", 1)[0], + 'mac' : mac, + 'ip' : ip, + } + try: + hosts[net] += host_template % d + except: + hosts[net] = host_template % d + animation.new_step() + # Put a \n after the last iteration. + animation.end() - step = "Enregistrement de la configuration dans les fichiers" - affichage.prettyDoin(step, "...") - for (net, fichier) in dhcp_config.reseaux.items(): - with ConfFile(fichier) as configFile: - configFile.header("#") - if hosts.has_key(net): - configFile.write(hosts[net]) + step = "Enregistrement de la configuration dans les fichiers" + affichage.prettyDoin(step, "...") + for (net, fichier) in dhcp_config.reseaux.items(): + with ConfFile(fichier) as configFile: + configFile.header("#") + if hosts.has_key(net): + configFile.write(hosts[net]) + affichage.prettyDoin(step, "Ok") + + step = "Nettoyage des fichiers de leases" + affichage.prettyDoin(step, "...") + try: + lease_clean() affichage.prettyDoin(step, "Ok") + except: + affichage.prettyDoin(step, "Erreur") + print "During lease clean, an error occured." + raise - step = "Nettoyage des fichiers de leases" - affichage.prettyDoin(step, "...") - try: - cls.lease_clean() - affichage.prettyDoin(step, "Ok") - except: - affichage.prettyDoin(step, "Erreur") - print "During lease clean, an error occured." - raise - @classmethod - def check_params(cls): - """This method allows lazy evaluation for dhcp_omapi_keyname - and dhcp_omapi_key, since event imports all services. This is actually - the best lazy eval we can hope, since property won't work on - classmethods. +def add_dhcp_host(mac, ip, name=None): + """Adds a dhcp host using omapi - """ - if cls.dhcp_omapi_keyname is None: - cls.dhcp_omapi_keyname = secrets_new.get("dhcp_omapi_keyname") - if cls.dhcp_omapi_key is None: - cls.dhcp_omapi_key = secrets_new.get("dhcp_omapi_keys")[hostname] - if cls.ldap_conn is None: - cls.ldap_conn = lc_ldap.shortcuts.lc_ldap_readonly() + """ - @classmethod - def add_dhcp_host(cls, mac, ip, name=None): - """Adds a dhcp host using omapi + if '' in [ip, mac]: + return + msg = OmapiMessage.open(b"host") + msg.message.append((b"create", struct.pack("!I", 1))) + msg.message.append((b"exclusive", struct.pack("!I", 1))) + msg.obj.append((b"hardware-address", pack_mac(mac))) + msg.obj.append((b"hardware-type", struct.pack("!I", 1))) + msg.obj.append((b"ip-address", pack_ip(ip))) + if name: + msg.obj.append((b"name", bytes(name))) + conn = Omapi(hostname_adm, 9991, dhcp_omapi_keyname, dhcp_omapi_key) + _ = conn.query_server(msg) + conn.close() - """ - cls.check_params() - if '' in [ip, mac]: - return - msg = OmapiMessage.open(b"host") - msg.message.append((b"create", struct.pack("!I", 1))) - msg.message.append((b"exclusive", struct.pack("!I", 1))) - msg.obj.append((b"hardware-address", pack_mac(mac))) - msg.obj.append((b"hardware-type", struct.pack("!I", 1))) - msg.obj.append((b"ip-address", pack_ip(ip))) - if name: - msg.obj.append((b"name", bytes(name))) - conn = Omapi(hostname, 9991, cls.dhcp_omapi_keyname, cls.dhcp_omapi_key) - _ = conn.query_server(msg) - conn.close() +def delete_dhcp_host(mac, ip): + """Deletes dhcp host using omapi - @classmethod - def delete_dhcp_host(cls, mac, ip): - """Deletes dhcp host using omapi + """ - """ - cls.check_params() + if '' in [ip, mac]: + return + msg = OmapiMessage.open(b"host") + msg.obj.append((b"hardware-address", pack_mac(mac))) + msg.obj.append((b"hardware-type", struct.pack("!I", 1))) + msg.obj.append((b"ip-address", pack_ip(ip))) + conn = Omapi(hostname_adm, 9991, dhcp_omapi_keyname, dhcp_omapi_key) + response = conn.query_server(msg) + if response.opcode == OMAPI_OP_UPDATE: + _ = conn.query_server(OmapiMessage.delete(response.handle)) + conn.close() - if '' in [ip, mac]: - return - msg = OmapiMessage.open(b"host") - msg.obj.append((b"hardware-address", pack_mac(mac))) - msg.obj.append((b"hardware-type", struct.pack("!I", 1))) - msg.obj.append((b"ip-address", pack_ip(ip))) - conn = Omapi(hostname, 9991, cls.dhcp_omapi_keyname, cls.dhcp_omapi_key) - response = conn.query_server(msg) - if response.opcode == OMAPI_OP_UPDATE: - _ = conn.query_server(OmapiMessage.delete(response.handle)) - conn.close() - @staticmethod - def lease_clean(): - """Clean the lease file +def lease_clean(): + """Clean the lease file - """ - # TODO : use ConfigFile structure - leasefile = open(dhcp_config.dhcplease) - newleasefile = open(dhcp_config.dhcplease + '.new', 'w') + """ + # TODO : use ConfigFile structure + leasefile = open(dhcp_config.dhcplease) + newleasefile = open(dhcp_config.dhcplease + '.new', 'w') + line = leasefile.readline() + write = True + while line: + if line.strip().startswith('host'): + write = False + if write: + newleasefile.write(line) + if not write and line.strip().endswith('}'): + write = True line = leasefile.readline() - write = True - while line: - if line.strip().startswith('host'): - write = False - if write: - newleasefile.write(line) - if not write and line.strip().endswith('}'): - write = True - line = leasefile.readline() - leasefile.close() - newleasefile.close() - os.rename(dhcp_config.dhcplease+'.new', dhcp_config.dhcplease) - + leasefile.close() + newleasefile.close() + os.rename(dhcp_config.dhcplease+'.new', dhcp_config.dhcplease) diff --git a/gestion/trigger/services/event.py b/gestion/trigger/services/event.py index 81360262..24bd373a 100644 --- a/gestion/trigger/services/event.py +++ b/gestion/trigger/services/event.py @@ -21,10 +21,10 @@ import itertools import traceback import gestion.secrets_new as secrets + # Trigger features import gestion.config.trigger as trigger_config -from gestion.trigger.host import TriggerFactory -from gestion.trigger.services.service import BasicService +from gestion.trigger.host import TriggerFactory, record_service, record_parser # Clogger import cranslib.clogger as clogger @@ -32,7 +32,7 @@ import cranslib.clogger as clogger # lc_ldap import lc_ldap.attributs -logger = clogger.CLogger("trigger", "event", "debug", trigger_config.debug) +logger = clogger.CLogger("trigger", "event", trigger_config.log_level, trigger_config.debug) services = [] for config_service in trigger_config.all_services: @@ -136,63 +136,52 @@ def compare_lists(list1, list2): return moins, plus -class Event(BasicService): - """Event service class. It extends BasicService, but should not implement - any change trigger, since it's this service which is designed to call - change triggers of other services. + +@record_service +def event(body=()): + """When any event arrives on trigger-civet-event, this method is called + and designed to transcript the body (ldap data) in something usable for + the services. Afterwards, it sends these transcripts on the good way + using routing_key. + + body is a 3-tuple, containing LDAP dn, the former state of the object + (a simple dict), and the later state. The data are non-binding-dependant. + + A new object has body[1] to None, a deleted one has body[2] to None. """ - @classmethod - def get_changes(cls, body, diff): - """Compute changes from diff""" + logger.info("Received message %r…", body) - return [None] + diff = diff_o_matic(body) - @classmethod - def regen(cls, body=()): - """When any event arrives on trigger-civet-event, this method is called - and designed to transcript the body (ldap data) in something usable for - the services. Afterwards, it sends these transcripts on the good way - using routing_key. + # Now, diff is a dict containing attributes which has been modified. + # diff['macAddress'] could look like (['aa:bb:cc:dd:ee:fg'], ['aa:bb:cc:dd:ee:ff']), + # where the list on the left is the former value of attributes, and the list on the + # right the latter values. - body is a 3-tuple, containing LDAP dn, the former state of the object - (a simple dict), and the later state. The data are non-binding-dependant. + # -*- Explain -*- + #In [11]: import itertools + # + #In [12]: a = [[(3, 'lol'), ('7', 3)], [(5, 6), None], [None], [('lol', 'lal')]] + # + #In [13]: a + #Out[13]: [[(3, 'lol'), ('7', 3)], [(5, 6), None], [None], [('lol', 'lal')]] + # + #In [14]: list(set([message for message in itertools.chain(*a)])) + #Out[14]: [('7', 3), (5, 6), None, ('lol', 'lal'), (3, 'lol')] # Only one None from a, since [None, x, y, None] is equivalent for itertools to [x, y] + # + #In [15]: b = list(set([message for message in itertools.chain(*a) if message is not None])) + # + #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])])) + msg_to_send = [function(body, diff) for function in functions] - A new object has body[1] to None, a deleted one has body[2] to None. - - """ - - logger.info("Received message %r…", body) - - diff = diff_o_matic(body) - - # Now, diff is a dict containing attributes which has been modified. - # diff['macAddress'] could look like (['aa:bb:cc:dd:ee:fg'], ['aa:bb:cc:dd:ee:ff']), - # where the list on the left is the former value of attributes, and the list on the - # right the latter values. - - # -*- Explain -*- - #In [11]: import itertools - # - #In [12]: a = [[(3, 'lol'), ('7', 3)], [(5, 6), None], [None], [('lol', 'lal')]] - # - #In [13]: a - #Out[13]: [[(3, 'lol'), ('7', 3)], [(5, 6), None], [None], [('lol', 'lal')]] - # - #In [14]: list(set([message for message in itertools.chain(*a)])) - #Out[14]: [('7', 3), (5, 6), None, ('lol', 'lal'), (3, 'lol')] # Only one None from a, since [None, x, y, None] is equivalent for itertools to [x, y] - # - #In [15]: b = list(set([message for message in itertools.chain(*a) if message is not None])) - # - #In [16]: b - #Out[16]: [('7', 3), (5, 6), ('lol', 'lal'), (3, 'lol')] - msg_to_send = [message for message in itertools.chain(*[service.get_changes(body, diff) for service in TriggerFactory.get_services()]) if message is not None] - - for msg in msg_to_send: - logger.info("Sending %r on the road \\o/", msg) - # XXX - uncomment this when in production - # trigger_send(*msg) + for msg in msg_to_send: + logger.info("Sending %r on the road \\o/", msg) + # XXX - uncomment this when in production + trigger_send(*msg) def trigger_send(routing_key, body): sender = EventProducer("civet") diff --git a/gestion/trigger/services/firewall.py b/gestion/trigger/services/firewall.py index fd4332dc..624a4863 100644 --- a/gestion/trigger/services/firewall.py +++ b/gestion/trigger/services/firewall.py @@ -16,67 +16,75 @@ it to regenerate what needs to. import cranslib.clogger as clogger import gestion.config.trigger as trigger_config -logger = clogger.CLogger("trigger", "firewall", "debug", trigger_config.debug) +logger = clogger.CLogger("trigger", "firewall", trigger_config.log_level, trigger_config.debug) import lc_ldap.shortcuts -from gestion.trigger.services.service import BasicService +from gestion.trigger.host import record_service, record_parser import gestion.trigger.firewall4.firewall4 as firewall4 -class Firewall(BasicService): - """Firewall service that handles any modification in the firewall. +class FwFactory(object): + """Records firewall functions, and provide them. """ - # Class lookup table to define which changes call which function. - changes_trigger = { - lc_ldap.attributs.macAddress.ldap_name: ('send_mac_ip',), - lc_ldap.attributs.ipHostNumber.ldap_name: ('send_mac_ip',), - } + _fwfuns = {} @classmethod - def send_mac_ip(cls, body, diff): - """Computes mac_ip data to send from body and diff - - """ - macs = tuple([body[i].get(lc_ldap.attributs.macAddress.ldap_name, [''])[0] for i in xrange(1, 3)]) - ips = tuple([body[i].get(lc_ldap.attributs.ipHostNumber.ldap_name, [''])[0] for i in xrange(1, 3)]) - - # Mise à jour du parefeu mac_ip - if not macs[0]: - # Création d'une nouvelle machine. - fw = {'add': [(macs[1], ips[1])]} - elif not macs[1]: - # Destruction d'une machine. - fw = {'delete': [(macs[0], ips[0])]} - else: - # Mise à jour. - fw = {'update': [(macs[0], ips[0], macs[1], ips[1])]} - return ("firewall", ("mac_ip", fw)) + def register(cls, key, value): + cls._fwfuns[key] = value @classmethod - def regen(cls, body=()): - """Regens the specific service + def get(cls, key): + return cls._fwfuns.get(key, None) - """ - 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) - getattr(cls, service)(data) +def fwrecord(fun): + FwFactory.register(fun.func_name, fun) - @classmethod - def mac_ip(cls, body): - host_fw = firewall4.firewall() - if body and isinstance(body, dict): - for (mac, ip) in body.get("add", []): - logger.info("Adding mac_ip %s,%s", mac, ip) - host_fw.mac_ip_append(mac, ip) - for (mac, ip) in body.get("delete", []): - logger.info("Removing mac_ip %s,%s", mac, ip) - host_fw.mac_ip_remove(mac, ip) - for (rmac, rip, mac, ip) in body.get("update", []): - logger.info("Updating mac_ip %s,%s with %s,%s", rmac, rip, mac, ip) - host_fw.mac_ip_remove(rmac, rip) - host_fw.mac_ip_append(mac, ip) +@record_parser(lc_ldap.attributs.macAddress.ldap_name, lc_ldap.attributs.ipHostNumber.ldap_name) +def send_mac_ip(body, diff): + """Computes mac_ip data to send from body and diff + + """ + macs = tuple([body[i].get(lc_ldap.attributs.macAddress.ldap_name, [''])[0] for i in xrange(1, 3)]) + ips = tuple([body[i].get(lc_ldap.attributs.ipHostNumber.ldap_name, [''])[0] for i in xrange(1, 3)]) + + # Mise à jour du parefeu mac_ip + if not macs[0]: + # Création d'une nouvelle machine. + fw = {'add': [(macs[1], ips[1])]} + elif not macs[1]: + # Destruction d'une machine. + fw = {'delete': [(macs[0], ips[0])]} + else: + # Mise à jour. + fw = {'update': [(macs[0], ips[0], macs[1], ips[1])]} + return ("firewall", ("mac_ip", fw)) + +@record_service +def firewall(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) + +@fwrecord +def mac_ip(body): + host_fw = firewall4.firewall() + if body and isinstance(body, dict): + for (mac, ip) in body.get("add", []): + logger.info("Adding mac_ip %s,%s", mac, ip) + host_fw.mac_ip_append(mac, ip) + for (mac, ip) in body.get("delete", []): + logger.info("Removing mac_ip %s,%s", mac, ip) + host_fw.mac_ip_remove(mac, ip) + for (rmac, rip, mac, ip) in body.get("update", []): + logger.info("Updating mac_ip %s,%s with %s,%s", rmac, rip, mac, ip) + host_fw.mac_ip_remove(rmac, rip) + host_fw.mac_ip_append(mac, ip) diff --git a/gestion/trigger/trigger.py b/gestion/trigger/trigger.py index 6c055207..5e7a6f65 100755 --- a/gestion/trigger/trigger.py +++ b/gestion/trigger/trigger.py @@ -20,12 +20,12 @@ import pika import gestion.secrets_new as secrets import gestion.config.trigger as trigger_config import gestion.affichage as affichage -from gestion.trigger.host import trigger +from gestion.trigger.host import trigger_service import cranslib.clogger as clogger import cmb hostname = socket.gethostname().split(".")[0] -logger = clogger.CLogger("trigger", "trigger", "info", trigger_config.debug) +logger = clogger.CLogger("trigger", "trigger", trigger_config.log_level, trigger_config.debug) # Ce bloc contient le peu de "magie" de la librairie, on utilise les services listés dans config/trigger.py # comme référence. Pour éviter toute redondance, la commande importe donc les services utiles suivant cette @@ -70,7 +70,7 @@ class EvenementListener(cmb.AsynchronousConsumer): # about contient le nom de la fonction à appeler, body lui est filé en argument. try: if about in trigger_config.services[hostname]: - trigger(about).regen(body) + trigger_service(about)(body) else: raise AttributeError except AttributeError: @@ -122,7 +122,7 @@ if __name__ == '__main__': for host_service in trigger_config.services[hostname]: try: print affichage.style(" (Ré)Génération du service %s" % (host_service,), "cyan") - trigger(host_service).regen(True) + trigger_service(host_service)(True) except AttributeError: print "No suitable trigger handle found for service %s on host %s" % (host_service, hostname) elif args.daemon: @@ -133,4 +133,4 @@ if __name__ == '__main__': for arg_service in trigger_config.services[hostname]: if getattr(args, arg_service, False) == True: print affichage.style(" (Ré)Génération du service %s" % (arg_service,), "cyan") - trigger(arg_service).regen(True) + trigger_service(arg_service)(True)