#!/bin/bash /usr/scripts/python.sh
# -*- coding: utf-8 -*-

# Copyright (C) Frédéric Pauget
# Licence : GPLv2

USAGE = \
"""Ce script permet de lancer la reconfiguration des divers services

Usage: %(prog)s options
Les options possibles sont :
\t%(options)s
Les options avec = doivent être suivies d'un argument. Plusieurs
arguments peuvent être founis pour une même option, les séparer par &
"""

import sys, signal, os, getopt
from trigger import trigger_generate as trigger

sys.path.append('/usr/scripts/gestion')
if '/usr/scripts' not in sys.path:
    sys.path.append('/usr/scripts')

from gestion.ldap_crans import crans_ldap, hostname
from lock import *
from affich_tools import anim, cprint, OK
from time import localtime, strftime, time, sleep
import ridtools
from inspect import getargspec
from syslog import *
import platform
openlog("generate")

db = crans_ldap()
make_lock('auto_generate', 'Big lock', nowait=1)

class base_reconfigure:
    try:
        sys.path.append('/etc/crans/')
        from services import services as __services
        sys.path.pop()
        __firewalled_servers = __services.get('firewall', [])
        __blacklist_servers = [ _s + '-blacklist' for _s in  __firewalled_servers ]
        __service_develop = {
          'macip': [ _s + '-macip' for _s in  __firewalled_servers ],
#          'droits': [ 'rouge-droits', 'ragnarok-droits' ],
          'blacklist': __blacklist_servers,
          'bl_chbre_invalide': __blacklist_servers,
          'blacklist_mail_invalide': __blacklist_servers,
          'blacklist_virus': __blacklist_servers,
          'blacklist_warez': __blacklist_servers,
          'blacklist_ipv6_ra': __blacklist_servers,
          'blacklist_upload': __blacklist_servers,
          'blacklist_autodisc_upload': __blacklist_servers,
          'blacklist_bloq': __blacklist_servers,
          'del_user': [ 'zbee-del_user', 'owl-del_user', 'zamok-del_user' ],
          'port': ['%s-port' % _s for _s in __services.get('connection-main', [])],
          'dhcp': [ "%s-dhcp" % _s for _s in __services.get('isc-dhcp-server', []) ],
        }
    #Y R U Aliasing !
        __service_develop.update({
          'mail_invalide':__service_develop['blacklist_mail_invalide'],
          'virus':__service_develop['blacklist_virus'],
          'warez':__service_develop['blacklist_warez'],
          'ipv6_ra':__service_develop['blacklist_ipv6_ra'],
          'upload': __service_develop['blacklist_upload'],
          'autodisc_upload': __service_develop['blacklist_autodisc_upload'],
          'bloq': __service_develop['blacklist_bloq'],
        })
    except ImportError:
       __service_develop = {}

    def __init__(self, to_do=None):

        # On vérifie que l'on est root
        if os.getuid() != 0:
            sys.stderr.write("Il faut être root\n")
            sys.exit(1)

        if not to_do:
            if debug:
                print 'Lecture des services à redémarrer dans la base LDAP...'
            auto = True
            to_do = {}
            # Création de la liste de ce qu'il y a à faire
            for serv in db.services_to_restart():
                # Services spéciaux portant sur plusieurs machines
                to_add = self.__service_develop.get(serv.nom, [])
                if to_add:
                    for nom in to_add:
                        for t in serv.start:
                            db.services_to_restart(nom, serv.args, t)
                            if time() > t:
                                to_do[nom] = serv.args
                    db.services_to_restart('-' + serv.nom)
                else:
                     for t in serv.start:
                         if time() > t:
                             to_do[serv.nom] = serv.args
                             break
        else:
            auto = False
            if debug:
                print 'Services à redémarrer imposés (non lecture de la base LDAP)'

        for serv, args in to_do.items():
            # Au cas où le service porte sur plusieurs machines
            service = serv.replace('%s-' % hostname, '')
            if hasattr(self, service):
                # Le service est à reconfigurer sur cette machine
                db.services_to_restart('-%s' % serv)
                try:
                    m = getattr(self, service)
                    if len(getargspec(m)[0]) > 1:
                        m(args)
                    else:
                        m()
                except:
                    if auto:
                        db.services_to_restart(serv, args)
                    sys.stderr.write('%s :' % serv)
                    import traceback
                    traceback.print_exc()
            else:
                # Le service n'existe pas
                if debug:
                    print "Le service %s n'est pas disponible sur %s" % (service, hostname)

        if debug:
            reste = db.services_to_restart()
            if reste:
                print "Reste à faire :"
                for s in reste:
                    try:
                        print '\t%s' % s
                    except UnicodeDecodeError:
                        print '\t%s: non imprimable' % s.nom
            else:
                print "Plus rien à faire"

    def _machines(self):
        """ Retourne les machines de la base étant 'à jour' """
        return db.all_machines(graphic=True)

    def _do(self, service, machines=None):
        # Reconfiguration des services
        service.debug = debug
        if machines:
            service.machines = machines
        service.reconfigure()

    def _fw(self):
        if not hasattr(self, '__real_fw'):
            from firewall4 import firewall
            self.__real_fw = firewall()
        return self.__real_fw

    def macip(self, ips):
        if self.__service_develop.get('macip', []):
            cprint(u"Mise a jour correspondance MAC-IP", 'gras')
            self._fw().mac_ip_maj(ips)

    def blacklist(self, ips):
        if self.__service_develop.get('blacklist', []):
            cprint(u"Mise a jour des blacklists", 'gras')
            self._fw().blacklist_maj(ips)

