Projet

Général

Profil

migration_amon_26.py

ma version amon - équipe eole Academie d'Orléans-Tours, 24/01/2019 12:06

Télécharger (15,9 ko)

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

    
4
import sys
5
if '/usr/share/eole/orl' not in sys.path:
6
        sys.path.append('/usr/share/eole/orl')
7
if '/usr/share/eole/orl/scripts' not in sys.path:
8
        sys.path.append('/usr/share/eole/orl/scripts')
9
###########################################################################
10
# Eole - 2014
11
# Copyright Pole de Competence Eole  (Ministere Education - Academie Dijon)
12
# Licence CeCill  cf /root/LicenceEole.txt
13
# eole@ac-dijon.fr
14
#
15
# migration_2.4.py
16
#
17
# squelette de script permettant de générer des configurations de migration
18
# en mode batch (via l'API XMLRPC de Zéphir)
19
#
20
# Ce script génère une configuration de la même façon qu'en utilisant
21
# le bouton "générer un configuration de migration' de l'application web.
22
#
23
# Il est possible de personnaliser la fonction update_conf pour gérer
24
# des variables supplémentaires non gérées par la fonction d'origine.
25
# (variables déclarées au niveau des variantes / serveurs).
26
#
27
###########################################################################
28

    
29
import csv,getpass,os
30
import base64,xmlrpclib
31
from zephir.utils.creolewrap import ZephirDict
32
import sys
33
reload(sys)
34
import string
35
# force l'encodage par défaut à utf-8 pour les chaînes unicode
36
sys.setdefaultencoding('utf-8')
37

    
38
# à redéfinir si utilisé à distance
39
adresse_zephir='localhost'
40

    
41
# délimiteur de champ pour le fichier CSV décrivant les serveurs à traiter
42
delimiter = ';'
43
# contenu des champs du fichier csv:
44
# id_serveur;id_variante_destination
45

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

    
49
#######################################################
50
## FONCTIONS UTILITAIRES POUR LE TRAITEMENT DES VALEURS
51

    
52
def is_empty(value):
53
    # renvoie True si value est 'vide' :
54
    # liste vide / chaine vide / liste de chaines vides
55
    return len(u"".join(value)) == 0
56

    
57
def is_equal(dico, nom_var, test):
58
    """renvoie True si la valeur de la variable nom_var est équivalente à test
59
    gère le cas des chaines unicode ou non et des listes 'vides'
60
    """
61
    if nom_var in dico.liste_vars:
62
        if test in ([], [''], [u'']):
63
            if dico.get_value(nom_var) in ([], [''], [u'']):
64
                return True
65
        if dico.get_value(nom_var) == test or \
66
           dico.get_value(nom_var) == [test] or \
67
           dico.get_value(nom_var) == [unicode(test)]:
68
            return True
69
        return False
70
    else:
71
        print u"Appel de is_equal sur une variable inconnue : {0}".format(nom_var)
72

    
73
def copy_val(dico, nom_var, value):
74
    """ définit une valeur sur une variable en transformant
75
    les chaînes non unicode en unicode dico est une configuration 2.4
76
    """
77
    if nom_var in dico.liste_vars:
78
        if value == "[u'']" or  value == "['']":
79
            value = []
80
        if value != '[]' and type(value) != list:
81
            #print "START", nom_var
82
            if value.startswith(u"["):
83
                value = eval(value)
84
        # si le dictionnaire de destination est de type 'creole3' (eole 2.4),
85
        # on transforme les type 'str' en 'unicode'
86
        if dico.version == 'creole3':
87
            if type(value) == list:
88
                for  index ,val in enumerate(value):
89
                    if type(val) == str:
90
                        value[index] = unicode(val, 'utf-8')
91
            elif type(value) == str:
92
                value = unicode(value, 'utf-8')
93
        dico.get_var(nom_var)
94
        dico.set_value(value)
95
    else:
96
        print u"Appel de copy_val sur une variable inconnue : {0}".format(nom_var)
97

    
98
def read_val(dico, nom_var):
99
    if nom_var in dico.liste_vars:
100
        value = dico.get_value(nom_var)
101
        if value == "[u'']" or  value == "['']" or value == ['']:
102
            value = []
103
        if value != '[]' and type(value) != list:
104
            #print "START", nom_var
105
            if value.startswith(u"["):
106
                value = eval(value)
107
        if type(value) == list:
108
            for index,v in enumerate(value):
109
                if type(v) == str:
110
                        value[index] = unicode(v, 'utf-8')
111
            return value
112
        else:
113
            return unicode(dico.get_value(nom_var), 'utf-8')
114
    else:
115
        print u"Appel de read_val sur une variable inconnue : {0}".format(nom_var)
116

    
117
###AJOUT ORLEANS
118
nat_agr={"18":"20",
119
        "28":"21",
120
        "36":"22",
121
        "37":"23",
122
        "41":"24",
123
        "45":"25",
124
        "99":"25"
125
        }
126

    
127
def sub_octet_4(ip, octet4):
128
    octets=ip.split(".")
129
    octets.__delitem__(3)
130
    octets.append(str(octet4))
131
    return ".".join(octets)
132

    
133
def sub_octet_1D(ip):
134
        octets=ip.split(".")
135
        octets[1]="1"+octets[1]
136
        return ".".join(octets)
137

    
138
def concat_list(liste1, liste2):
139
        new_liste=[]
140
        for i in liste1:
141
                new_liste.append(i)
142
        for j in liste2:
143
                new_liste.append(j)
144
        return new_liste
145

    
146
def del_index_list(index, liste):
147
    return liste.__delitem__(index)
148

    
149
######################################
150
## FONCTION PERSONNALISEE DE MIGRATION
151

    
152
def update_conf(d_eole1, d_eole2, variante, proxy, domaine, ip_scribe, smtp, type_etab, statut, vm, version, maxchildren_adm, maxchildren_peda, lst_ips):
153
    """
154
        traitement automatique des variables
155

156
    met à jour la configuration de migration en fonction de la configuration actuelle
157

158
    d_eole1 : dictionnaire avec la configuration d'origine du serveur
159
    d_eole2 : dictionnaire qui sera sauvegardé sur Zéphir comme 'migration.eol'
160
              (configuration à appliquer sur le serveur migré)
161
    variante: identifiant de la variante du serveur après migration
162
    proxy: proxy XMLRPC utilisable pour faire des appels à l'API Zéphir
163

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

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

171
    copier la valeur d'une variable de dico1 vers une variabel de dico2:
172
          copy_val(d_eole2,'nom_variable2.4',d_eole1.get_value('nom_variable2.2'))
173

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

176
          copy_val(d_eole2,'nom_var',u'valeur')
177

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

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

182
          if 'nom_variable' in d_eoleX.liste_vars:
183
              .....
184

185
    une bonne pratique peut être de créer des sous fonctions spécifiques à chaque variante
186

187
    Pour plus d'informations sur l'utilisation de l'API de Zéphir:
188
    https://<adresse_ip_zephir>:8070/aide/devel
189
    https://<adresse_ip_zephir>:8070/aide/api
190
    """
191

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

    
200

    
201
    ### Attention, pour la migration vers EOLE 2.4 :
202
    #
203
    # pour set_value sur d_eole2, il faut utiliser des chaînes unicode pour les chaînes de caractères :
204
    # par exemple:
205
    # - d_eole2.get_var('passerelle_smtp') : sélectionne la variable
206
    # - d_eole2.set_value(u'smtp.in.ac-dijon.fr') : applique la valeur (unicode)
207
    #
208
    # utiliser de préférence les fonction copy_val et read_val, qui convertissent les chaînes si besoin :
209
    # copy_val(d_eole2, 'passerelle_smtp', u'smtp.in.ac-dijon.fr') : ici, u est optionnel
210
    ###
211

    
212
    # exemple1 : mettre le nombre de cartes à 3 si le modèle de pare-feu dans la configuration amon-1.5
213
    # contient la chaine '3zones'
214
    #
215
    #if 'type_amon' in d_eole1.liste_vars:
216
    #    if '3zones' in d_eole1.get_value('type_amon'):
217
    #        d_eole2.dico.set_value('nombre_interfaces','3')
218

    
219
    # exemple2 : pour la variante 8, activer le serveur sso si le frontend ead-web est activé
220
    #
221
    #if variante == 8:
222
    #    if isequal(d_eole2, 'ead_web', 'oui'):
223
    #        copy_val(d_eole2,'adresse_ip_sso', read_val(d_eole1,'adresse_ip_eth0'))
224

    
225
    # exemple 3:
226
    #
227
    # passage à oui de 'activer_ajout_hosts' si des noms supplémentaires ont été ajoutés par la variante 2.4
228
    # (forcé à non au moment de l'upgrade si la configuration d_eole1 ne contient pas de noms supplémentaire)
229
    #
230
    #if len(d_eole2.get_value('adresse_ip_hosts')) != 0:
231
    #    copy_val(d_eole2, 'activer_ajout_hosts', u'oui')
232
        ###
233
        # Calul du département
234
    rne=read_val(d_eole1,'numero_etab')[0]
235
    dept=rne[1:3]
