Package zephir :: Package backend :: Module modules_rpc
[frames] | no frames]

Source Code for Module zephir.backend.modules_rpc

   1  # -*- coding: UTF-8 -*- 
   2  ########################################################################### 
   3  # Eole NG - 2007   
   4  # Copyright Pole de Competence Eole  (Ministere Education - Academie Dijon) 
   5  # Licence CeCill  cf /root/LicenceEole.txt 
   6  # eole@ac-dijon.fr  
   7  #   
   8  # modules_rpc.py 
   9  #   
  10  # fonctions xmlrpc pour la gestion des modules dans Zephir 
  11  #        
  12  ########################################################################### 
  13  """module de gestion des modules Eole 
  14  """ 
  15  from zephir.backend.db_utils import * 
  16  from zephir.backend import config 
  17  from zephir.backend.config import u, log 
  18  from zephir.backend.xmlrpceole import XMLRPCEole as XMLRPC 
  19  from zephir.backend.lib_backend import ResourceAuthError, istextfile, cx_pool 
  20  from zephir.utils.creolewrap import ZephirDict 
  21   
  22  # import relatifs aux tables 
  23  import sys,os,shutil,md5,time,dico,base64,ConfigParser, traceback 
  24  from zephir.eolerpclib import xmlrpclib 
  25  from creole.cfgparser import EoleDict, eosfunc 
  26   
  27  BLANK_MD5 = md5.md5('').hexdigest() 
  28   