class redisdead(base_reconfigure):
    def droits(self):
        from gen_confs.droits import droits_ldap
        self._do(droits_ldap())

    def desabonner_ml(self, args):
        from gen_confs.droits import desabonner_ml
        d = desabonner_ml()
        d.args = args
        self._do(d)

    def mail_ajout_droits(self, args):
        from adherents import mail_ajout_droits
        self._do(mail_ajout_droits(args))

    def mail_modif(self, trucs):
        """
        trucs est une liste de recherches à effectuer dans la base
        l'affichage des résultats formera le corps du mail
        """
        from supervison import mail
        self._do(mail(trucs))

    def mail_solde(self, modifs):
        from gen_confs.supervison import mail_solde
        self._do(mail_solde(modifs))


class owl(base_reconfigure):
    def del_user(self, args):
        # Suppression des fichiers index de dovecot
        from adherents import del_user
        self._do(del_user(args))

class odlyd(base_reconfigure):
    def __fw6(self):
        if not hasattr(self, '__real_fw6'):
            from firewall6 import Update
            self.__real_fw6 = Update()
        return self.__real_fw6

    def filtrage_exemptions(self):
        from gen_confs.filtrage import exemptions
        self._do(exemptions())

    def filtrage_machines(self):
        from gen_confs.filtrage import machines
        self._do(machines(), self._machines())

    def macip(self, ips):
        cprint(u"Mise a jour correspondance MAC-IP", 'gras')
        self._fw().mac_ip_maj(ips)
        self.__fw6().macs([], 6)

    def ports(self, ips):
        self._fw().filtrage_ports_maj(ips)
        #self.__fw6().ports(map(self.midt.from_ipv4, ips), 6)

    def blacklist(self, ips):
        self._fw().blacklist_maj(ips)
        self.__fw6().blacklist(6)

class zamok(base_reconfigure):
    def del_user(self, args):
        # Suppression des fichiers d'impression
        from adherents import del_user
        self._do(del_user(args))

class zbee(base_reconfigure):
    def home(self, args):
        from adherents import home
        self._do(home(args))

    def del_user(self, args):
        # Suppression du home et des mails
        from adherents import del_user
        self._do(del_user(args))

    def mail_bienvenue(self, mails):
        from adherents import mail_bienvenue
        self._do(mail_bienvenue(mails))


class komaz(base_reconfigure):

    # Mimétisme de ma part -- xhub
    def __fw6(self):
        if not hasattr(self, '__real_fw6'):
            from firewall6 import Update
            self.__real_fw6 = Update()
        return self.__real_fw6


    def macip(self, ips):
        cprint(u"Mise a jour correspondance MAC-IP", 'gras')
        self._fw().mac_ip_maj(ips)
        self.__fw6().macs([], 6)

    def ports(self, ips):
        self._fw().filtrage_ports_maj(ips)
        #self.__fw6().ports(map(self.midt.from_ipv4, ips), 6)

    def blacklist(self, ips):
        self._fw().blacklist_maj(ips)
        self.__fw6().blacklist(6)

    def classify(self, ips):
        #self.__fw().classes_p2p_maj(ips)
        pass

