#!/usr/bin/env python
# -*- coding: UTF-8 -*-

######################################################
# migrate_serveurs24.py
#
# Script permettant d'automatiser la génération de
# configurations de migration dans Zéphir
#
# Adapter la fonction update_conf pour correspondre aux besoins locaux
# (la migration des variables EOLE est prise en compte automatiquement
# de la même façon qu'en passant par l'interface web)
#
# le script demande l'emplacement d'un fichier CSV avec des lignes au format suivant :
#
# id_serveur;id_variante_destination
#

import csv,getpass,os
import dico,base64,xmlrpclib
from zephir.utils.creolewrap import ZephirDict
import sys
import traceback
import urllib2

# !!  mettre à True pour vérifier les valeurs lors de tests (la configuration ne sera pas sauvegardée) !!
debug = False

reload(sys)
sys.setdefaultencoding('utf-8')

adresse_zephir='localhost'
# délimiteur de champ
delimiter = ';'
login='admin-eole'
passwd=file('/root/admin-eole.pwd').readline().split('\n')[0]

# format des lignes csv:
# id_serveur;valeur_variable
def egala(dico, var, test):
    if var in dico.liste_vars:
        #print dico.get_value(var),type(dico.get_value(var)),"???===",test,type(test)
        if test == [''] or test == []:
            if dico.get_value(var) == [''] or dico.get_value(var) == []:
                return True
        if dico.get_value(var) == test or dico.get_value(var) == [test] or dico.get_value(var) == [unicode(test)]:
            return True
        else:
            return False

def copy_val(d_eole2, nom_var, var):
    # transformation des chaînes non unicode en unicode
    #print nom_var, var ,type(var),d_eole2.var_paths
    if nom_var in d_eole2.liste_vars:
        #print nom_var, var ,type(var)
        if var == "[u'']" or  var == "['']":
            var = []
        if var != '[]' and type(var) != list:
            if var.startswith(u"["):
                var = eval(var)
        if type(var) == list:
            for  index ,val in enumerate(var):
                #print val, index
                if type(val) == str:
                    var[index] = unicode(val, 'utf-8')
        elif type(var) == str:
            var = unicode(var, 'utf-8')
        #print nom_var, var ,type(var)
        #d_eole2.index = d_eole2.liste_vars[nom_var]
        d_eole2.get_var(nom_var)
        #opt = d_eole2.vars[d_eole2.index]
        #print nom_var, var ,type(var),d_eole2.var_paths[opt._properties]
        d_eole2.set_value( var)


def read_val(dico, val):
    if val in dico.liste_vars:
        var = dico.get_value(val)
        if var == "[u'']" or  var == "['']" or var == ['']:
            var = []
        #print "readval, var, type(var)", val, var, type(var)
        if var != '[]' and type(var) != list:
            if var.startswith(u"["):
                var = eval(var)
        #if type(var) == unicode:
        #    print val,var
        #    if var.startswith('['):
        #print var
        #        var = eval(var)
        if type(var) == list:
            for index,v in enumerate(var):
                #print index, v
                if type(v) == str:
                        var[index] = unicode(v, 'utf-8')
            return var #unicode(dico.get_value(val))
        else:
            return unicode(dico.get_value(val), 'utf-8')