236
    # Mise à jour des variables
237
        #conf wpad
238
    copy_val(d_eole2,'proxy_bypass_eth1','oui')
239
    if read_val(d_eole1,'nombre_interfaces')[0]=='4':
240
        copy_val(d_eole2,'proxy_bypass_eth3','non')
241
    if type_etab=="lyc":
242
        copy_val(d_eole2,'proxy_bypass_eth2','oui')
243
        copy_val(d_eole2,'proxy_bypass_network_eth2',['192.168.232.0','192.168.236.0','192.168.220.0','192.168.224.0','172.16.0.0','192.168.122.0'])
244
        copy_val(d_eole2,'proxy_bypass_netmask_eth2',['255.255.252.0','255.255.255.0','255.255.252.0','255.255.248.0','255.248.0.0','255.255.255.0'])
245
        copy_val(d_eole2,'proxy_bypass_network_eth1',['172.16.0.0','172.24.0.0','10.0.0.0','161.48.0.0','192.168.232.0','192.168.236.0','192.168.220.0','192.168.224.0','192.168.122.0'])
246
        copy_val(d_eole2,'proxy_bypass_netmask_eth1',['255.248.0.0','255.248.0.0','255.0.0.0','255.255.224.0','255.255.252.0','255.255.255.0','255.255.252.0','255.255.248.0','255.255.255.0'])
247
    else:
248
        copy_val(d_eole2,'proxy_bypass_network_eth1',['172.16.0.0','172.24.0.0','10.0.0.0','161.48.0.0'])
249
        copy_val(d_eole2,'proxy_bypass_netmask_eth1',['255.248.0.0','255.248.0.0','255.0.0.0','255.255.224.0'])
250
        copy_val(d_eole2,'proxy_bypass_eth2','non')
251
    copy_val(d_eole2,'proxy_bypass_domain_eth1','etab.ac-orleans-tours.fr')
252
    copy_val(d_eole2,'proxy_bypass_domain_eth2',domaine+'.ac-orleans-tours.fr')
253
    if read_val(d_eole1,'nombre_interfaces')[0]=='4':
254
        copy_val(d_eole2,'proxy_bypass_domain_eth3',domaine+'.ac-orleans-tours.fr')
255

    
256
    #safesearch via DNS
257
    copy_val(d_eole2,'nom_domaine_local_supp','rpz.com')
258

    
259
#pour proxy.wifi
260
    lst_vlan=read_val(d_eole1,'vlan_id_eth2')
261
    lst_dns_fw=read_val(d_eole1,'dns_forward_vlan_eth2')
262
    if "24" in lst_vlan:
263
        index=read_val(d_eole1,'vlan_id_eth2').index("24")
264
        lst_dns_fw[index]=u"oui"
265
        copy_val(d_eole2,'dns_forward_vlan_eth2',lst_dns_fw)
266
    if "25" in lst_vlan:
267
        index=read_val(d_eole1,'vlan_id_eth2').index("25")
268
        lst_dns_fw[index]=u"oui"
269
        copy_val(d_eole2,'dns_forward_vlan_eth2',lst_dns_fw)
270
    if "26" in lst_vlan:
271
        index=read_val(d_eole1,'vlan_id_eth2').index("26")
272
        lst_dns_fw[index]=u"oui"
273
        copy_val(d_eole2,'dns_forward_vlan_eth2',lst_dns_fw)
274
    #vmtools
275
    if vm=="1":
276
        copy_val(d_eole2,'orl_vmware_tools','oui')
277

    
278
    #maxchildren passe en httpworkers
279
    #c'est géré par le script migration_conf qui demande les valeurs d'apres la ram
280

    
281
    #https://dev-eole.ac-dijon.fr/issues/15792
282
    copy_val(d_eole2,'half_closed_clients','off')
283

    
284
    if type_etab=="lyc":
285
        copy_val(d_eole2,'orl_filtrage_youtube','aucun')
286
# ---- fin des traitements
287

    
288
    return d_eole2
289

    
290
###AJOUT ORLEANS
291
def get_pass():
292
    fic=open("/root/pwd", "r")
293
    pwd=fic.readline().strip()
294
    fic.close()
295
    os.system("rm -f /root/pwd")
296
    login=pwd.split(";")[0]
297
    passwd=pwd.split(";")[1]
298
    return [login, passwd]
299

    
300
######################
301
## FONCTION PRINCIPALE
302

    
303
def migrate_serveurs(fic_csv_name="migration.csv", main_loop=False):
304
    """
305
    boucle principal de parcours des serveurs
306
    """
307
    login, passwd = get_pass()