29 -class RPCModules(XMLRPC):
30 """serveur XMLRPC zephir pour la gestion des modules Eole 31 """ 32
33 - def __init__(self,parent):
34 self.dbpool = db_connect() 35 self.dbpool.noisy = 0 36 self.parent = parent 37 # mise à jour des modules si besoin 38 XMLRPC.__init__(self)
39
40 - def startup(self):
42
43 - def xmlrpc_update_modules(self,cred_user=''):
44 """vérification de la liste des modules""" 45 cursor = cx_pool.create() 46 try: 47 cursor.execute("""select libelle from modules""") 48 modules_actuels = [module[0] for module in cursor.fetchall()] 49 except: 50 cx_pool.close(cursor) 51 # Erreur de lecture des modules 52 log.msg("\nErreur de lecture de la liste des modules\n") 53 return 0, u("Erreur de lecture de la liste des modules") 54 cx_pool.close(cursor) 55 new_modules = [] 56 for version, modules in config.liste_modules.items(): 57 for module in modules: 58 if module not in modules_actuels: 59 # ajout d'un nouveau module 60 try: 61 new_modules.append(module) 62 self.xmlrpc_add_module("", module, version).addCallbacks(log.msg,log.msg) 63 except: 64 return 0, u("erreur d'ajout du module %s" % module) 65 # log de la création des modules 66 if len(new_modules) > 0: 67 log.msg("\nNouveaux modules: %s\n" % ", ".join(new_modules)) 68 return 1, u("Nouveaux modules : %s" % ", ".join(new_modules)) 69 else: 70 return 1, u("OK")
71
72 - def _got_modules(self,modules,cred_user):
73 """Récupération de la table module depuis le backend 74 """ 75 l=[] 76 for module in modules: 77 try: 78 self.parent.s_pool.check_mod_credential(cred_user, module[0]) 79 except ResourceAuthError: 80 # non autorisé : module suivant 81 continue 82 if module[2] == None: 83 version = 1 84 else: 85 version = module[2] 86 l.append({'id':module[0],'libelle':module[1],'version':version}) 87 return 1,u(l)
88 89 ############################## 90 ## gestion de la table modules 91 ############################## 92 93
94 - def xmlrpc_add_module(self, cred_user, libelle, version=3):
95 """ajoute un module dans la base de données et crée l'arborescence correspondante""" 96 # on vérifie que les données obligatoires sont remplies 97 if libelle: 98 query = """insert into modules (libelle, version) values (E%s,%s)""" 99 params = (libelle, int(version)) 100 # on effectue l'insertion (l'existence est à tester dans l'application cliente) 101 return self.dbpool.runOperation(query, params).addCallbacks(self._add_module1,db_client_failed,callbackArgs=[libelle, version]) 102 else: 103 # des attributs manquent 104 return 0, u("""donnez un libellé""")
105
106 - def _add_module1(self,resultat,libelle,version):
107 """récupère l'id du module créé""" 108 # requête pour récupérer l'id 109 query="""select id from modules where libelle ilike E%s""" 110 return self.dbpool.runQuery(query, (libelle,)).addCallbacks(self._add_module2,db_client_failed,callbackArgs=[libelle,version])
111
112 - def _add_module2(self,row,libelle,version):
113 """crée la variante standard d'un nouveau module""" 114 if row ==[]: 115 return 0,u('erreur de création du module dans la base') 116 else: 117 id_module=row[0][0] 118 # on crée la variante standard du module 119 query = """insert into variantes (module,libelle) values (%s, 'standard')""" 120 return self.dbpool.runOperation(query, (int(id_module),)).addCallbacks(self._add_module3,db_client_failed,callbackArgs=[id_module,libelle,version])
121
122 - def _add_module3(self,resultat,id_module,libelle,version):
123 """récupère l'id de la variante standard""" 124 query = """select id,module from variantes where module = %s and libelle = 'standard'""" 125 return self.dbpool.runQuery(query, (int(id_module),)).addCallbacks(self._add_module4,db_client_failed,callbackArgs=[libelle,version])
126 127
128 - def _add_module4(self,row,libelle,version):
129 """met en place l'arborescence du nouveau module et de ses variantes""" 130 if row == []: 131 return 0,u('erreur de creation de la variante par défaut dans la base') 132 else: 133 id_variante = row[0][0] 134 id_module = row[0][1] 135 # on créé l'arborescence pour le module 136 module_dir = os.path.abspath(config.PATH_MODULES)+os.sep+str(id_module) 137 try: 138 os.makedirs(module_dir) 139 # lien du(des) dictionnaire(s) 140 if int(version) == 1: 141 dico_module=os.path.abspath(config.ROOT_DIR)+'/dictionnaires/dico-%s' % libelle 142 os.system('ln -s %s %s' % (dico_module,module_dir+os.sep+'dictionnaire')) 143 else: 144 # module eole 2 145 dico_module=os.path.abspath(config.ROOT_DIR)+'/dictionnaires/%s' % libelle 146 if os.path.isdir(dico_module): 147 # modules de base eole 148 os.system('ln -s %s %s' % (dico_module, os.path.join(module_dir,'dicos'))) 149 # création d'un fichier de valeurs par défaut 150 d = EoleDict() 151 d.read_dir(os.path.join(module_dir,'dicos')) 152 # sauvegarde des valeurs sans vérifications pour créer le fichier 153 d.save_values(os.path.join(module_dir,'module.eol'),True) 154 else: 155 # module additionnel 156 os.makedirs(os.path.join(module_dir,'dicos')) 157 # on crée la variante par défaut (module standard) 158 os.makedirs(module_dir+os.sep+'variantes'+os.sep+str(id_variante)+os.sep+'dicos') 159 os.makedirs(module_dir+os.sep+'variantes'+os.sep+str(id_variante)+os.sep+'patchs') 160 os.makedirs(module_dir+os.sep+'variantes'+os.sep+str(id_variante)+os.sep+'fichiers_perso') 161 os.makedirs(module_dir+os.sep+'variantes'+os.sep+str(id_variante)+os.sep+'fichiers_zephir') 162 except: 163 traceback.print_exc() 164 try: 165 shutil.rmtree(module_dir) 166 except: 167 # aucun répertoire créé 168 pass 169 query = """delete from variantes where module = %s""" 170 self.dbpool.runOperation(query, (int(id_module),)) 171 query = """delete from modules where id = %s""" 172 self.dbpool.runOperation(query, (int(id_module),)) 173 return 0, u("""erreur de creation de l'arborescence du module""") 174 # mise à jour des statistiques 175 self.parent.s_pool.stats['serv_modules'][str(id_module)] = 0 176 return 1, u(id_module)
177
178 - def xmlrpc_del_module(self,cred_user,id_module):
179 """supprime un module et ses variantes""" 180 if int(id_module) >= 0: 181 self.parent.s_pool.check_mod_credential(cred_user, id_module) 182 # suppression des variantes dans la base de données 183 query = "delete from variantes where module = %s" 184 return self.dbpool.runOperation(query, (int(id_module),)).addCallbacks(self._del_module,db_client_failed,callbackArgs=[id_module]) 185 else: 186 return 0, u("""donnez l'id d'un module (nombre entier)""")
187
188 - def _del_module(self,retour,id_module):
189 """supprime de la base les services liés au module""" 190 query = "delete from services where module = %s" 191 return self.dbpool.runOperation(query, (int(id_module),)).addCallbacks(self._del_module1,db_client_failed,callbackArgs=[id_module])
192
193 - def _del_module1(self,retour,id_module):
194 """supprime le module dans la base de données""" 195 query = "delete from modules where id = %s" 196 return self.dbpool.runOperation(query, (int(id_module),)).addCallbacks(self._del_module2,db_client_failed,callbackArgs=[id_module])
197
198 - def _del_module2(self,retour,id_module):
199 """supprime l'arborescence du module dans l'arborescence zephir""" 200 # mise à jour des statistiques 201 if str(id_module) in self.parent.s_pool.stats['serv_modules']: 202 del(self.parent.s_pool.stats['serv_modules'][str(id_module)]) 203 module_dir=os.path.abspath(config.PATH_MODULES)+os.sep+str(id_module) 204 try: 205 shutil.rmtree(module_dir) 206 except: 207 return 1,u("""erreur de supression du répertoire du module""") 208 return 1,u('ok')
209
210 - def xmlrpc_edit_module(self,cred_user,id_module,dico_modifs):
211 """modification d'un module 212 cette fonction prend en compte un dictionnaire qui indique les 213 champs à modifier et leur nouvelle valeur. l'application cliente 214 doit s'assurer que ces champs existent dans la base""" 215 self.parent.s_pool.check_mod_credential(cred_user, id_module) 216 if dico_modifs == {}: 217 return 1,u("""aucune modification demandée""") 218 # on vérifie que l'identifiant n'est pas modifié 219 if 'id' in dico_modifs.keys(): 220 return 0,u("""l'identifiant ne peut pas être modifié""") 221 # construction de la requête SQL de modification 222 requete = ["update modules set "] 223 params = [] 224 for cle in dico_modifs.keys(): 225 requete.append(str(cle)) 226 if cle == 'version': 227 requete.append("=%s, ") 228 params.append(int(dico_modifs[cle])) 229 else: 230 requete.append("=E%s, ") 231 params.append(dico_modifs[cle]) 232 string_fin=""" where id=%s""" 233 params.append(int(id_module)) 234 query="".join(requete)[:-2] 235 query += string_fin 236 return self.dbpool.runOperation(query, params).addCallbacks(lambda x:(1,'ok'), db_client_failed)
237
238 - def xmlrpc_get_module(self,cred_user, id_module=None):
239 """récupère un module précis dans la base ou tous les modules""" 240 if id_module : 241 # on récupère le module demandé 242 query = """select id, libelle, version from modules where id = %s""" 243 return self.dbpool.runQuery(query, (int(id_module),)).addCallbacks(self._got_modules,db_client_failed,callbackArgs=[cred_user]) 244 else : 245 # sinon on renvoie tous les modules 246 query = """select id, libelle, version from modules order by version desc, libelle""" 247 return self.dbpool.runQuery(query).addCallbacks(self._got_modules,db_client_failed,callbackArgs=[cred_user])
248
249 - def xmlrpc_get_dico(self,cred_user,id_module,id_variante=None):
250 """récupération du dictionnaire d'un module (valeurs par défaut)""" 251 # recherche du répertoire ou le dictionnaire est stocké 252 try: 253 query = "select version from modules where id = %s" 254 except: 255 return 0, u("""donnez l'id d'un module (nombre entier)""") 256 return self.dbpool.runQuery(query, (int(id_module),)).addCallbacks(self._get_dico,db_client_failed,callbackArgs=[id_module, id_variante])
257
258 - def _get_dico(self,data,id_module,id_variante=None):
259 # détection version de créole 260 try: 261 version = int(data[0][0]) 262 except: 263 version = 3 264 265 try: 266 # dictionnaire de base du module 267 if version == 1: 268 # module Eole1 269 path_dico = os.path.abspath(config.PATH_ZEPHIR)+os.sep+'modules'+os.sep+str(id_module)+os.sep+'dictionnaire' 270 # envoi des fichiers de configuration au programme de saisie 271 try: 272 fic = open(path_dico,'r') 273 except: 274 return 0, u("""dictionnaire non présent""") 275 276 # dictionnaire du module 277 lines = fic.readlines() 278 fic.close() 279 dictionnaire = [ unicode(line, 'ISO-8859-1').encode('UTF-8') for line in lines ] 280 # dictionnaires additionnels 281 if id_variante is not None: 282 dicos=os.path.abspath(config.PATH_ZEPHIR)+os.sep+'modules'+os.sep+str(id_module)+os.sep+'variantes'+os.sep+str(id_variante)+os.sep+'dicos' 283 for nom_fic in os.listdir(dicos): 284 if nom_fic.endswith('.eol') or nom_fic.endswith('.xml'): 285 # ajout d'un dictionnaire 286 fic = open(dicos+os.sep+nom_fic,'r') 287 lines = fic.readlines() 288 fic.close() 289 dictionnaire.extend([ unicode(line, 'ISO-8859-1').encode('UTF-8') for line in lines ]) 290 291 # dictionnaire complet (dictionnaire module + dico locaux) 292 dic_complet=dico.DicoEole(dico_zephir=[dictionnaire]) 293 294 # si un dico.eol existait déjà, on reprend les anciennes valeurs 295 if id_variante is not None: 296 path_dicovar = os.path.abspath(config.PATH_ZEPHIR)+os.sep+'modules'+os.sep+str(id_module)+os.sep+'variantes'+os.sep+str(id_variante)+os.sep+'dico.eol' 297 if os.path.isfile(path_dicovar): 298 # on instancie un dictionnaire depuis dico.eol 299 # et un autre avec le dictionnaire complet 300 f=file(path_dicovar) 301 lines = f.readlines() 302 f.close() 303 data = [ unicode(line, 'ISO-8859-1').encode('UTF-8') for line in lines ] 304 # dictionnaire des valeurs actuelles 305 dic_actuel=dico.DicoEole(dico_zephir=[data]).ParseDico() 306 dico_final = {} 307 # on réinsère les données existantes dans le dictionnaire 308 for variable, data in dic_complet.dictionnaire.items(): 309 # si la variable existait déjà, on reprend sa valeur 310 if dic_actuel.has_key(data[0]): 311 data[1] = dic_actuel[data[0]][0] 312 dico_final[variable]=data 313 # on remet le dictionnaire modifié en place dans dico_serveur 314 dic_complet.dictionnaire = dico_final 315 316 dicos=[base64.encodestring(dic_complet.save("/dev/null"))] 317 else: 318 # version creole2 319 # chargement de configuration pour un serveur Eole2 320 path_module = os.path.abspath(config.PATH_ZEPHIR)+os.sep+'modules'+os.sep+str(id_module) 321 path_dico = path_module+os.sep+'dicos' 322 # définition des dictionnaires à charger 323 dict_dirs = [path_dico] 324 if id_variante is not None: 325 dict_dirs.append(os.path.join(path_module,'variantes',str(id_variante),'dicos')) 326 # création de l'objet ZephirDict et lecture des valeurs existantes 327 dict_zeph = ZephirDict(dicos=dict_dirs, confdir=path_dico, mode='config', version='creole2') 328 if os.path.isfile(os.path.join(path_module,'module.eol')): 329 dict_zeph.dico.load_values(os.path.join(path_module,'module.eol')) 330 # traitement de la variable si demandé 331 if id_variante is not None: 332 path_var = os.path.join(path_module,'variantes',str(id_variante),'dico.eol') 333 dict_zeph.dico.load_values(os.path.join(path_var)) 334 dicos = dict_zeph.get_dict() 335 if dicos == None: 336 dicos = [] 337 except Exception, e: 338 return 0, u(str(e)) 339 340 return 1,u(dicos)
341
342 - def xmlrpc_get_vars(self,cred_user,id_module):
343 """récupération des libellés/familles des variables eole pour un module""" 344 # recherche du répertoire ou le dictionnaire est stocké 345 try: 346 query = "select id,version from modules where id = %s" 347 except: 348 return 0, u("""donnez l'id d'un module (nombre entier)""") 349 return self.dbpool.runQuery(query, (int(id_module),)).addCallbacks(self._get_vars,db_client_failed)
350
351 - def _get_vars(self,data):
352 # détection version de créole 353 try: 354 id_module = int(data[0][0]) 355 except: 356 return 0, u("""module non trouvé""") 357 try: 358 version = int(data[0][1]) 359 except: 360 version = 3 361 # dictionnaire de base du module 362 if version == 1: 363 # module Eole1 364 creole_files = [os.path.abspath(config.PATH_ZEPHIR)+os.sep+'modules'+os.sep+str(id_module)+os.sep+'dictionnaire'] 365 # récupération des familles de variables 366 dicos = [] 367 for dic in creole_files: 368 try: 369 # lecture du contenu des dictionnaires 370 fic = open(dic,'r') 371 lines = fic.readlines() 372 fic.close() 373 data = [ unicode(line, 'ISO-8859-1').encode('UTF-8') for line in lines ] 374 # stockage du contenu du dictionnaire 375 dicos.append(data) 376 except OSError: 377 pass 378 dict_zeph = ZephirDict(dicos=dicos, confdir='', mode='dico', version='creole1') 379 families = {} 380 else: 381 # version creole2 382 # chargement de configuration pour un serveur Eole2 383 path_module = os.path.abspath(config.PATH_ZEPHIR)+os.sep+'modules'+os.sep+str(id_module) 384 path_dico = path_module+os.sep+'dicos' 385 # définition des dictionnaires à charger 386 dict_dirs = [path_dico] 387 # création de l'objet ZephirDict et lecture des valeurs existantes 388 dict_zeph = ZephirDict(dicos=dict_dirs, confdir=path_dico, mode='config', version='creole2') 389 families = {} 390 menu = dict_zeph.get_menu(True) 391 for family in menu: 392 for var in family[2]: 393 families[var] = family[0] 394 395 # dictionnaire variable, libelle 396 vars_dict = {} 397 try: 398 var_data = dict_zeph.get_first() 399 while 1: 400 if families.has_key(var_data[0]): 401 family = families[var_data[0]] 402 else: 403 family = '' 404 vars_dict[var_data[0]] = [var_data[2],family] 405 var_data = dict_zeph.get_next() 406 except: 407 # on arrive en fin de dictionnaire 408 pass 409 410 return 1,u(vars_dict)
411
412 - def xmlrpc_save_dico(self,cred_user,dico_b64,id_module,id_variante=None,pass_var=""):
413 """mise à jour du dictionnaire d'un module (valeurs par défaut)""" 414 # recherche du libellé du module 415 self.parent.s_pool.check_mod_credential(cred_user, id_module) 416 if id_variante is not None: 417 self.parent.s_pool.check_var_credential(cred_user, id_variante) 418 query = "select modules.id, modules.libelle, modules.version, variantes.owner, variantes.passmd5 \ 419 from modules,variantes where modules.id=%s and modules.id=variantes.module and variantes.id=%s" 420 return self.dbpool.runQuery(query, (int(id_module), int(id_variante))).addCallbacks(self._save_dico, db_client_failed, callbackArgs=[cred_user,dico_b64,id_variante,pass_var]) 421 else: 422 query = """select id, libelle, version from modules where id=%s""" 423 return self.dbpool.runQuery(query, (int(id_module),)).addCallbacks(self._save_dico, db_client_failed, callbackArgs=[cred_user,dico_b64,id_variante,pass_var])
424
425 - def _save_dico(self,data,cred_user,dico_b64,id_variante=None,pass_var=""):
426 if data == []: 427 return 0,u("""module non retrouvé""") 428 # récupération id et libellé module 429 id_module = data[0][0] 430 libelle = data[0][1] 431 try: 432 version = int(data[0][2]) 433 except: 434 version = 3 435 if id_variante is not None: 436 # vérification owner/mot de passe 437 owner = data[0][3] 438 passmd5 = data[0][4] 439 if owner != cred_user: 440 # vérification du mot de passe 441 if passmd5 != pass_var and passmd5 not in [None,'', BLANK_MD5]: 442 # mauvais mot de passe 443 return 0,u('mot de passe incorrect pour cette variante') 444 # gestion des différentes versions de creole 445 if version == 1: 446 try: 447 # décodage du dictionnaire 448 dico = base64.decodestring(dico_b64) 449 # creole 1 -> encodage en latin-1 450 dico = unicode(dico,'UTF-8').encode('ISO-8859-1') 451 # sauvegarde 452 if id_variante is None: 453 path_dico = os.path.abspath(config.ROOT_DIR)+'/dictionnaires/dico-%s' % libelle 454 else: 455 path_dico = os.path.abspath(config.PATH_ZEPHIR)+os.sep+'modules'+os.sep+str(id_module)+os.sep+'variantes'+os.sep+str(id_variante)+os.sep+'dico.eol' 456 fic_zephir = open(path_dico,'w') 457 fic_zephir.write(dico) 458 fic_zephir.close() 459 except: 460 return 0,u("""erreur de sauvegarde du dictionnaire""") 461 else: 462 if id_variante is None: 463 path_dico = os.path.abspath(config.PATH_ZEPHIR)+os.sep+'modules'+os.sep+str(id_module)+os.sep+'module.eol' 464 else: 465 path_dico = os.path.abspath(config.PATH_ZEPHIR)+os.sep+'modules'+os.sep+str(id_module)+os.sep+'variantes'+os.sep+str(id_variante)+os.sep+'dico.eol' 466 values = eval(dico_b64[-1]) 467 try: 468 parser = ConfigParser.ConfigParser() 469 parser._sections = values 470 fic_zephir = open(path_dico,'w') 471 parser.write(fic_zephir) 472 fic_zephir.close() 473 except: 474 return 0,u("""erreur de sauvegarde du dictionnaire""") 475 476 return 1,u('ok')
477
478 - def xmlrpc_get_mod_dict(self,cred_user,id_module):
479 """renvoie la liste des dictionnaires d'un module. 480 utile pour les modules eole2 (fichier fixé pour les modules eole1) 481 """ 482 self.parent.s_pool.check_mod_credential(cred_user, id_module) 483 query = "select id, version from modules where id=%s" 484 return self.dbpool.runQuery(query, (int(id_module),)).addCallbacks(self._get_mod_dict, db_client_failed)
485
486 - def _get_mod_dict(self,data):
487 # définition du chemin vers les dictionnaires 488 id_module, version = data[0] 489 try: 490 version = int(version) 491 except: 492 version = 3 493 if version == 1: 494 # non géré sur creole1 495 return 1, [] 496 try: 497 dest_dir=os.path.join(os.path.abspath(config.PATH_MODULES),str(id_module),"dicos") 498 content = [] 499 # cas d'un répertoire 500 for dict in os.listdir(dest_dir): 501 if dict.endswith('.xml'): 502 content.append(dict) 503 return 1, u(content) 504 except: 505 return 0,u("""erreur de parcours du répertoire des dictionnaires""")
506
507 - def xmlrpc_del_mod_dict(self,cred_user,id_module,dico_name):
508 """renvoie la liste des dictionnaires d'un module. 509 utile pour les modules eole2 (fichier fixé pour les modules eole1) 510 """ 511 # définition du chemin vers les dictionnaires 512 self.parent.s_pool.check_mod_credential(cred_user, id_module) 513 try: 514 fic_dest = os.path.join(os.path.abspath(config.PATH_MODULES),str(id_module),"dicos",dico_name) 515 assert os.path.isfile(fic_dest) 516 except: 517 return 0,u("""dictionnaire inexistant %s""" % dico_name) 518 # on supprime le fichier 519 try: 520 os.unlink(fic_dest) 521 return 1, "OK" 522 except: 523 return 0,u("""erreur lors de la suppression du dictionnaire""")
524 525 #################################### 526 ## gestion des variantes des modules 527 #################################### 528
529 - def _got_variantes(self,variantes,cred_user):
530 """formate les données lues dans la table variantes pour 531 l'envoyer à une application zephir (liste de dictionnaires)""" 532 l=[] 533 for variante in variantes: 534 owner = variante[3] 535 if owner == None: 536 owner = "" 537 try: 538 self.parent.s_pool.check_var_credential(cred_user, variante[0]) 539 except ResourceAuthError: 540 # non autorisé : module suivant 541 continue 542 l.append({'id':variante[0],'module':variante[1],'libelle':variante[2],'owner':owner}) 543 return 1,u(l)
544
545 - def xmlrpc_copy_variante(self,cred_user,module,id_var_src="",libelle="",passmd5="",keep_perms=False,id_var=""):
546 """Copie une variante existante sur une nouvelle variante""" 547 # recherche des données de l'ancienne variante 548 try: 549 var_src = int(id_var_src) 550 module = int(module) 551 if id_var == "": 552 assert libelle != "" 553 else: 554 # écrasement d'une variante existante 555 id_var = int(id_var) 556 except: 557 return 0, u("""paramètres invalides""") 558 559 # lecture du mot de passe et du module de l'ancienne variante 560 query = """select module,owner,passmd5 from variantes where id=%s""" 561 return self.dbpool.runQuery(query, (int(var_src),)).addCallbacks(self._copy_variante, db_client_failed,callbackArgs=[cred_user,var_src,libelle,module,passmd5,keep_perms,id_var])
562
563 - def _copy_variante(self,data,cred_user,var_src,libelle,module,passmd5,keep_perms,id_var):
564 """insertion de la nouvelle variante""" 565 try: 566 module_src = data[0][0] 567 if keep_perms and id_var == "": 568 # on veut conserver le propriétaire/mot de passe 569 cred_user = data[0][1] 570 passmd5 = data[0][2] 571 except: 572 # variante créée non trouvée dans la base 573 return 0,u("""module d'origine non retrouvé dans la base""") 574 575 if id_var != "": 576 # copie sur une variante existante 577 query = """select * from variantes where id=%s""" 578 return self.dbpool.runQuery(query, (int(id_var),)).addCallbacks(self._copy_variante3, db_client_failed,callbackArgs=[var_src,module_src,id_var,cred_user,passmd5]) 579 else: 580 # création d'une copie de variante 581 query = """insert into variantes (module,libelle,owner,passmd5) values (%s,E%s,%s,%s)""" 582 params = (int(module), libelle, cred_user, passmd5) 583 # id assigné automatiquement dans postgresql 584 # on effectue l'insertion 585 return self.dbpool.runOperation(query, params).addCallbacks(self._copy_variante2, db_client_failed,callbackArgs=[var_src,module_src,libelle,module,id_var,cred_user,passmd5])
586
587 - def _copy_variante2(self,data,var_src,module_src,libelle,module,id_var,cred_user,passmd5):
588 """recherche de l'id de la variante créée""" 589 590 query = """select * from variantes where libelle=E%s and module=%s""" 591 params = (libelle, int(module)) 592 return self.dbpool.runQuery(query, params).addCallbacks(self._copy_variante3, db_client_failed,callbackArgs=[var_src,module_src,id_var,cred_user,passmd5])
593
594 - def _copy_variante3(self,data,var_src,module_src,id_var,cred_user,passmd5):
595 """copie l'arborescence de la variante source""" 596 try: 597 var_dest = data[0][0] 598 module = data[0][1] 599 libelle = data[0][2] 600 owner = data[0][3] 601 pass_var = data[0][4] 602 except: 603 # variante créée non trouvée dans la base 604 return 0,u("""nouvelle variante non retrouvée dans la base""") 605 else: 606 # on recopie l'arborescence de la variante source 607 rep_src=os.path.abspath(config.PATH_MODULES)+os.sep+str(module_src)+os.sep+'variantes'+os.sep+str(var_src) 608 rep_dest=os.path.abspath(config.PATH_MODULES)+os.sep+str(module)+os.sep+'variantes'+os.sep+str(var_dest) 609 try: 610 if id_var == "": 611 if str(var_dest) not in self.parent.s_pool.stats['serv_variantes']: 612 self.parent.s_pool.stats['serv_variantes'][str(var_dest)] = 0 613 else: 614 # modification d'une variante existante 615 if owner != cred_user: 616 # vérification du mot de passe 617 if passmd5 != pass_var and pass_var not in [None,'', BLANK_MD5]: 618 # mauvais mot de passe 619 return 0, u("""Mauvais mot de passe pour la variante de destination""") 620 shutil.rmtree(rep_dest) 621 shutil.copytree(rep_src,rep_dest) 622 except: 623 traceback.print_exc() 624 return 0,u("""erreur de copie de l'arborescence de la variante""") 625 626 query = """select id, libelle, version from modules where id = %s or id = %s""" 627 params = (int(module_src), int(module)) 628 return self.dbpool.runQuery(query, params).addCallbacks(self._copy_variante4, db_client_failed,callbackArgs=[var_src, var_dest, module_src, module, id_var])
629
630 - def _copy_variante4(self, data, var_src, var_dest, module_src, module, id_var):
631 """stocke la concordance entre les variantes si nécessaire""" 632 if id_var == "": 633 version_src = version_dest = 0 634 libelle_src = libelle_dest = "" 635 try: 636 for mod in data: 637 if mod[0] == module_src: 638 version_src = int(mod[2]) 639 libelle_src = mod[1][:mod[1].rindex("-")] 640 elif mod[0] == module: 641 version_dest = int(mod[2]) 642 libelle_dest = mod[1][:mod[1].rindex("-")] 643 except: 644 log.msg('copie de variante : erreur lors de la recherche des version des modules sources et destination') 645 # stockage de la liaison entre les 2 variantes si copie pour upgrade entre 2 version d'un module 646 version_delta = version_dest - version_src 647 if libelle_src == libelle_dest and version_delta == 1: 648 query = """insert into migration_variantes (id_source, id_dest) values (%s,%s)""" 649 params = (int(var_src), int(var_dest)) 650 return self.dbpool.runOperation(query, params).addCallbacks(lambda x:(1, var_dest), db_client_failed) 651 return 1, var_dest
652
653 - def xmlrpc_add_variante(self,cred_user, module, libelle, pass_var=""):
654 """ajoute une variante à un module""" 655 self.parent.s_pool.check_mod_credential(cred_user, module) 656 # on vérifie qu'on a bien récupéré un module 657 if module and libelle: 658 query = """insert into variantes (module,libelle,owner,passmd5) values (%s,E%s,E%s,%s)""" 659 params = (int(module), libelle, cred_user, pass_var) 660 # id assigné automatiquement dans postgresql 661 # on effectue l'insertion 662 return self.dbpool.runOperation(query, params).addCallbacks(self._add_variante1, db_client_failed,callbackArgs=[libelle,module]) 663 else: 664 # des attributs manquent 665 return 0, u("""donnez un id de module et un libellé""")
666
667 - def _add_variante1(self,data,libelle,module):
668 """recherche de l'id de la variante créée""" 669 # on récupère l'id de la variante créée 670 query = """select * from variantes where libelle ilike E%s and module = %s""" 671 params = (libelle, int(module)) 672 return self.dbpool.runQuery(query, params).addCallbacks(self._add_variante2,db_client_failed)
673
674 - def _add_variante2(self,variante):
675 """met en place l'arborescence d'une nouvelle variante""" 676 try: 677 id_variante = variante[0][0] 678 module = variante[0][1] 679 libelle = variante[0][2] 680 except: 681 # variante créée non trouvée dans la base 682 return 0,u("""nouvelle variante non retrouvée dans la base""") 683 else: 684 # on créé l'arborescence de la variante dans les modules 685 os.makedirs(os.path.abspath(config.PATH_MODULES)+os.sep+str(module)+os.sep+'variantes'+os.sep+str(id_variante)) 686 os.makedirs(os.path.abspath(config.PATH_MODULES)+os.sep+str(module)+os.sep+'variantes'+os.sep+str(id_variante)+os.sep+'patchs') 687 os.makedirs(os.path.abspath(config.PATH_MODULES)+os.sep+str(module)+os.sep+'variantes'+os.sep+str(id_variante)+os.sep+'dicos') 688 os.makedirs(os.path.abspath(config.PATH_MODULES)+os.sep+str(module)+os.sep+'variantes'+os.sep+str(id_variante)+os.sep+'fichiers_perso') 689 os.makedirs(os.path.abspath(config.PATH_MODULES)+os.sep+str(module)+os.sep+'variantes'+os.sep+str(id_variante)+os.sep+'fichiers_zephir') 690 # on met à jour les statistiques 691 self.parent.s_pool.stats['serv_variantes'][str(id_variante)] = 0 692 return 1,id_variante
693 694
695 - def xmlrpc_del_variante(self,cred_user,id_variante):
696 """suppression d'une variante de la base zephir""" 697 self.parent.s_pool.check_var_credential(cred_user, id_variante) 698 if id_variante: 699 query = """select * from variantes where id = %s""" 700 # on récupère les données de la variante 701 return self.dbpool.runQuery(query, (int(id_variante),)).addCallbacks(self._del_variante, db_client_failed) 702 else: 703 return 0,u("""donnez un identifiant de variante""")
704
705 - def _del_variante(self,variante):
706 """supprime la variante de la base de données""" 707 try: 708 id_variante = variante[0][0] 709 id_module = variante[0][1] 710 libelle = variante[0][2] 711 except: 712 # variante non trouvée dans la base 713 return 0,u("""variante non trouvée dans la base""") 714 else: 715 # on interdit la supression de la variante standard 716 if libelle == 'standard': 717 return 0, u("""la variante standard ne peut pas être supprimée""") 718 # suppression variante dans la base 719 query = """delete from variantes where id = %s""" 720 return self.dbpool.runOperation(query, (int(id_variante),)).addCallbacks(self._del_variante2, db_client_failed,callbackArgs=[id_module,id_variante])
721
722 - def _del_variante2(self,result,id_module,id_variante):
723 """supression de l'arborescence de la variante""" 724 del(self.parent.s_pool.stats['serv_variantes'][str(id_variante)]) 725 # ok, on supprime son arborescence dans zephir/modules/variantes/id_variante 726 variante_dir=os.path.abspath(config.PATH_MODULES)+os.sep+str(id_module)+os.sep+"variantes"+os.sep+str(id_variante) 727 try: 728 shutil.rmtree(variante_dir) 729 except: 730 # remonter code -1 si supression de répertoire impossible ? 731 return 0,u("""erreur de supression du répertoire de la variante""") 732 return 1, u('ok')
733
734 - def xmlrpc_fichiers_variante(self,cred_user,id_variante,show_details=False):
735 """ retourne la liste des fichiers personnalisés pour cette variante """ 736 self.parent.s_pool.check_var_credential(cred_user, id_variante) 737 query = """select id,module from variantes where id = %s""" 738 return self.dbpool.runQuery(query, (int(id_variante),)).addCallbacks(self._fichiers_zephir,db_client_failed,callbackArgs=[show_details])
739
740 - def _fichiers_zephir(self,data,show_details):
741 """recherche les fichiers liés à une variante""" 742 if data == []: 743 return 0,u("serveur inconnu de zephir") 744 else: 745 id_variante = int(data[0][0]) 746 id_module = int(data[0][1]) 747 # répertoire de stockage de la variante sur zephir 748 variante_dir = os.path.abspath(config.PATH_ZEPHIR)+os.sep+'modules'+os.sep+str(id_module)+os.sep+'variantes'+os.sep+str(id_variante) 749 # création du dictionnaire de listes des différents fichiers 750 dico_res={} 751 try: 752 # dictionnaires additionnels 753 liste_dicos = [] 754 liste_dicos_var = [] 755 for fic in os.listdir(variante_dir+os.sep+'dicos'): 756 if fic.endswith('.eol') or fic.endswith('.xml'): 757 liste_dicos_var.append(fic) 758 dico_res['dicos_var'] = liste_dicos_var 759 except OSError: 760 dico_res['dicos_var'] = ['répertoire non trouvé !'] 761 try: 762 # fichiers templates variante 763 dico_res['persos_var'] = (os.listdir(variante_dir+os.sep+'fichiers_perso')) 764 except OSError: 765 dico_res['persos_var'] = ['répertoire non trouvé !'] 766 try: 767 # patchs variante 768 dico_res['patchs_var'] = os.listdir(variante_dir+os.sep+'patchs') 769 except OSError: 770 dico_res['patchs_var'] = ['répertoire non trouvé !'] 771 try: 772 # RPMS variante 773 # lecture de la liste des rpms supplémentaires 774 fic = open(variante_dir+'/fichiers_zephir/fichiers_variante') 775 data = fic.read().split("\n") 776 fic.close() 777 # recherche de la section des RPMS 778 liste_pkg_var = [] 779 section_rpm = 0 780 for ligne in data: 781 ligne = ligne.strip() 782 if section_rpm == 1: 783 # on regarde si on a bien affaire à un paquetage 784 if not ligne.startswith('#') and ligne != '': 785 # on affiche le nom du paquetage 786 liste_pkg_var.append(ligne) 787 if ligne == '%%': 788 section_rpm = 1 789 dico_res['rpms_var'] = liste_pkg_var 790 except IOError: 791 dico_res['rpms_var'] = [] 792 try: 793 # fichiers du module 794 liste_fic=[] 795 try: 796 f=open(variante_dir+os.sep+'fichiers_zephir/fichiers_variante') 797 old_content=f.read() 798 f.close() 799 fichiers=old_content.split('%%\n')[0] 800 except: 801 fichiers="" 802 for f in fichiers.split('\n'): 803 if f.strip().startswith("""/"""): 804 f_local = os.path.join(variante_dir,'fichiers_zephir',os.path.basename(f.strip())) 805 if show_details: 806 f_info = config.get_file_info(f_local) 807 liste_fic.append((f,f_info)) 808 elif os.path.exists(f_local): 809 liste_fic.append(f) 810 dico_res['fichiers_var'] = liste_fic 811 # for fic in os.listdir(variante_dir+os.sep+'fichiers_zephir'): 812 # if fic != 'fichiers_variante': 813 # liste_dicos.append(fic) 814 # dico_res['fichiers_var'] = liste_dicos 815 except: 816 dico_res['fichiers_var'] = ['répertoire non trouvé !'] 817 return 1,u(dico_res)
818
819 - def xmlrpc_get_variante_perms(self, cred_user, id_variante, filepath=""):
820 """renvoie les informations de permissions associées à un(des) fichier(s) 821 """ 822 # on recherche le répertoire ou la variante est stockée 823 query = """select id,module from variantes where id=%s""" 824 return self.dbpool.runQuery(query, (int(id_variante),)).addCallbacks(self._get_variante_perms,db_client_failed,callbackArgs=[filepath])
825
826 - def _get_variante_perms(self, data, filepath):
827 """crée l'archive de la variante et la renvoie""" 828 if data != []: 829 id_variante = data[0][0] 830 id_module = data[0][1] 831 # répertoire de la variante 832 var_dir=os.path.abspath(config.PATH_MODULES)+os.sep+str(id_module)+os.sep+"variantes"+os.sep+str(id_variante) 833 try: 834 id_var = int(id_variante) 835 836 except (KeyError, ValueError): 837 return 0, u("""variante inconnue : %s""" % str(id_var)) 838 else: 839 result = self.parent.s_pool.get_file_perms(var_dir, filepath) 840 return 1, u(result)
841
842 - def xmlrpc_del_variante_perms(self, cred_user, id_variante, filepath="", pass_var=""):
843 """supprime les informations de permissions associées à un(des) fichier(s) 844 """ 845 # on recherche le répertoire ou la variante est stockée 846 query = """select id,module,owner,passmd5 from variantes where id=%s""" 847 return self.dbpool.runQuery(query, (int(id_variante),)).addCallbacks(self._del_variante_perms,db_client_failed,callbackArgs=[cred_user,filepath,pass_var])
848
849 - def _del_variante_perms(self, data, cred_user, filepath, pass_var):
850 """crée l'archive de la variante et la renvoie""" 851 if data != []: 852 id_variante = data[0][0] 853 id_module = data[0][1] 854 owner = data[0][2] 855 passmd5 = data[0][3] 856 # vérification owner/mot de passe 857 if owner != cred_user: 858 # vérification du mot de passe 859 if passmd5 != pass_var and passmd5 not in [None,'',BLANK_MD5]: 860 # mauvais mot de passe 861 return 0,u('mot de passe incorrect pour cette variante') 862 # répertoire de la variante 863 var_dir=os.path.abspath(config.PATH_MODULES)+os.sep+str(id_module)+os.sep+"variantes"+os.sep+str(id_variante) 864 try: 865 id_var = int(id_variante) 866 except (KeyError, ValueError): 867 return 0, u("""variante inconnue : %s""" % str(id_var)) 868 else: 869 result = self.parent.s_pool.del_file_perms(var_dir, filepath) 870 return 1, u(result)
871
872 - def xmlrpc_set_variante_perms(self, cred_user, id_variante, rights, pass_var=""):
873 """enregistre les informations de permissions associées à un(des) fichier(s) 874 @param rights: dictionnaire au format suviant : {'filepath':[mode,ownership]} 875 """ 876 # on recherche le répertoire ou la variante est stockée 877 query = """select id,module,owner,passmd5 from variantes where id=%s""" 878 return self.dbpool.runQuery(query, (int(id_variante),)).addCallbacks(self._set_variante_perms,db_client_failed,callbackArgs=[cred_user,rights,pass_var])
879
880 - def _set_variante_perms(self, data, cred_user, rights, pass_var):
881 """crée l'archive de la variante et la renvoie""" 882 if data != []: 883 id_variante = data[0][0] 884 id_module = data[0][1] 885 owner = data[0][2] 886 passmd5 = data[0][3] 887 # vérification owner/mot de passe 888 if owner != cred_user: 889 # vérification du mot de passe 890 if passmd5 != pass_var and passmd5 not in [None,'',BLANK_MD5]: 891 # mauvais mot de passe 892 return 0,u('mot de passe incorrect pour cette variante') 893 # répertoire de la variante 894 var_dir=os.path.abspath(config.PATH_MODULES)+os.sep+str(id_module)+os.sep+"variantes"+os.sep+str(id_variante) 895 try: 896 id_var = int(id_variante) 897 except (KeyError, ValueError): 898 return 0, u("""variante inconnue : %s""" % str(id_var)) 899 else: 900 res = self.parent.s_pool.set_file_perms(rights, var_dir) 901 if res: 902 return 1,"OK" 903 else: 904 return 0, u("""erreur d'enregistrement des permissions""")
905
906 - def xmlrpc_get_variante(self,cred_user,id_variante=None):
907 """récupère la liste d'une variante (ou toutes)""" 908 if id_variante : 909 query = """select * from variantes where id=%s """ 910 return self.dbpool.runQuery(query, (int(id_variante),)).addCallbacks(self._got_variantes,db_client_failed,callbackArgs=[cred_user]) 911 else : 912 query = """select * from variantes order by module desc, id desc""" 913 return self.dbpool.runQuery(query).addCallbacks(self._got_variantes,db_client_failed,callbackArgs=[cred_user])
914
915 - def xmlrpc_edit_variante(self,cred_user,id_variante,dico_modifs,pass_var=""):
916 """modification d'une variante 917 cette fonction prend en compte un dictionnaire qui indique les 918 champs à modifier et leur nouvelle valeur. l'application cliente 919 doit s'assurer que ces champs existent dans la base""" 920 self.parent.s_pool.check_var_credential(cred_user, id_variante) 921 # vérification du propriétaire/mot de passe 922 query = """select owner,passmd5 from variantes where id=%s""" 923 return self.dbpool.runQuery(query, (int(id_variante),)).addCallbacks(self._edit_variante,db_client_failed, 924 callbackArgs=[cred_user,id_variante,dico_modifs,pass_var])
925
926 - def _edit_variante(self,data,cred_user,id_variante,dico_modifs,pass_var):
927 # on vérifie que l'identifiant n'est pas modifié 928 if dico_modifs == {}: 929 return 1,u("""aucune modification demandée""") 930 owner = data[0][0] 931 passmd5 = data[0][1] 932 # vérification owner/mot de passe 933 if owner != cred_user: 934 # vérification du mot de passe 935 if passmd5 != pass_var and passmd5 not in [None,'',BLANK_MD5]: 936 # mauvais mot de passe 937 return 0,u('mot de passe incorrect pour cette variante') 938 if ('id' in dico_modifs.keys()) or ('module' in dico_modifs.keys()): 939 return 0,u("""l'identifiant et le module ne peuvent pas être modifiés""") 940 if ('owner' in dico_modifs.keys()) or ('passmd5' in dico_modifs.keys()): 941 return 0,u("""modification du propriétaire ou mot de passe interdits""") 942 # construction de la requête SQL de modification 943 requete = ["update variantes set "] 944 params = [] 945 for cle in dico_modifs.keys(): 946 requete.append(str(cle)) 947 requete.append("=E%s, ") 948 params.append(str(dico_modifs[cle])) 949 string_fin=""" where id=%s""" 950 params.append(int(id_variante)) 951 query = "".join(requete)[:-2] 952 query += string_fin 953 return self.dbpool.runOperation(query, params).addCallbacks(lambda x:(1,'ok'), db_client_failed)
954
955 - def xmlrpc_get_migration_infos(self, cred_user, id_module):
956 """récupère la liste des variantes d'un module et des variantes de migration définies 957 """ 958 try: 959 id_module = int(id_module) 960 except: 961 return 0,u("identifiant de module invalide") 962 self.parent.s_pool.check_mod_credential(cred_user, id_module) 963 # récupération des modules 964 query = """select id, libelle, version from modules""" 965 return self.dbpool.runQuery(query).addCallbacks(self._get_migration_infos,db_client_failed,callbackArgs=[id_module])
966
967 - def _get_migration_infos(self, data, id_module):
968 # recherche des modules vers lesquels on peut migrer 969 mod_src_lib = "" 970 mod_src_version = 0 971 info_modules = {} 972 for module in data: 973 if module[0] == id_module: 974 mod_src_lib = module[1] 975 mod_src_version = int(module[2]) 976 break 977 migration_infos = {} 978 if mod_src_version == 1: 979 return 1, [] 980 elif mod_src_version > 1: 981 mod_src_name = mod_src_lib[:mod_src_lib.rindex('-')] 982 # migration non standard acceptées 983 allowed_upgrades = [mod_src_version+1] 984 if mod_src_name in config.allowed_upgrades and mod_src_version in config.allowed_upgrades[mod_src_name]: 985 allowed_upgrades.extend(config.allowed_upgrades[mod_src_name][mod_src_version]) 986 for module in data: 987 mod_name = module[1][:module[1].rindex('-')] 988 mod_version = int(module[2]) 989 if mod_name == mod_src_name: 990 if mod_version in allowed_upgrades: 991 info_modules[module[0]] = [module[1],int(module[2])] 992 migration_infos[mod_version] = [[],[]] 993 query="""select modules.version, id_source, id_dest, var_dst.module from migration_variantes, modules, variantes as var_dst, variantes as var_src where id_source=var_src.id and var_src.module=%s and var_dst.id=id_dest and modules.id = var_dst.module""" 994 return self.dbpool.runQuery(query, (int(id_module),)).addCallbacks(self._get_migration_infos2,db_client_failed,callbackArgs=[id_module, migration_infos, info_modules]) 995 else: 996 return 0,u("module inexistant dans la base")
997
998 - def _get_migration_infos2(self, data, id_module, migration_infos, info_modules):
999 # correspondances déjà définies 1000 for var_migration in data: 1001 if var_migration[0] in migration_infos: 1002 migration_infos[var_migration[0]][1].append([var_migration[1], var_migration[2]]) 1003 query = """select id, module from variantes""" 1004 return self.dbpool.runQuery(query).addCallbacks(self._get_migration_infos3, db_client_failed,callbackArgs=[id_module, migration_infos, info_modules])
1005
1006 - def _get_migration_infos3(self, data, id_module, migration_infos, info_modules):
1007 # liste des destinations possibles pour chaque module 1008 for id_var, id_mod in data: 1009 # on garde seulement les modules de même type 1010 if id_mod in info_modules: 1011 vers_mod = info_modules[id_mod][1] 1012 # si migration autorisée 1013 if vers_mod in migration_infos: 1014 # liste des variantes dispos 1015 migration_infos[vers_mod][0].append(id_var) 1016 result = [] 1017 for vers, data in migration_infos.items(): 1018 result.append((vers, data[0], data[1])) 1019 return 1, result
1020
1021 - def xmlrpc_variantes_upgrade(self, cred_user, var_src, var_migr):
1022 """sauvegarde les équivalences d'une variable pour upgrade_auto 1023 """ 1024 try: 1025 var_src = int(var_src) 1026 var_dest = [] 1027 if type(var_migr) != list: 1028 var_migr = [var_migr] 1029 for var in var_migr: 1030 var_dest.append(int(var)) 1031 except: 1032 return 0,u("identifiant de variante invalide") 1033 self.parent.s_pool.check_var_credential(cred_user, var_src) 1034 # supression des anciennes correspondances 1035 query = """delete from migration_variantes where id_source=%s""" 1036 return self.dbpool.runOperation(query, (int(var_src),)).addCallbacks(self._variantes_upgrade2, db_client_failed, callbackArgs=[var_src, var_dest])
1037
1038 - def _variantes_upgrade2(self, result, var_src, var_dest):
1039 """sauvegarde les équivalences d'une variable pour upgrade_auto 1040 """ 1041 if var_dest != []: 1042 params = [] 1043 inserts = [] 1044 for dst in var_dest: 1045 inserts.append('(%s,%s)') 1046 params.extend([int(var_src), int(dst)]) 1047 query = """insert into migration_variantes (id_source, id_dest) values %s""" % ", ".join(inserts) 1048 return self.dbpool.runOperation(query, params).addCallbacks(lambda x:(1,'ok'), db_client_failed) 1049 else: 1050 return 1, 'ok'
1051
1052 - def xmlrpc_add_files(self,cred_user,id_variante,dico_files,passwd="",encode=False):
1053 """ajoute des fichiers, patchs, dictionnaires à une variante 1054 """ 1055 self.parent.s_pool.check_var_credential(cred_user, id_variante) 1056 query="select modules.version,variantes.id,variantes.module,variantes.owner,variantes.passmd5 from variantes,modules where variantes.id=%s and modules.id=variantes.module" 1057 return self.dbpool.runQuery(query, (int(id_variante),)).addCallbacks(self._add_files,db_client_failed,callbackArgs=[dico_files,cred_user,passwd,encode])
1058
1059 - def _add_files(self,data,dico_files,cred_user,passwd,encode):
1060 """ajoute des fichiers, patchs, dictionnaires,rpms à une variante 1061 """ 1062 mod_version = data[0][0] 1063 try: 1064 mod_version = int(mod_version) 1065 except: 1066 mod_version = 3 1067 id_variante = data[0][1] 1068 id_module = data[0][2] 1069 owner = data[0][3] 1070 pass_var = data[0][4] 1071 # si la variante ne nous appartient pas, on interdit la modification si mauvais mot de passe 1072 if owner != cred_user: 1073 # vérification du mot de passe 1074 if passwd != pass_var and pass_var not in [None,'',BLANK_MD5]: 1075 # mauvais mot de passe 1076 return 0,u('mot de passe incorrect pour cette variante') 1077 # on met en place les différents types de fichiers 1078 dest_dir=os.path.abspath(config.PATH_MODULES)+os.sep+str(id_module)+os.sep+"variantes"+os.sep+str(id_variante) 1079 # dans le cas d'un serveur eole1, on encode le contenu des fichiers en iso8859 si nécessaire 1080 if mod_version == 1 and encode == True: 1081 for type_f, files in dico_files.items(): 1082 if type_f in ['dicos_var','patchs_var','persos_var','fichiers_var']: 1083 encoded_files = [] 1084 for fichier in dico_files[type_f]: 1085 content = unicode(base64.decodestring(fichier[1]),config.charset).encode('ISO-8859-1') 1086 localpath = "" 1087 if len(fichier) == 3: 1088 localpath = fichier[2] 1089 encoded_files.append([fichier[0], base64.encodestring(content),localpath]) 1090 dico_files[type_f] = encoded_files 1091 # dictionnaires locaux 1092 for dico in dico_files['dicos_var']: 1093 try: 1094 if dico[0] != "": 1095 f=open(dest_dir+os.sep+'dicos'+os.sep+os.path.basename(dico[0].replace("\\","/")),'w') 1096 f.write(base64.decodestring(dico[1])) 1097 f.close() 1098 except: 1099 return 0,u("erreur de sauvegarde de %s" % dico) 1100 for template in dico_files['persos_var']: 1101 try: 1102 if template[0] != "": 1103 f=open(dest_dir+os.sep+'fichiers_perso'+os.sep+os.path.basename(template[0].replace("\\","/")),'w') 1104 f.write(base64.decodestring(template[1])) 1105 f.close() 1106 except: 1107 return 0,u("erreur de sauvegarde de %s" % template) 1108 for patch in dico_files['patchs_var']: 1109 try: 1110 if patch[0] != "": 1111 f=open(dest_dir+os.sep+'patchs'+os.sep+os.path.basename(patch[0].replace("\\","/")),'w') 1112 f.write(base64.decodestring(patch[1])) 1113 f.close() 1114 except: 1115 return 0,u("erreur de sauvegarde de %s" % patch) 1116 # on reprend la liste des fichiers existants 1117 try: 1118 f=open(dest_dir+os.sep+'fichiers_zephir/fichiers_variante') 1119 old_content=f.read() 1120 f.close() 1121 fichiers=old_content.split('%%\n')[0] 1122 rpms=old_content.split('%%\n')[1] 1123 except: 1124 fichiers="""# section 1 1125 # liste des fichiers à sauvegarder 1126 # (ne pas modifier sauf pour créer ou mettre à jour la variante)""" 1127 rpms="""# section 2 1128 # inscrire les noms des paquetages qui seront installés à la mise à jour du serveur 1129 # (ils doivent être présents sur le serveur de mise à jour)""" 1130 1131 for fichier in dico_files['fichiers_var']: 1132 # on ajoute le fichier à la liste si il n'est pas déjà présent 1133 localpath = "" 1134 if len(fichier) == 3: 1135 localpath = fichier[2] 1136 # on ajoute le fichier à la liste si il n'est pas déjà présent et si il n'est pas dans un sous répertoire 1137 nom_fic = fichier[0].replace("\\","/") 1138 # on supprime les séparateurs en fin de ligne 1139 if fichier[0].endswith('/'): 1140 nom_fic = fichier[0][:-1] 1141 if fichier[0].endswith("\\"): 1142 nom_fic = fichier[0][:-2] 1143 if nom_fic not in fichiers.split('\n') and localpath == "": 1144 fichiers = fichiers.strip() + '\n' + nom_fic +'\n' 1145 # on écrit le contenu du fichier 1146 try: 1147 if nom_fic != "": 1148 if localpath == "": 1149 f=open(os.path.join(dest_dir,'fichiers_zephir',os.path.basename(nom_fic)),'w') 1150 else: 1151 f=open(os.path.join(dest_dir,localpath,os.path.basename(nom_fic)),'w') 1152 f.write(base64.decodestring(fichier[1])) 1153 f.close() 1154 except: 1155 return 0,u("erreur de sauvegarde de %s" % fichier) 1156 1157 # rpms 1158 for rpm in dico_files['rpms_var']: 1159 # on ajoute le rpm si il n'est pas présent 1160 if rpm not in rpms.split('\n'): 1161 rpms = rpms.strip() + '\n' + rpm +'\n' 1162 1163 f=open(dest_dir+os.sep+'fichiers_zephir/fichiers_variante','w') 1164 f.write(fichiers+"%%\n"+rpms) 1165 f.close() 1166 return 1,u("ok")
1167
1168 - def xmlrpc_del_files(self,cred_user,id_variante,dico_files,passwd=None):
1169 """suppression de fichiers, patchs, dictionnaires d'une variante 1170 """ 1171 self.parent.s_pool.check_var_credential(cred_user, id_variante) 1172 query = "select id,module,owner,passmd5 from variantes where id=%s" 1173 return self.dbpool.runQuery(query, (int(id_variante),)).addCallbacks(self._del_files,db_client_failed,callbackArgs=[dico_files,cred_user,passwd])
1174
1175 - def _del_files(self,data,dico_files,cred_user,passwd):
1176 """supression de fichiers, patchs, dictionnaires,rpms d'une variante 1177 """ 1178 id_variante = data[0][0] 1179 id_module = data[0][1] 1180 owner = data[0][2] 1181 pass_var = data[0][3] 1182 # si la variante ne nous appartient pas, on interdit la modification si mauvais mot de passe 1183 if owner != cred_user: 1184 # vérification du mot de passe 1185 if passwd != pass_var and pass_var not in [None,'',BLANK_MD5]: 1186 # mauvais mot de passe 1187 return 0,u('mot de passe incorrect pour cette variante') 1188 # on met en place les différents types de fichiers 1189 dest_dir=os.path.abspath(config.PATH_MODULES)+os.sep+str(id_module)+os.sep+"variantes"+os.sep+str(id_variante) 1190 # dictionnaires locaux 1191 for dico in dico_files['dicos_var']: 1192 try: 1193 if dico != "": 1194 os.unlink(dest_dir+os.sep+'dicos'+os.sep+dico) 1195 except: 1196 return 0,u("erreur de suppression de %s" % dico) 1197 for template in dico_files['persos_var']: 1198 try: 1199 if template != "": 1200 os.unlink(dest_dir+os.sep+'fichiers_perso'+os.sep+template) 1201 except: 1202 return 0,u("erreur de supression de %s" % template) 1203 # on supprime les droits associés si nécessaire 1204 self.parent.s_pool.del_file_perms(dest_dir,'fichiers_perso'+os.sep+template) 1205 1206 for patch in dico_files['patchs_var']: 1207 try: 1208 if patch != "": 1209 os.unlink(dest_dir+os.sep+'patchs'+os.sep+patch) 1210 except: 1211 return 0,u("erreur de suppression de %s" % patch) 1212 # on reprend la liste des fichiers existants 1213 try: 1214 f=open(dest_dir+os.sep+'fichiers_zephir/fichiers_variante') 1215 old_content=f.read() 1216 f.close() 1217 fichiers=old_content.split('%%\n')[0] 1218 rpms=old_content.split('%%\n')[1] 1219 except: 1220 fichiers="""# section 1 1221 # liste des fichiers à sauvegarder pour la variante 1222 # (ne pas modifier sauf pour créer ou mettre à jour la variante)""" 1223 rpms="""# section 2 1224 # inscrire les noms des paquetages qui seront installés à la mise à jour du serveur 1225 # (ils doivent être présents sur le serveur de mise à jour)""" 1226 1227 for fichier in dico_files['fichiers_var']: 1228 # on supprime le fichier de la liste 1229 liste=fichiers.split('\n') 1230 if fichier in liste: 1231 liste.remove(fichier) 1232 fichiers = "\n".join(liste) 1233 fic_path = os.path.join(dest_dir,'fichiers_zephir',os.path.basename(fichier.replace("\\","/"))) 1234 else: 1235 fic_path = os.path.join(dest_dir,fichier) 1236 # on efface le fichier 1237 try: 1238 if fichier != "": 1239 if os.path.isdir(fic_path): 1240 shutil.rmtree(fic_path) 1241 elif os.path.isfile(fic_path): 1242 os.unlink(fic_path) 1243 except: 1244 return 0,u("erreur de suppression de %s" % fichier) 1245 if fichier.startswith('/'): 1246 fic_sup = 'fichiers_zephir/'+os.path.basename(fichier.replace("\\","/")) 1247 else: 1248 fic_sup = fichier 1249 self.parent.s_pool.del_file_perms(dest_dir,fic_sup,True) 1250 1251 # rpms 1252 for rpm in dico_files['rpms_var']: 1253 # on supprime le rpm si il existe 1254 liste=rpms.split('\n') 1255 if rpm in liste: 1256 liste.remove(rpm) 1257 rpms = "\n".join(liste) 1258 else: 1259 return 0,u("rpm non trouvé dans la liste : %s" % rpm) 1260 1261 f=open(dest_dir+os.sep+'fichiers_zephir/fichiers_variante','w') 1262 f.write(fichiers+"%%\n"+rpms) 1263 f.close() 1264 return 1,u("ok")
1265
1266 - def xmlrpc_get_var_file(self,cred_user,id_var,id_module,path,show_details=False):
1267 """renvoie le contenu d'un fichier de variante""" 1268 # définition du chemin de la variante 1269 self.parent.s_pool.check_var_credential(cred_user, id_var) 1270 query="select variantes.id,variantes.module,modules.version from variantes,modules where variantes.id=%s and modules.id=variantes.module" % id_var 1271 return self.dbpool.runQuery(query, (int(id_var),)).addCallbacks(self._get_var_file,db_client_failed,callbackArgs=[path,show_details])
1272
1273 - def _get_var_file(self,data,path,show_details):
1274 id_var = data[0][0] 1275 id_module = data[0][1] 1276 mod_version = data[0][2] 1277 try: 1278 mod_version = int(mod_version) 1279 except: 1280 mod_version = 3 1281 try: 1282 dest_dir=os.path.abspath(config.PATH_MODULES)+os.sep+str(id_module)+os.sep+"variantes"+os.sep+str(id_var) 1283 except: 1284 return 0,u("""lecture du fichier: paramètres non valides""") 1285 # on lit le fichier 1286 try: 1287 # cas d'un répertoire 1288 if os.path.isdir(dest_dir + os.sep + path): 1289 dirfiles = os.listdir(dest_dir + os.sep + path) 1290 content = [] 1291 if show_details: 1292 for f in dirfiles: 1293 f_local = os.path.join(dest_dir,path,f) 1294 f_info = config.get_file_info(f_local) 1295 content.append((f,f_info)) 1296 else: 1297 content = dirfiles 1298 return 1, u(content) 1299 else: 1300 if istextfile(dest_dir + os.sep + path): 1301 f=file(dest_dir + os.sep + path) 1302 content=f.read() 1303 f.close() 1304 # on encode le contenu en base64 1305 if mod_version == 1: 1306 try: 1307 content = unicode(content,'ISO-8859-1').encode(config.charset) 1308 except: 1309 # le fichier n'est pas en unicode ?? 1310 log.msg("echec d'encoding du fichier %s provenant d'un serveur eole1" % path) 1311 content = base64.encodestring(content) 1312 else: 1313 content = "BINARY" 1314 return 1, content 1315 except: 1316 return 0,u("""erreur de lecture du fichier""")
1317
1318 - def xmlrpc_export_variante(self,cred_user,id_variante):
1319 """envoie le contenu d'une variante sur un autre zephir""" 1320 # on recherche le répertoire ou la variante est stockée 1321 query = """select id,module from variantes where id=%s""" 1322 return self.dbpool.runQuery(query, (int(id_variante),)).addCallbacks(self._export_variante,db_client_failed)
1323
1324 - def _export_variante(self,data):
1325 """crée l'archive de la variante et le renvoie""" 1326 if data != []: 1327 id_variante = data[0][0] 1328 id_module = data[0][1] 1329 # répertoire de la variante 1330 parent_dir=os.path.abspath(config.PATH_MODULES)+os.sep+str(id_module)+os.sep+"variantes" 1331 var_dir=parent_dir+os.sep+str(id_variante) 1332 # on crée une archive de ce répertoire 1333 archive=str(time.time()) 1334 if os.path.isdir(var_dir): 1335 # création du fichier tar à envoyer 1336 cmd_tar = ['cd ',var_dir,';','tar','-chzf','/tmp/'+archive+'.tgz','*'] 1337 cmd_tar.append('2>&1 >/dev/null') 1338 # exécution de tar 1339 res=os.system(" ".join(cmd_tar)) 1340 if res != 0: 1341 return 0, u("""erreur de création de l'archive %s.tgz dans /tmp""" % (archive)) 1342 else: 1343 # calcul et stockage d'un checksum md5 de l'archive 1344 cmd_checksum = """cd /tmp/; md5sum -b %s.tgz > %s.md5""" % (archive,archive) 1345 res=os.system(cmd_checksum) 1346 # on stocke en mémoire les données 1347 try: 1348 # le checksum 1349 f = open('/tmp'+os.sep+archive+'.md5') 1350 data1 = f.read() 1351 f.close() 1352 os.unlink('/tmp'+os.sep+archive+'.md5') 1353 # l'archive 1354 f = open('/tmp'+os.sep+archive+'.tgz') 1355 data2 = f.read() 1356 f.close() 1357 os.unlink('/tmp'+os.sep+archive+'.tgz') 1358 return 1,u([archive,base64.encodestring(data1),base64.encodestring(data2)]) 1359 except Exception, e: 1360 return 0,u("""erreur lors de l'envoi de l'archive : %s""" % str(e)) 1361 else: 1362 return 0, u("""répertoire %s introuvable""" % var_dir) 1363 else: 1364 return 0, u("""variante inexistante""")
1365
1366 - def xmlrpc_import_variante(self,cred_user,pwd_var,id_local,id_distant,zephir_distant,login_distant,pwd_distant):
1367 """récupère le contenu d'une variante sur un autre zephir""" 1368 # création d'un proxy vers le serveur zephir distant 1369 z=xmlrpclib.ServerProxy("https://%s:%s@%s:%s" % (login_distant,pwd_distant,zephir_distant,config.PORT_ZEPHIR)) 1370 # on vérifie l'existence des variantes des 2 cotés 1371 try: 1372 res=z.modules.get_variante(id_distant) 1373 except: 1374 return 0,u("""permissions insuffisantes""") 1375 if res[0] == 0: 1376 return 0,u("""erreur lors de la recherche de la variante d'origine""") 1377 1378 # on recherche le module de la variante locale 1379 query = """select id, module, owner, passmd5 from variantes where id=%s""" 1380 return self.dbpool.runQuery(query, (int(id_local),)).addCallbacks(self._import_variante,db_client_failed,callbackArgs=[z,id_distant,cred_user,pwd_var])
1381
1382 - def _import_variante(self,data,proxy,id_distant,cred_user,pwd_var):
1383 """demande l'envoi de l'archive et met en place les fichiers""" 1384 if data == []: 1385 return 0, u("""variante locale non trouvée""") 1386 else: 1387 id_variante = data[0][0] 1388 id_module = data[0][1] 1389 owner = data[0][2] 1390 passmd5 = data[0][3] 1391 # on vérifie le mot de passe de la variante 1392 if owner != cred_user and pwd_var != passmd5: 1393 return 0,u("""mauvais mot de passe de variante""") 1394 else: 1395 # définition du chemin de destination 1396 parent_dir=os.path.abspath(config.PATH_MODULES)+os.sep+str(id_module)+os.sep+"variantes" 1397 var_dir = parent_dir+os.sep+str(id_variante) 1398 # on regarde si des fichiers existent déjà 1399 if not os.path.exists(var_dir): 1400 return 0,u("""répertoire de la variante de destination non trouvé""") 1401 # onrécupère les données de la variante source 1402 res=proxy.modules.export_variante(id_distant) 1403 if res[0]==0: 1404 return 0,u("""erreur lors de la récupération de la variante""") 1405 else: 1406 # nom de l'archive 1407 archive=res[1][0] 1408 # somme md5 1409 var_data=base64.decodestring(res[1][1]) 1410 # contenu de l'archive 1411 md5_data=base64.decodestring(res[1][2]) 1412 try: 1413 # on supprime l'ancien répertoire de la variante 1414 shutil.rmtree(var_dir) 1415 # on recrée un répertoire vide 1416 os.makedirs(var_dir) 1417 # on recrée l'archive et le fichier md5 1418 f=open(var_dir+os.sep+archive+'.tgz','w') 1419 f.write(md5_data) 1420 f.close() 1421 f=open(var_dir+os.sep+archive+'.md5','w') 1422 f.write(var_data) 1423 f.close() 1424 # on vérifie la somme md5 1425 cmd_md5 = """cd %s; md5sum -c %s.md5 2>&1 > /dev/null""" % (var_dir,archive) 1426 res=os.system(cmd_md5) 1427 if res != 0: 1428 return 0,u("""archive corrompue""") 1429 # on décompresse l'archive 1430 cmd_tar = """cd %s ; tar -xzf %s.tgz > /dev/null""" % (var_dir,archive) 1431 res=os.system(cmd_tar) 1432 if res != 0: 1433 return 0,u("""erreur de décompression de l'archive""") 1434 # on supprime les fichiers temporaires 1435 os.unlink(var_dir+os.sep+archive+'.tgz') 1436 os.unlink(var_dir+os.sep+archive+'.md5') 1437 except Exception, e: 1438 return 0,u("""erreur de mise en place des fichiers de la variante : %s""" % str(e)) 1439 # l'import s'est terminé correctement 1440 return 1,u("ok")
1441