def update_conf(d_eole1, d_eole2, variante):
    """
    traitement automatique des variables

    met à jour la configuration eole2 de migration en fonction de la configuration eole1

    d_eole1 : dictionnaire avec la configuration d'origine du serveur Eole 2.2
    d_eole2 : dictionnaire Eole 2.3 qui sera sauvegardé comme 'migration.eol'

    lire la valeur d'une variable (dico 1 ou 2):

          d_eoleX.get_value('nom_var')
          !ATTENTION! : get_value renvoie toujours une liste de valeur.
          En cas de test sur une valeur, récupérer la valeur voulue
          ex: if read_val(d_eole1,'activer_squid_auth')[0] == 'pedago':

    copier la valeur d'une variable de dico1 vers une variabel de dico2:
          copy_val(d_eole2,'nom_variable2.3',d_eole1.dico.get_value('nom_variable2.2'))

    modifier la valeur d'une variable du dictionnaire eole 2:

          copy_val(d_eole2,'nom_var','valeur')

    pour une variable multiple :  copy_val(d_eole2,'nom_var',['valeur1','valeur2, ...])

    vérifier si une variable est présente dans un dictionnaire:

          if 'nom_variable' in d_eoleX.liste_vars:
              .....

    variante : la variante à utiliser pour le serveur NG
    """

    # ----- inclure les traitements des variables ici
    # --- !! pour éviter des problèmes d'indentation, configurez l'éditeur pour remplacer
    # --- les tabulations par 4 espaces (ou éditez le fichier avec vi sur un module eole)
    #
    # --- Dans la mesure du possible, utilisez de préférence la modification des valeurs par défaut
    # --- des modules/variantes eole NG dans l'application web si les valeurs à renseigner sont les mêmes
    # --- pour tous les serveurs d'un(e) variante/module.


    ### Attention, si migration vers EOLE 2.4 :
    # pour set_value sur d_eole2, il faut utiliser des chaînes unicode pour les chaînes de caractères :
    # - au lieu de : copy_val(d_eole2,'passerelle_smtp', 'smtp.in.ac-dijon.fr')
    # - mettre : copy_val(d_eole2,'passerelle_smtp', u'smtp.in.ac-dijon.fr')
    ###
    #settings = d_eole2.dico.cfgimpl_get_settings()
    #settings.remove('disabled')
    #settings.remove('frozen')

    # exemple : mettre le nombre de cartes à 3 si le modèle de pare-feu dans la configuration amon-1.5
    # contient la chaine '3zones'
    #if 'type_amon' in d_eole1.liste_vars:
    #    if '3zones' in read_val(d_eole1,'type_amon'):
    #        copy_val(d_eole2,'nombre_interfaces','3')

    # exemple2 : pour la variante 8, activer le serveur sso si le frontend ead-web est activé
    #if variante == 8:
    #    if d_eole2.get_value('ead_web') == 'oui':
    #        copy_val(d_eole2,'adresse_ip_sso', read_val(d_eole1,'adresse_ip_eth0'))

    # ---- fin des traitements

    # exemple 3 (variables migrées à Nantes)
    #if egala(d_eole1,'fw_pronote','oui') or \
    #   egala(d_eole1,'fw_edt','oui') or \
    #   egala(d_eole1,'fw_campus','oui'):
    #    copy_val(d_eole2,'fw_scolarite',u'oui')
    #
    #if egala(d_eole1,'dhcp_eth1','oui') and \
    #   not egala(d_eole1,'dhcp_eth2','oui') :
    #    copy_val(d_eole2,'adresse_network_dhcp',read_val(d_eole1,'adresse_network_eth1'))
    #    copy_val(d_eole2,'adresse_netmask_dhcp',read_val(d_eole1,'adresse_netmask_eth1'))
    #    copy_val(d_eole2,'ip_basse_dhcp',read_val(d_eole1,'dhcp_eth1_debut'))
    #    copy_val(d_eole2,'ip_haute_dhcp',read_val(d_eole1,'dhcp_eth1_fin'))
    #    copy_val(d_eole2,'adresse_ip_gw_dhcp',read_val(d_eole1,'adresse_ip_eth1'))
    #    copy_val(d_eole2,'adresse_ip_dns_dhcp',read_val(d_eole1,'adresse_ip_eth1'))
    #    copy_val(d_eole2,'nom_domaine_dhcp',read_val(d_eole1,'nom_domaine_local'))

    return d_eole2