class fy(base_reconfigure):
    def autostatus(self):
        from autostatus import autostatus
        self._do(autostatus())

class dhcp(base_reconfigure):
    def dhcp(self):
        from gen_confs.dhcpd_new import dhcp
        self._do(dhcp(), db.search("mid=*")['machine'])

class isc(base_reconfigure):
    def dhcp(self):
        from gen_confs.dhcpd_new import dhcp
        self._do(dhcp(), db.search("mid=*")['machine'])

class sable(base_reconfigure):

    def dns(self):
        from gen_confs.bind import dns
        self._do(dns(), [])

class routeur(base_reconfigure):
    pass

class eap(base_reconfigure):
    pass

class gordon(base_reconfigure) :
    pass

class titanic(base_reconfigure):
    pass

remove_lock('auto_generate')

if __name__ == '__main__':
    signal.signal(signal.SIGINT, signal.SIG_IGN) # Pas de Ctrl-C
    openlog('generate', LOG_PID)
    for x in db.services_to_restart():
        try:
            syslog(str(x))
        except UnicodeDecodeError:
            syslog("%s: non imprimable" % x.nom)
    classe = getattr(sys.modules[__name__], hostname, base_reconfigure)

    args_autorises = ['quiet', 'remove=', 'add=', 'list', 'help', 'reconnect']
    # Ajout aussi des arguments spécifiques à la machine
    for nom in dir(classe):
        if nom[0] != '_':
            if len(getargspec(getattr(classe, nom))[0]) > 1:
                nom += '='
            args_autorises.append(nom)


    ##### Options fournies ?
    try:
        if len(sys.argv) > 1:
            options, arg = getopt.getopt(sys.argv[1:], 'h', args_autorises)
        else:
            options, arg = ([], '')
    except getopt.error, msg:
        sys.stderr.write('%s\n' % msg)
        sys.exit(255)

    debug = 1 # défaut
    to_do = {}

    for opt, val in options:
        if opt == '--quiet':
            debug = 0

        elif opt == '--remove':
            for serv in val.split('&'):
                print 'Supression de %s' % serv
                db.services_to_restart('--%s' % serv)
            sys.exit(0)

        elif opt == '--list':
            print 'Services à redémarrer :'
            for s in db.services_to_restart():
                try:
                    print '\t%s' % s
                except UnicodeDecodeError:
                    print '\t%s: non imprimable' % s.nom
            sys.exit(0)

        elif opt == '--reconnect':
            # Personnes à reconnecter
            print 'Recherche des personnes en fin de sanction...'
            c = db.search('blacklist=*')
            services = []
            nom = time()
            hier = time() - 24*3600
            demain = time() + 24*3600
            for a_reco in c['adherent'] + c['machine'] + c['club']:
                for bl in a_reco.blacklist():
                    fin, sanction = bl.split('$')[1:3]
                    if fin != '-' and fin <= demain and fin >= now and (sanction, fin) not in services:
                        services.append((sanction, fin))
            for s,f in services:
                print "Ajout de blacklist_%s pour reconfiguration" % s
                db.services_to_restart('blacklist_%s' % s, start=f)
            sys.exit(0)

        elif opt == '--add':
            # Ajout d'un item dans les services à redémarrer
            for serv in val.split('&'):
                if serv.find(',') != -1:
                    serv, arg = serv.split(',', 1)
                    arg = arg.split(',')
                else:
                    arg = []

                print 'Ajout de %s (%s)' % (serv, arg)
                db.services_to_restart(serv, arg)
            sys.exit(0)

        elif opt == '-h' or opt == '--help':
            print USAGE % { 'prog': sys.argv[0].split('/')[-1],
                              'options': '--' + '\n\t--'.join(args_autorises) }
            sys.exit(0)

        elif len(opt) > 2 and opt[:2] == '--':
            to_do[opt[2:]] = val.split('&')


    # On fait ce qu'il y a à faire
    classe(to_do)
    signal.signal(signal.SIGINT, signal.SIG_DFL) # Comportement normal de Ctrl-C