308
    # lecture du fichier csv
309
    fic_csv_name = "/root/amon.csv"
310
    fic_csv = open(fic_csv_name)
311
    parser = csv.reader(fic_csv,delimiter=delimiter)
312
    proxy = xmlrpclib.ServerProxy('http://%s:%s@%s:7081' % (login,passwd,adresse_zephir))
313
    # informations sur les module et variantes
314

    
315
    # parsing des données
316
    erreurs = []
317
    while True:
318
        try:
319
            # lecture d'une ligne du fichier csv
320
            data_serveur = parser.next()
321
        except StopIteration:
322
            # fin du fichier
323
            fic_csv.close()
324
            break
325
        # chaque ligne indique un numéro de serveur et le n° de la variante à utiliser après migration
326
        id_serveur, variante, domaine, ip_scribe, smtp, type_etab, statut, vm, version, maxchildren_adm, maxchildren_peda, lst_ips = data_serveur
327
        id_serveur = int(id_serveur)
328
        variante = int(variante)
329
        # migration du serveur (équivalent de 'générer la 'générer les données de migration' dans  l'appli web)
330
        try:
331
            # récupération du dictionnaire creole du serveur dans sa version actuelle
332
            code, data_ori = proxy.serveurs.get_dico(id_serveur,'modif_config',True)
333
            # passage 2.4.2 ou 2.5.2 à 2.6.2
334
            d_eole1 = ZephirDict(mode='', version='creole3')
335
            d_eole1.init_from_zephir(data_ori)
336
            # initialisation du dictionnaire creole2
337
            code, data_migration = proxy.serveurs.migrate_conf(int(id_serveur), 'migration', int(variante))
338
            if code == 0:
339
                raise Exception, data_migration
340
            ##  IMPORTANT, pour la migration vers eole 2.4, bien spécifier version='creole3'
341
            d_eole2 = ZephirDict(mode='', version='creole3')
342
            # initialisation du dictionnaire depuis les valeurs renvoyées par Zéphir
343
            d_eole2.init_from_zephir(data_migration)
344
            # déblocage temporaire des variables cachées et vérouillées ?
345
            #settings = d_eole2.dico.cfgimpl_get_settings()
346
            #settings.remove('disabled')
347
            #settings.remove('frozen')
348
            # mise à jour du dictionnaire de migration
349
            # APPEL DE LA FONCTION DE MIGRATION PERSONNALISEE
350
            d_eole2 = update_conf(d_eole1, d_eole2, int(variante), proxy, domaine, ip_scribe, smtp, type_etab, statut, vm, version, maxchildren_adm, maxchildren_peda, lst_ips)
351
            if debug:
352
                print "\n--- configuration du serveur %s\n" % id_serveur
353
                for var in d_eole2.liste_vars:
354
                    print var, '-->', d_eole2.get_value(var)
355
                if not main_loop:
356
                    # mod debug et appel depuis shell python: on retourne
357
                    # les 2 dictionnaires pour le premier serveur du fichier CSV
358
                    # pour faciliter les diagnostics
359
                    fic_csv.close()
360
                    return d_eole1, d_eole2
361
            else:
362
                save_data = d_eole2.save(force=False) #,eol_file='/tmp/test.txt')
363
                # sauvegarde de la conf sur zephir (migration.eol)
364
                code, detail = proxy.serveurs.save_conf(id_serveur, save_data, 'migration')
365
                print "serveur modifié : %s" % id_serveur
366
        except Exception, e:
367
            if debug:
368
                # trace complète en mode debug
369
                import traceback
370
                traceback.print_exc()
371
            print "erreur de modification du serveur %s : %s" % (id_serveur, str(e))
372
            erreurs.append(delimiter.join(data_serveur))
373

    
374
    # on stocke dans un fichier csv les serveurs non ajoutés
375
    if len(erreurs) > 0:
376
        f=open("error.csv","w")
377
        f.write('\n'.join(erreurs))
378
        f.close()
379
        print "\nDes erreurs ont été rencontrées :\n"
380
        print "- Vous pouvez consulter les logs du service zephir pour plus d'informations:\n"
381
        print "     /var/log/rsyslog/local/zephir_backend/zephir_backend.info.log\n"
382
        print "- un fichier error.csv a été généré pour relancer ce script sur les serveurs en erreur\n"
383

    
384
if __name__ == '__main__':
385
    try:
386
        # on regarde si un fichier csv est passé en argument
387
        assert os.path.isfile(sys.argv[1])
388
        fic_csv = sys.argv[1]
389
    except:
390
        fic_csv = ""
391
    migrate_serveurs(fic_csv, main_loop=True)