def migrate_serveurs(fic_csv_name,idz,var):
    """
    boucle principal de parcours des serveurs
    """
    #login = raw_input('login zephir :')
    #passwd = getpass.getpass('mot de passe :')
    login='admin-eole'
    passwd=file('/root/admin-eole.pwd').readline().split('\n')[0]
    proxy = xmlrpclib.ServerProxy('http://%s:%s@%s:7081' % (login,passwd,adresse_zephir))
    erreurs = []
    # lecture du fichier csv
    if fic_csv_name != None:
        fic_csv = open(fic_csv_name)
        parser = csv.reader(fic_csv,delimiter=delimiter)
        # parsing des données
        while True:
            try:
                # lecture d'une ligne du fichier csv
                data_serveur = parser.next()
            except StopIteration:
                # fin du fichier
                fic_csv.close()
                break
            # chaque ligne indique un numéro de serveur et le n° de la variante NG à utiliser après migration
            id_serveur, variante = data_serveur
            id_serveur = int(id_serveur)
            variante = int(variante)
            # migration du serveur (équivalent de 'générer la 'générer les données de migration' dans  l'appli web)
            try:
                # récupération du dictionnaire creole1 du serveur amon 1.5
                code, data_ori = proxy.serveurs.get_dico(id_serveur,'modif_config',True)
                d_eole1 = ZephirDict(mode='')
                d_eole1.init_from_zephir(data_ori)
                # initialisation du dictionnaire creole2
                print "variante", str(variante)
                code, data_migration = proxy.serveurs.migrate_conf(int(id_serveur), 'migration', int(variante))
                if code == 0:
                    raise Exception, data_migration
                d_eole2 = ZephirDict(mode='', version='creole3')
                d_eole2.init_from_zephir(data_migration)
                # mise à jour du dictionnaire de migration
                d_eole2 = update_conf(d_eole1, d_eole2, int(variante))
                if debug:
                    print "\n--- configuration du serveur %s\n" % id_serveur
                    for var in d_eole2.liste_vars:
                        print var, '-->', d_eole2.get_value(var)
                else:
                    save_data = d_eole2.save(force=False)#,eol_file='/tmp/test.txt')
                    # sauvegarde de la conf sur zephir (migration.eol)
                    code, detail = proxy.serveurs.save_conf(id_serveur, save_data, 'migration')
                    proxy.serveurs.edit_serveur(id_serveur,{'libelle':'pf-amon-' + read_val(d_eole1,'numero_etab')[0]})
                    print "serveur modifié : %s" % id_serveur
            except Exception, e:
                import traceback
                traceback.print_exc()
                print "erreur de modification du serveur %s : %s" % (id_serveur, str(e))
                erreurs.append(delimiter.join(data_serveur))
    else:
        id_serveur = int(idz)
        variante = int(var)
        # migration du serveur (équivalent de 'générer la 'générer les données de migration' dans  l'appli web)
        try:
            # récupération du dictionnaire creole1 du serveur amon 1.5
            code, data_ori = proxy.serveurs.get_dico(id_serveur,'modif_config',True)
            d_eole1 = ZephirDict(mode='')
            d_eole1.init_from_zephir(data_ori)
            # initialisation du dictionnaire creole2
            print "variante", str(variante)
            code, data_migration = proxy.serveurs.migrate_conf(int(id_serveur), 'migration', int(variante))
            if code == 0:
                raise Exception, data_migration
            d_eole2 = ZephirDict(mode='', version='creole3')
            d_eole2.init_from_zephir(data_migration)
            # mise à jour du dictionnaire de migration
            d_eole2 = update_conf(d_eole1, d_eole2, int(variante))
            if debug:
                print "\n--- configuration du serveur %s\n" % id_serveur
                for var in d_eole2.liste_vars:
                    print var, '-->', d_eole2.get_value(var)
            else:
                save_data = d_eole2.save(force=False)#,eol_file='/tmp/test.txt')
                # sauvegarde de la conf sur zephir (migration.eol)
                code, detail = proxy.serveurs.save_conf(id_serveur, save_data, 'migration')
                proxy.serveurs.edit_serveur(id_serveur,{'libelle':'pf-amon-' + read_val(d_eole1,'numero_etab')[0]})
                print "serveur modifié : %s" % id_serveur
        except Exception, e:
            import traceback
            traceback.print_exc()
            print "erreur de modification du serveur %s : %s" % (id_serveur, str(e))
            erreurs.append(delimiter.join(data_serveur))

    # on stocke dans un fichier csv les serveurs non ajoutés
    if len(erreurs) > 0:
        f=open("error.csv","w")
        f.write('\n'.join(erreurs))
        f.close()



if __name__ == '__main__':
    try:
        csvfile = None
        idz = None
        var = None
        if len(sys.argv) == 1:
            print 'Usage : migration.py <Id_serveur> <Id_variante>'
            print 'Usage : migration.py <fichier.csv>'
        if len(sys.argv) == 2:
            csvfile=sys.argv[1]
        if len(sys.argv) == 3:
            idz=sys.argv[1]
            var=sys.argv[2]
        if csvfile == None and idz == None and var == None:
            csvfile = raw_input('emplacement du fichier csv : ')
        #login='admin-eole'
        #passwd=file('/root/admin-eole.pwd').readline().split('\n')[0]
    except:
        print "Erreur  d'argument " + str(len(sys.argv))
    migrate_serveurs(csvfile,int(idz),int(var))
