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

Source Code for Module zephir.backend.serveurs_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  # serveurs_rpc.py 
   9  # 
  10  # fonctions xmlrpc pour la gestion des serveurs dans Zephir 
  11  # 
  12  ########################################################################### 
  13  """module de gestion des serveurs 
  14  """ 
  15  from zephir.backend.db_utils import * 
  16  from zephir.backend import config 
  17  from zephir.backend.config import log 
  18  from zephir.backend.uucp_utils import UUCPError, uucp_pool 
  19  from zephir.backend.config import u, FILE_SECTION, RPM_SECTION 
  20  from zephir.backend.xmlrpceole import XMLRPCEole as XMLRPC 
  21  from zephir.monitor.collecteur import ServeurStatus 
  22  from zephir.backend.lib_backend import ResourceAuthError, istextfile 
  23  from tiramisu.error import PropertiesOptionError 
  24   
  25  import psycopg2 as PgSQL 
  26   
  27  import sys,os,shutil,time,dico,base64, traceback 
  28   
29 -class RPCServeurs(XMLRPC):
30 """serveur XMLRPC zephir pour la gestion des serveurs 31 """ 32
33 - def __init__(self,parent,agent_manager):
34 self.dbpool = db_connect() 35 self.dbpool.noisy = 0 36 XMLRPC.__init__(self) 37 self.agent_manager = agent_manager 38 self.parent = parent
39
40 - def _got_serveur(self,serveurs,cred_user):
41 """Formatage de la liste des serveurs 42 """ 43 l=[] 44 auth_error = False 45 for serveur in serveurs: 46 # on ne renvoie que les serveurs accessibles 47 try: 48 serv = self.parent.s_pool.get(cred_user,int(serveur[0])) 49 except ResourceAuthError: 50 auth_error = True 51 continue 52 l.append(self._format_serv(serveur, serv)) 53 if l == [] and auth_error == True: 54 # aucun serveur n'est autorisé dans ce groupe 55 return 0, u("Vous n'avez accès à aucun serveur dans ce groupe") 56 return 1,u(l)
57
58 - def _format_serv(self, serveur, serv):
59 if serveur[14] is None: 60 timeout = 0 61 else: 62 timeout =int(serveur[14]) 63 if serveur[17] == None: 64 params = serv.get_params() 65 else: 66 params = serveur[17] 67 if serveur[18] == None: 68 maj_serv = -1 69 else: 70 maj_serv = serveur[18] 71 if serveur[19] == None: 72 md5_serv = -1 73 else: 74 md5_serv = serveur[19] 75 if serveur[20] == None: 76 ip_publique = "" 77 else: 78 ip_publique = serveur[20] 79 if serveur[21] in (None, 0): 80 no_alert = 0 81 else: 82 no_alert = 1 83 return {'id':serveur[0], 84 'rne':serveur[1], 85 'libelle':serveur[2], 86 'materiel':serveur[3], 87 'processeur':serveur[4], 88 'disque_dur':serveur[5], 89 'date_install':str(serveur[6]), 90 'installateur':serveur[7], 91 'tel':serveur[8], 92 'remarques':serveur[9], 93 'module_initial':serveur[10], 94 'module_actuel':serveur[11], 95 'variante':serveur[12], 96 'timeout':timeout, 97 'timestamp':serv.modified, 98 'etat':serv.get_status(), 99 'params':params, 100 'maj':maj_serv, 101 'md5s':md5_serv, 102 'ip_publique':ip_publique, 103 'no_alert':no_alert 104 }
105
106 - def _got_log(self,lignes,cred_user):
107 """Formattage de la liste des logs 108 """ 109 # on vérifie quels serveurs sont accessibles 110 servs = {} 111 for ligne in lignes: 112 id_serveur = ligne[1] 113 try: 114 if id_serveur not in servs.keys(): 115 self.parent.s_pool.get(cred_user,int(id_serveur)) 116 except: 117 servs[id_serveur] = False 118 else: 119 servs[id_serveur] = True 120 # création de la liste des logs à afficher 121 l=[] 122 for ligne in lignes: 123 if servs[ligne[1]] == True: 124 l.append( 125 {'id':ligne[0] 126 ,'id_serveur':ligne[1] 127 ,'date':str(ligne[2]) 128 ,'action':ligne[3] 129 ,'message':ligne[4] 130 ,'etat':ligne[5]}) 131 return 1,u(l)
132 133 134 ############################# 135 ## gestion des serveurs eole 136 ############################# 137
138 - def xmlrpc_regen_key(self,cred_user,serveurs, regen_certs=False, new_addr=None):
139 """prépare une nouvelle clé ssh pour la communication client/zephir 140 - génère la clé 141 - prépare une action de mise en place de la clé sur le client 142 """ 143 if type(serveurs) != list: 144 serveurs = [serveurs] 145 erreurs = [] 146 for id_serveur in serveurs: 147 try: 148 id_serveur = int(id_serveur) 149 serv = self.parent.s_pool.get(cred_user, id_serveur) 150 except: 151 erreurs.append("Serveur %s : inexistant ou accès refusé" % str(id_serveur)) 152 if not os.path.isfile(os.path.join(serv.get_confdir(), 'cle_publique')): 153 erreurs.append("%s (%s): Le serveur n'est pas encore enregistré" % (serv.id_s, serv.rne)) 154 else: 155 res = serv.regen_key(new_addr) 156 if res != 0: 157 erreurs.append("%s (%s): Erreur lors de la génération de la clé" % (serv.id_s, serv.rne)) 158 else: 159 # envoi de la nouvelle clé publique au serveur par uucp 160 code, data = self.parent.getSubHandler('uucp')._send_files(serv,'pubkey',['new_key.pub'],uucp=1) 161 if code == 0: 162 erreurs.append("%s (%s): Echec d'envoi de la clé publique (%s)" % (serv.id_s, serv.rne, data)) 163 else: 164 id_uucp = str(serv.get_rne())+'-'+str(serv.id_s) 165 if new_addr is None: 166 # mise en file d'attente de la procédure de mise en place 167 # non utilisé dans le cas d'un changement d'adresse de zephir 168 # (le client installera la clé quand la nouvelle adresse répondra) 169 try: 170 if regen_certs: 171 res = uucp_pool.add_cmd(id_uucp,"zephir_client update_key regen_certs") 172 else: 173 res = uucp_pool.add_cmd(id_uucp,"zephir_client update_key") 174 except UUCPError,e: 175 erreurs.append("serveur %s (%s) : Erreur UUCP %s" % (serv.id_s, serv.rne, str(e))) 176 else: 177 try: 178 res = uucp_pool.add_cmd(id_uucp,"zephir_client change_ip") 179 except UUCPError,e: 180 erreurs.append("serveur %s (%s) : Erreur UUCP %s" % (serv.id_s, serv.rne, str(e))) 181 return 1, u(erreurs)
182
183 - def xmlrpc_get_key(self,cred_user,id_serveur,old_key,new_key,confirm_ip=False):
184 """retourne à un serveur une nouvelle clé ssh générée (appelé depuis le client) 185 la clé est renvoyée seulement si les clés publiques correspondent 186 confirm_ip : utilisé dans le cas d'un changement d'adresse de zephir pour confirmer 187 que l'adresse est bien prise en compte par le client 188 """ 189 id_serveur = int(id_serveur) 190 serv = self.parent.s_pool.get(cred_user, id_serveur) 191 # récupération des données de la clé 192 code, res = serv.get_key(old_key,new_key, confirm_ip) 193 return code, u(res)
194
195 - def xmlrpc_update_key(self,cred_user,id_serveur):
196 """valide la mise en place d'une nouvelle clé et invalide l'ancienne 197 """ 198 id_serveur = int(id_serveur) 199 serv = self.parent.s_pool.get(cred_user, id_serveur) 200 """met en place la nouvelle clé d'enregistrement côté zephir 201 Les clés publiques et privées doivent avoir été récupérées par le serveur""" 202 actual_key_path = os.path.join(serv.get_confdir(), 'cle_publique') 203 new_key_path = os.path.join(serv.get_confdir(), 'new_key.pub') 204 new_key_priv_path = os.path.join(serv.get_confdir(), 'new_key') 205 new_addr_path = os.path.join(serv.get_confdir(), 'new_addr_ok') 206 if not os.path.isfile(new_key_path) or os.path.isfile(new_key_priv_path): 207 return 0, """Nouvelles clés non récupérées par le serveur""" 208 cle_rsa = file(new_key_path).read().strip() 209 # on supprime la clé publique temporaire 210 os.unlink(new_key_path) 211 if os.path.isfile(new_addr_path): 212 os.unlink(new_addr_path) 213 return self._conf_ssh('',serv.id_s,cle_rsa)
214
215 - def xmlrpc_purge_key(self,cred_user,serveurs):
216 """annule la prise en compte d'une nouvelle adresse ip pour une liste de serveurs 217 """ 218 if type(serveurs) != list: 219 serveurs = [serveurs] 220 erreurs = [] 221 for id_serveur in serveurs: 222 try: 223 id_serveur = int(id_serveur) 224 serv = self.parent.s_pool.get(cred_user, id_serveur) 225 except: 226 erreurs.append("Serveur %s : inexistant ou accès refusé" % str(id_serveur)) 227 continue 228 try: 229 params = serv.get_params() 230 if params.has_key('new_key') and params['new_key'][0] in (2,3): 231 id_uucp = str(serv.get_rne()) + '-' + str(serv.id_s) 232 uucp_pool.add_cmd(id_uucp,"zephir_client purge_ip") 233 except UUCPError,e: 234 erreurs.append("serveur %s (%s) : Erreur UUCP %s" % (serv.id_s, serv.rne, str(e))) 235 continue 236 for fic in ('new_key','new_key.pub','new_addr','new_addr_ok'): 237 serv_fic = os.path.join(serv.get_confdir(), fic) 238 if os.path.isfile(serv_fic): 239 os.unlink(serv_fic) 240 return 1, erreurs
241
242 - def xmlrpc_check_serveurs(self,cred_user,serveurs,last_check=None):
243 """permet de vérifier si des serveurs ont été modifiés 244 """ 245 return 1, u(self.parent.s_pool.check_serveurs(cred_user, serveurs, last_check))
246
247 - def xmlrpc_check_groupes(self, cred_user, groupes, last_check=None):
248 """permet de vérifier si des serveurs ont été modifiés 249 """ 250 return 1, u(self.parent.s_pool.check_groupes(cred_user, groupes, last_check))
251
252 - def xmlrpc_variante_migration(self, cred_user, id_serveur):
253 """renvoie la variante de migration choisie si disponible 254 """ 255 try: 256 id_serveur = int(id_serveur) 257 serv = self.parent.s_pool.get(cred_user, id_serveur) 258 except KeyError: 259 return 0, u("""serveur inconnu""") 260 try: 261 variante_dest = serv.variante_migration() 262 assert variante_dest 263 return 1, int(variante_dest) 264 except: 265 return 0, u('Variante de migration non définie')
266
267 - def xmlrpc_migrate_serveur(self, cred_user, id_serveur, hw_infos, module_dest, variante_dest=None):
268 """modifie un serveur Eole1 en serveur NG""" 269 try: 270 id_serveur = int(id_serveur) 271 serv = self.parent.s_pool.get(cred_user, id_serveur) 272 except KeyError: 273 return 0, u("""serveur inconnu""") 274 if variante_dest == None: 275 # on regarde si une variante de migration a été définie sur zephir 276 try: 277 variante_dest = serv.variante_migration() 278 assert int(variante_dest) > 0 279 except: 280 variante_dest = None 281 if variante_dest == None: 282 query = "select modules.id, modules.libelle, modules.version, variantes.id from modules,variantes \ 283 where modules.id=%s and modules.id=variantes.module and variantes.libelle='standard'" 284 return self.dbpool.runQuery(query, (int(module_dest),)).addCallbacks(self._migrate_serveur2,db_client_failed,callbackArgs=[cred_user, serv, hw_infos, variante_dest, module_dest]) 285 else: 286 query = "select modules.id, modules.libelle, modules.version, variantes.id from modules, variantes \ 287 where modules.id=%s and modules.id=variantes.module and variantes.id=%s" 288 return self.dbpool.runQuery(query, (int(module_dest), int(variante_dest))).addCallbacks(self._migrate_serveur2,db_client_failed,callbackArgs=[cred_user, serv, hw_infos, variante_dest, module_dest])
289
290 - def _migrate_serveur2(self, data, cred_user, serv, hw_infos, variante_dest, module_dest):
291 # vérification de la validité des modules 292 try: 293 lib_new = data[0][1] 294 id_new_mod = int(data[0][0]) 295 version_new = int(data[0][2]) 296 id_variante = int(data[0][3]) 297 lib_act = serv.module 298 299 version_act = serv.module_version 300 assert lib_new[:lib_new.rindex('-')] == lib_act[:lib_act.rindex('-')] 301 assert lib_new != lib_act and version_new > 1 302 if (version_act > 1) and (version_new != version_act + 1): 303 # cas particulier, on regarde si le passage est autorisé entre ces 2 version pour ce module 304 assert version_new in config.allowed_upgrades[lib_act[:lib_act.rindex('-')]][version_act] 305 except: 306 traceback.print_exc() 307 return 0,u("""la migration vers le module demandé n'est pas gérée""") 308 if version_act not in config.allowed_migrations: 309 # migration transparente entre 2 versions d'eole NG 310 migrate = False 311 if variante_dest == None: 312 # si pas de variante spécifiée, on regarde si on a une variante correspondant à la variante actuelle (table migration_variantes) 313 query = "select id_dest, module from migration_variantes, variantes where id_source=%s and id_dest = id and module = %s" 314 return self.dbpool.runQuery(query, (int(serv.id_var), int(module_dest))).addCallbacks(self._migrate_variante, db_client_failed, callbackArgs=[serv,id_new_mod,id_variante,hw_infos,cred_user,migrate]) 315 else: 316 # migration avec préparation de configuration obligatoire 317 # (aujourd'hui eole1 -> NG, eole 2.2 -> 2.3) 318 migrate = True 319 query = "select module_actuel, variante, materiel, processeur, disque_dur, date_install, installateur, tel, remarques, timeout from serveurs where id=%s" % (serv.id_s) 320 return self.dbpool.runQuery(query, (int(serv.id_s),)).addCallbacks(self._backup_serveur_data, db_client_failed,callbackArgs=[serv,id_new_mod,id_variante, hw_infos, cred_user, migrate])
321
322 - def _migrate_variante(self, data, serv,id_new_mod,id_variante, hw_infos, cred_user, migrate):
323 """récupère la variante à migrer automatiquement si disponible""" 324 if len(data) > 0: 325 id_var_mod = data[0][1] 326 if id_var_mod == id_new_mod: 327 # variante de migration trouvée dans le module de destination 328 id_variante = data[0][0] 329 query = "select module_actuel, variante, materiel, processeur, disque_dur, date_install, installateur, tel, remarques, timeout from serveurs where id=%s" 330 return self.dbpool.runQuery(query, (int(serv.id_s),)).addCallbacks(self._backup_serveur_data, db_client_failed,callbackArgs=[serv,id_new_mod,id_variante, hw_infos, cred_user, migrate])
331
332 - def _backup_serveur_data(self, data, serv, id_new_mod, id_variante, hw_infos, cred_user, migrate = True):
333 path_ori = serv.get_confdir() 334 if migrate == True: 335 path_bak = path_ori + "-backup" 336 else: 337 path_bak = path_ori + "-downgrade" 338 # on fait un backup des anciennes données 339 if os.path.exists(path_bak): 340 try: 341 prev_migration_var = int(open(os.path.join(path_bak, 'variante_migration')).read().strip()) 342 except: 343 prev_migration_var = None 344 if migrate and prev_migration_var == int(serv.variante_migration()): 345 # migration déjà effectuée: ne devrait pas se produire plusieurs fois 346 return 0, u("""répertoire de backup déjà présent: %s""" % path_bak) 347 else: 348 # on supprime l'ancien backup pour permettre des upgrade/migrations successives 349 shutil.rmtree(path_bak) 350 # on sauvegarde dans un fichier les données sql d'origine 351 sql_data = "::".join([str(val) for val in data[0]]) 352 f_var_ori = file(os.path.join(path_ori,"sql_data.ori"),'w') 353 f_var_ori.write(sql_data) 354 f_var_ori.close() 355 # mise de coté des anciennes données 356 res = os.system("/bin/mv %s %s" % (path_ori, path_bak)) 357 if res != 0: 358 return 0, u("""erreur de création du répertoire de sauvegarde""") 359 # mise en forme des infos materielles 360 materiel = "" 361 query_params = [int(id_new_mod), int(id_variante)] 362 for row in ['materiel','processeur','disque_dur','installateur', 'date_install']: 363 if hw_infos.has_key(row): 364 if hw_infos[row] != '': 365 materiel += ", %s=%%s" % row 366 query_params.append(hw_infos[row]) 367 query_params.append(int(serv.id_s)) 368 # mise à jour de la base 369 query = "update serveurs set module_actuel=%s, variante=%s, params=''" + materiel + " where id=%s" 370 return self.dbpool.runOperation(query, query_params).addCallbacks(self._migrate_serveur_data, db_client_failed,callbackArgs=[serv,id_new_mod,id_variante,cred_user,migrate])
371
372 - def _migrate_serveur_data(self, res, serv, id_mod, id_var, cred_user, migrate):
373 # mise en place des répertoires 374 serv.update_data() 375 ret, msg = serv._cree_arbo_serveur() 376 if ret != 1: 377 self._revert_migration(serv, cred_user) 378 return ret, u(msg) 379 # copie des fichiers d'authentification 380 path_ori = serv.get_confdir() 381 if migrate: 382 path_bak = path_ori + "-backup" 383 else: 384 path_bak = path_ori + "-downgrade" 385 res = 0 386 self.copy_serveur_data(path_ori, path_bak, migrate) 387 serv.maj_params({'migration_ok':1}) 388 389 if migrate == True: 390 # on invalide la cle ssh de l'ancien serveur 391 try: 392 fic_cle_publique = os.path.join(path_bak,'cle_publique') 393 # si une clé existait déjà, on la supprime de authorized_keys avant de continuer 394 if os.path.isfile(fic_cle_publique): 395 # on lit la sauvegarde de l'ancienne clé 396 backup_cle = open(fic_cle_publique,"r") 397 old_cle = backup_cle.read().strip().split('\n')[0] 398 backup_cle.close() 399 # on enlève les occurences de cette ancienne clé des clés autorisées 400 self._remove_ssh_key(old_cle) 401 except: 402 traceback.print_exc() 403 return self._update_conf_uucp(cred_user, serv.id_s, serv.rne, "") 404 else: 405 return 1, serv.id_s
406
407 - def copy_serveur_data(self, path_ori, path_bak, migrate):
408 """copie des fichiers compatibles lors d'une migration/update 409 """ 410 # fichier de configuration creole 411 if os.path.isfile(os.path.join(path_bak,'zephir.eol')) and not migrate: 412 res = os.system("/bin/cp -rf %s %s" % (os.path.join(path_bak,'zephir.eol'),os.path.join(path_ori,'zephir.eol'))) 413 if res != 0: 414 return 0, u("""erreur de copie du fichier de configuration creole (zephir.eol)""") 415 if os.path.isfile(os.path.join(path_bak,'migration.eol')) and migrate: 416 res = os.system("/bin/cp -rf %s %s" % (os.path.join(path_bak,'migration.eol'),os.path.join(path_ori,'zephir.eol'))) 417 if res != 0: 418 return 0, u("""erreur de copie du fichier de migration creole (migration.eol -> zephir.eol)""") 419 # liste des fichiers à recopier 420 data_files = ['auth_keys','vpn'] 421 if not migrate: 422 data_files.append('cle_publique') 423 # upgrade de distribution, tous les fichiers personnalisés sont repris tels quels 424 for data_dir in ['fichiers_zephir', 'fichiers_perso', 'patchs', 'dicos/local', 'uucp']: 425 for data_file in os.listdir(os.path.join(path_bak,data_dir)): 426 if not os.path.islink(os.path.join(path_bak,data_dir,data_file)): 427 data_files.append(os.path.join(data_dir, data_file)) 428 log.msg("\n !! copying data : %s !!\n" % (data_files)) 429 res = 0 430 for fic in data_files: 431 if os.path.isdir(os.path.join(path_ori,fic)): 432 shutil.rmtree(os.path.join(path_ori,fic)) 433 if os.path.exists(os.path.join(path_bak,fic)): 434 res = os.system("/bin/cp -rpf %s %s" % (os.path.join(path_bak,fic),os.path.join(path_ori,fic))) 435 if res != 0: 436 break 437 if res != 0: 438 return 0, u("""erreur de copie des fichiers de configuration uucp""")
439
440 - def xmlrpc_migrate_data(self, cred_user, id_serveur, check=False):
441 """fonction de récupération des données d'un serveur migré 442 """ 443 try: 444 id_serveur = int(id_serveur) 445 serv = self.parent.s_pool.get(cred_user, id_serveur) 446 return serv.migrate_data(check) 447 except KeyError: 448 return 0, u("""serveur inconnu""")
449
450 - def xmlrpc_migrate_conf(self, cred_user, id_serveur, mode='migration', variante_dest=''):
451 """fonction de création d'un fichier de configuration pour la migration (migration.eol) 452 """ 453 try: 454 id_serveur = int(id_serveur) 455 serv = self.parent.s_pool.get(cred_user, id_serveur) 456 except KeyError: 457 return 0, u("""serveur invalide""") 458 if variante_dest == '': 459 # on récupère la variante déjà enregistrée 460 variante_dest = serv.variante_migration() 461 if variante_dest == '': 462 return 0, u("""variante de destination non définie""") 463 464 query = 'select variantes.id, variantes.module, modules.version, modules.libelle from variantes,modules where variantes.id=%s and modules.id=variantes.module' 465 return self.dbpool.runQuery(query, (int(variante_dest),)).addCallbacks(self._migrate_config, db_client_failed,callbackArgs=[cred_user, serv, mode])
466
467 - def _migrate_config(self, data, cred_user, serv, mode):
468 # on vérifie le module de destination 469 try: 470 id_variante = int(data[0][0]) 471 id_new_mod = int(data[0][1]) 472 version_new = int(data[0][2]) 473 lib_new = str(data[0][3]) 474 lib_act = serv.get_module().split('-')[0] 475 assert serv.module_version in config.allowed_migrations and version_new in config.allowed_migrations[serv.module_version] 476 # assert serv.version == "creole1" and version_new > 1 477 assert lib_new.split('-')[0] == lib_act.split('-')[0] 478 except: 479 return 0,u("""la migration vers le module demandé n'est pas gérée""") 480 # récupération du dictionnaire correspondant à la variante avec les valeurs 481 # importées de la configuration (creole1) du serveur 482 try: 483 creole_version = config.CREOLE_VERSIONS[version_new] 484 config_serv = serv.migrate_config(id_new_mod, id_variante, mode, creole_version) 485 data = config_serv.get_dict() 486 except: 487 return 0, u("""erreur lors de l'import des données de configuration""") 488 return 1, u(data)
489
490 - def xmlrpc_revert_migration(self,cred_user,id_serveur):
491 """retour en arrière sur la migration d'un serveur 492 """ 493 try: 494 id_serveur = int(id_serveur) 495 serv = self.parent.s_pool.get(cred_user, id_serveur) 496 return self._revert_migration(serv,cred_user) 497 except (KeyError, ValueError): 498 return 0, u("""id de serveur non valide : %s""" % str(id_serveur))
499
500 - def _revert_migration(self, serv, cred_user):
501 path_ori = serv.get_confdir() 502 path_bak = path_ori + "-downgrade" 503 if not os.path.isdir(path_bak): 504 path_bak = path_ori + "-backup" 505 if not os.path.isdir(path_bak): 506 return 0, u("""répertoire de backup non retrouvé""") 507 # on récupère les données sql d'origine 508 f_var_ori = file(os.path.join(path_bak,"sql_data.ori")) 509 data_ori = f_var_ori.read().strip().split('::') 510 f_var_ori.close() 511 try: 512 assert len(data_ori) == 10 513 except: 514 return 0, u("""impossible de relire les données sql d'origine""") 515 # réinsertion des valeur d'origine dans la base 516 data_ori.append(serv.id_s) 517 query = "update serveurs set \ 518 module_actuel=%s,\ 519 variante=%s,\ 520 materiel=E'%s',\ 521 processeur=E'%s',\ 522 disque_dur=E'%s',\ 523 date_install=E'%s',\ 524 installateur=E'%s',\ 525 tel=E'%s',\ 526 remarques=E'%s',\ 527 timeout=%s,\ 528 params=null, maj=null where id=%s" % tuple(data_ori) 529 return self.dbpool.runOperation(query).addCallbacks(self._revert_migration2,db_client_failed,callbackArgs=[serv, path_ori, path_bak,cred_user])
530
531 - def _revert_migration2(self, res, serv, path_ori, path_bak,cred_user):
532 fic_cle_publique = os.path.join(path_ori,'cle_publique') 533 try: 534 # suppression de la cle eoleNG 535 if os.path.isfile(fic_cle_publique): 536 backup_cle = open(fic_cle_publique,"r") 537 new_key = backup_cle.read().strip().split('\n')[0] 538 backup_cle.close() 539 # on enlève les occurences de cette ancienne clé des clés autorisées 540 self._remove_ssh_key(new_key) 541 except: 542 traceback.print_exc() 543 # remise en place de l'ancien password uucp 544 if os.path.isdir(path_ori): 545 shutil.rmtree(path_ori) 546 res = os.system("/bin/mv %s %s;/bin/sync" % (path_bak, path_ori)) 547 if res != 0: 548 return 0, u("""erreur de mise en place des données sauvegardées""") 549 os.unlink(os.path.join(path_ori,"sql_data.ori")) 550 try: 551 # réautorisation de la cle eole1 552 if os.path.isfile(fic_cle_publique): 553 # on lit la sauvegarde de l'ancienne clé 554 backup_cle = open(fic_cle_publique,"r") 555 old_key = backup_cle.read().strip().split('\n')[0] 556 backup_cle.close() 557 # on enlève les occurences de cette ancienne clé des clés autorisées 558 self._authorize_ssh_key(old_key) 559 except: 560 traceback.print_exc() 561 # remise en place de l'ancien password uucp 562 if os.path.isfile(os.path.join(path_ori,'uucp','sys')): 563 data_uucp = open(os.path.join(path_ori,'uucp','sys')).read().split('\n') 564 for line in data_uucp: 565 if line.startswith('call-password') and line.count(serv.rne) > 0: 566 passwd_uucp = line.strip().split()[-1] 567 self._update_conf_uucp(cred_user, serv.id_s, serv.rne, "", passwd_uucp) 568 break 569 serv.update_data() 570 serv.get_params() 571 return 1, "OK"
572
573 - def xmlrpc_check_backup(self, cred_user, id_serveur):
574 """regarde si un backup de migration est présent pour un serveur 575 """ 576 try: 577 id_serveur = int(id_serveur) 578 serv = self.parent.s_pool.get(cred_user, id_serveur) 579 path_serv = serv.get_confdir() 580 except KeyError: 581 return 0, u("""serveur inconnu""") 582 if os.path.isdir(path_serv + '-backup'): 583 return 1, True 584 else: 585 return 1, False
586
587 - def xmlrpc_download_upgrade(self, cred_user, id_serveur, version, delay):
588 """lancement telechargement pour migration sur un serveur""" 589 return self._download_upgrade(cred_user, id_serveur, version, delay)
590
591 - def xmlrpc_download_upgrade_groupe(self, cred_user, liste, version, delay):
592 """lancement telechargement pour migration sur un groupe de serveurs""" 593 erreurs=[] 594 for serveur in liste: 595 retour = self._download_upgrade(cred_user, serveur['id'], version, delay) 596 if retour[0] == 0: 597 erreurs.append("serveur "+str(serveur['id'])+' : '+retour[1]) 598 if erreurs != []: 599 if len(erreurs) == len(liste): 600 # echec pour tous les serveurs 601 return 0, u(erreurs) 602 else: 603 return 1, u(erreurs) 604 else: 605 return 1, []
606
607 - def _download_upgrade(self, cred_user, id_serveur, version, delay):
608 """lancement du téléchargement des paquets de mise à jour pour upgrader 609 vers une version supérieure du système""" 610 try: 611 id_serveur = int(id_serveur) 612 serv = self.parent.s_pool.get(cred_user, id_serveur) 613 except (KeyError, ValueError): 614 return 0, u("""id de serveur non valide : %s""" % str(id_serveur)) 615 serveur_version = serv.module_version 616 serveur_module = serv.module 617 serveur_module = serveur_module[:serveur_module.rindex('-')] 618 # on vérifie que l'upgrade est permis (version supérieure, et pas de migration nécessaire) 619 if serveur_version in config.allowed_migrations.keys(): 620 return 0, u("Migration non supportée (Upgrade-Auto non disponible pour cette version") 621 if version != serveur_version + 1: 622 # saut > 1 : permis seulement dans certains cas 623 try: 624 assert version in config.allowed_upgrades[serveur_module][serveur_version] 625 except: 626 return 0, u("Migration non supportée") 627 id_uucp = str(serv.get_rne()) + '-' + str(serv.id_s) 628 upgrade_version = config.DISTRIBS[version][1] 629 try: 630 # construction de la commande uucp 631 uucp_pool.add_cmd(id_uucp,"zephir_client download_upgrade %s %s" % (upgrade_version, str(delay))) 632 except UUCPError, e: 633 return 0, u("Erreur UUCP (%s)" % str(e)) 634 return 1, u("ok")
635
636 - def xmlrpc_add_serveur(self, cred_user, rne, libelle, materiel, processeur, disque_dur, 637 date_install, installateur, tel, remarques, 638 module_initial, module_actuel, timeout, variante=None, cle_rsa1="", id_groupe=-1 639 ):
640 """ajout d'un serveur dans la base zephir""" 641 # on vérifie qu'on a bien récupéré un serveur 642 if rne: 643 # on recherche la variante par défaut du module 644 liste_donnees = [cred_user, rne, libelle, materiel, processeur, disque_dur, date_install, installateur, tel, remarques, module_initial, module_actuel, variante, timeout, cle_rsa1,id_groupe] 645 query = """select id from variantes where module = %s and libelle = 'standard'""" 646 return self.dbpool.runQuery(query, (int(module_actuel),)).addCallbacks(self._add_serveur1, db_client_failed,callbackArgs=liste_donnees) 647 else: 648 # des attributs manquent 649 return 0,u("""arguments à fournir: 650 rne,libelle,materiel,processeur,disque_dur,date_install, 651 installateur,tel,remarques,module_initial,module_actuel,variante""")
652 653
654 - def _add_serveur1(self, search_result, cred_user, rne, libelle, materiel, processeur, disque_dur, 655 date_install, installateur, tel, remarques, 656 module_initial, module_actuel, variante, timeout, cle_rsa1="", id_groupe=-1 657 ):
658 """insertion du serveur dans la base de données""" 659 # dans le cas ou la variante n'est pas donnée, on prend la variante par défaut 660 if variante is None or variante == "": 661 variante = search_result[0][0] 662 timestamp_serveur = str(time.time()) 663 try: 664 timeout = int(timeout) 665 except: 666 timeout = 0 667 # ajout du serveur dans la base 668 try: 669 serv = self.parent.s_pool.add_serveur(cred_user, rne,libelle,materiel,processeur,disque_dur,date_install,installateur,tel,remarques,module_initial,module_actuel,variante,timestamp_serveur,timeout) 670 id_serveur = serv.id_s 671 # si on a demandé l'ajout à un groupe, on étend ce groupe 672 if int(id_groupe) >= 0: 673 self.parent.s_pool.extend_groupe(cred_user,int(id_groupe),[id_serveur]) 674 except Exception, e: 675 return 0, u(str(e)) 676 # mise en place de l'arborescence pour le serveur et préparation des actions uucp 677 result,errmsg = serv._cree_arbo_serveur() 678 if result == 0: 679 # 'rollback' 680 self.xmlrpc_del_serveur(cred_user, id_serveur) 681 return 0, u(errmsg) 682 else: 683 return self._update_conf_uucp(cred_user, serv.id_s, rne, cle_rsa1)
684
685 - def _update_conf_uucp(self,cred_user,id_serveur,rne, cle_rsa1, passwd_uucp=""):
686 # création de la configuration du système distant 687 id_uucp = str(rne)+'-'+str(id_serveur) 688 if passwd_uucp == "": 689 passwd_uucp = str(rne)+'-'+str(id_serveur)+'-'+str(time.time()) 690 id_uucp = str(rne)+'-'+str(id_serveur) 691 # path_rcv = os.path.abspath(config.PATH_ZEPHIR)+os.sep+'conf'+os.sep+str(rne)+os.sep+str(id_serveur) 692 chaine_conf = config.CONFIG_UUCP % (id_serveur,id_uucp,id_uucp,passwd_uucp) 693 try: 694 if not os.path.isdir("/etc/uucp/serveurs/"): 695 os.makedirs("/etc/uucp/serveurs/") 696 fic_conf = open("/etc/uucp/serveurs/"+id_uucp+".sys","w") 697 fic_conf.write(chaine_conf) 698 fic_conf.close() 699 except: 700 # 'rollback' 701 self.xmlrpc_del_serveur(cred_user, id_serveur) 702 return 0,u("""erreur de création de la configuration uucp""") 703 else: 704 # on met en place la configuration uucp du module sur zephir 705 test=os.system('grep "sysfile /etc/uucp/serveurs/'+id_uucp+'.sys" /etc/uucp/config_zephir') 706 result = 0 707 if test != 0: 708 # si le serveur n'est pas encore listé, on l'ajoute 709 result = os.system('echo "sysfile /etc/uucp/serveurs/'+id_uucp+'.sys" >>/etc/uucp/config_zephir') 710 if result == 0: 711 # on indique un login et un mot de passe pour ce serveur 712 try: 713 fic_pass = file('/etc/uucp/passwd_zephir') 714 lines = fic_pass.read().strip().split('\n') 715 fic_pass.close() 716 # on parcourt la liste des serveurs et on remplace si il est déjà présent 717 content = [] 718 for line in lines: 719 # on supprime l'ancien mot de passe du serveur 720 if not line.startswith(id_uucp+' '): 721 content.append(line) 722 # on ajoute le nouveau mot de passe 723 content.append("%s %s" % (id_uucp,passwd_uucp)) 724 # réécriture du fichier 725 fic_pass = file('/etc/uucp/passwd_zephir','w') 726 lines = fic_pass.write("\n".join(content)) 727 fic_pass.close() 728 except: 729 result = 1 730 if result == 0: 731 # Ok, configuration terminée 732 return self._conf_uucp(id_serveur, rne, passwd_uucp, cle_rsa1) 733 if result != 0: 734 self.xmlrpc_del_serveur(cred_user, id_serveur) 735 return 0,u("""erreur de mise à jour de la configuration uucp""")
736
737 - def _conf_uucp(self,id_serveur,rne,passwd_uucp,cle_rsa1=""):
738 """création des fichiers de configuration uucp du serveur""" 739 path_dest=os.path.abspath(config.PATH_ZEPHIR)+'/conf/'+rne+os.sep+str(id_serveur)+os.sep+'uucp' 740 # fichier call,dial,dialcode et port 741 # --> copie sans modification 742 cmd = """cp %s/call %s/dial %s/dialcode %s/passwd %s""" % (config.TEMPLATE_DIR,config.TEMPLATE_DIR,config.TEMPLATE_DIR,config.TEMPLATE_DIR,path_dest) 743 os.system(cmd) 744 # fichier config, passwd, sys 745 for filepath in ["config","sys","port"]: 746 # on lit le fichier par défaut 747 try: 748 fic_ori=open(config.TEMPLATE_DIR+os.sep+filepath,'r') 749 lines = fic_ori.readlines() 750 fic_ori.close() 751 except: 752 return 0,u('erreur de lecture du fichier %s ' % filepath) 753 conf=[] 754 for line in lines: 755 # l'adresse est maintenant remplie par le client lors de l'enregistrement 756 # (pour etre sur d'avoir une adresse accessible de l'exérieur) 757 line = line.replace('%%serveur%%',str(rne)+'-'+str(id_serveur)) 758 line = line.replace('%%password%%',passwd_uucp) 759 # line = line.replace('%%zephir%%',str(config.ADRESSE_ZEPHIR)) 760 conf.append(line) 761 # on écrit le fichier de destination 762 try: 763 fic_dest=open(path_dest+os.sep+filepath,'w') 764 fic_dest.writelines(conf) 765 fic_dest.close() 766 except: 767 return 0,u('erreur de création du fichier %s ' % path_dest+os.sep+filepath) 768 if cle_rsa1 != "": 769 # si une cle est donnée, on effectue son ajout maintenant 770 return self._conf_ssh('',id_serveur,base64.decodestring(cle_rsa1)) 771 else: 772 return 1, id_serveur
773
774 - def xmlrpc_get_conf_uucp(self,cred_user,id_serveur,cle_rsa1):
775 """permet de récupérer la configuration uucp d'un serveur via xmlrpc""" 776 if cle_rsa1 == "": 777 return 0, u("""clé rsa invalide""") 778 if self.parent.s_pool.has_key(id_serveur): 779 # on logue l'accès du serveur (pour avoir un premier contact lors de l'enregistrement) 780 self.parent.s_pool.update_contact(id_serveur) 781 return self._conf_ssh('',id_serveur,base64.decodestring(cle_rsa1)) 782 else: 783 return 0, u("""erreur, serveur non retrouvé""")
784
785 - def _conf_ssh(self,cred_user,id_serveur,cle_rsa1):
786 """mise en place de la clé pour l'authentification d'uucp sur ssh""" 787 try: 788 id_serveur = int(id_serveur) 789 serv = self.parent.s_pool.get(cred_user, id_serveur) 790 except KeyError: 791 return 0, u("""serveur inconnu""") 792 path_dest=serv.get_confdir() 793 # construction de l'autorisation pour la connexion d'uucp via ssh 794 ligne_rsa = 'command="sudo /usr/sbin/uucico2 -D -l" '+cle_rsa1 795 # on stocke la clé publique dans le répertoire du serveur 796 try: 797 fic_cle_publique = os.path.join(path_dest,'cle_publique') 798 # si une clé existait déjà, on la supprime de authorized_keys avant de continuer 799 if os.path.isfile(fic_cle_publique): 800 # on lit la sauvegarde de l'ancienne clé 801 backup_cle = open(fic_cle_publique,"r") 802 old_cle = backup_cle.read().strip().split('\n')[0] 803 backup_cle.close() 804 # on enlève les occurences de cette ancienne clé des clés autorisées 805 self._remove_ssh_key(old_cle) 806 # on sauvegarde la nouvelle clé sur zephir 807 backup_cle = open(fic_cle_publique,"w") 808 backup_cle.write(ligne_rsa) 809 backup_cle.close() 810 serv.maj_params({'cle_ok':1}) 811 # et on ajoute la nouvelle clé à la liste des clés ssh autorisées pour uucp 812 self._authorize_ssh_key(ligne_rsa) 813 except: 814 # erreur d'écriture dans un des fichiers 815 self.xmlrpc_del_serveur(cred_user,id_serveur) 816 return 0,u("Erreur d'ajout de la cle rsa sur le serveur") 817 else: 818 # création des chaines permettant de transférer la conf uucp minimale 819 files = [] 820 for path_conf in ['config','sys','port']: 821 # on lit le fichier de conf 822 file_conf=open(path_dest+os.sep+'uucp'+os.sep+path_conf,"r") 823 lines_conf=file_conf.read() 824 file_conf.close() 825 # cas particulier : config 826 # correction au cas où le client ne comporte pas la correction du lockdir 827 if path_conf == 'config': 828 if lines_conf.count('lockdir') == 0: 829 lines_conf = lines_conf + "\nlockdir /tmp" 830 # on encode le contenu en base 64 et on l'ajoute à la liste des fichiers de conf 831 files.append(base64.encodestring(lines_conf)) 832 # envoi du fichier config.eol si il est déjà présent 833 if os.path.exists(path_dest+os.sep+'zephir.eol'): 834 # lecture du contenu 835 file_conf=open(path_dest+os.sep+'zephir.eol',"r") 836 lines_conf = file_conf.read() 837 file_conf.close() 838 files.append(base64.encodestring(lines_conf)) 839 else: 840 # sinon on envoie un chaine vide 841 files.append("") 842 return 1,id_serveur,files[0],files[1],files[2],files[3]
843
844 - def _authorize_ssh_key(self, cle):
845 """ajoute une cle ssh dans authorized_keys 846 """ 847 if os.path.isfile("/var/spool/uucp/.ssh/authorized_keys"): 848 auth_keys = open("/var/spool/uucp/.ssh/authorized_keys","r") 849 lines=auth_keys.read().strip().split('\n') 850 auth_keys.close() 851 else: 852 lines = [] 853 # ajout de la nouvelle clé 854 lines.append(cle) 855 # on enregistre le fichier modifié 856 auth_keys = open("/var/spool/uucp/.ssh/authorized_keys","w") 857 auth_keys.write("\n".join(lines)) 858 auth_keys.close()
859
860 - def _remove_ssh_key(self, cle):
861 """supprime une cle ssh de authorized_keys 862 """ 863 auth_keys = open("/var/spool/uucp/.ssh/authorized_keys","r") 864 lines=auth_keys.read().strip().split('\n') 865 auth_keys.close() 866 new_lines = [] 867 for line in lines: 868 if line.startswith(cle.strip()): 869 # si c'est la clé recherchée, on ne l'écrit pas 870 pass 871 else: 872 # sinon on reprend la ligne telle quelle 873 new_lines.append(line) 874 # on enregistre le fichier modifié 875 auth_keys = open("/var/spool/uucp/.ssh/authorized_keys","w") 876 auth_keys.write("\n".join(new_lines)) 877 auth_keys.close()
878
879 - def xmlrpc_del_serveur(self,cred_user,id_serveur):
880 """supression d'un serveur de la base zephir""" 881 try: 882 id_serveur = int(id_serveur) 883 serv = self.parent.s_pool.get(cred_user, id_serveur) 884 except (ValueError, KeyError): 885 # id_serveur non valide 886 return 0, u("""donnez un identifiant de serveur valide""") 887 888 # on supprime l'objet de la base de données (en principe un seul objet, l'id est unique) 889 # avant de supprimer le serveur et la config uucp : 890 # effectuer une procédure sur le serveur pour qu'il ne se connecte plus 891 # avec son id uucp actuel ? 892 id_uucp = serv.rne+'-'+str(id_serveur) 893 # on supprime le serveur des groupes où il est référencé 894 query = """select id,libelle,serveurs from groupes_serveurs""" 895 cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD) 896 cursor=cx.cursor() 897 cursor.execute(query) 898 groupes=cursor.fetchall() 899 # recherche des groupes concernés 900 for groupe in groupes: 901 serv_gr = eval(groupe[2]) 902 if id_serveur in serv_gr: 903 # modification de la liste des serveurs 904 serv_gr.remove(id_serveur) 905 # sauvegarde du groupe 906 if serv_gr == []: 907 # suppression si vide 908 self.xmlrpc_del_group(cred_user,int(groupe[0])) 909 else: 910 self.xmlrpc_edit_group(cred_user,int(groupe[0]),groupe[1],serv_gr) 911 # fernmeture de la connexion sql 912 # XXX: FIXME - suppression des restrictions sur ce serveur 913 cursor.close() 914 cx.close() 915 916 serveur_dir = serv.get_confdir() 917 self.parent.s_pool.del_serveur(cred_user, id_serveur) 918 # supression de ce répertoire ? 919 # on récupère la clé publique si elle existe 920 cle_pub="" 921 if os.path.isfile(serveur_dir+os.sep+"cle_publique"): 922 fic_rsa=open(serveur_dir+os.sep+"cle_publique","r") 923 cle_pub = fic_rsa.read().strip().split('\n')[0] 924 fic_rsa.close() 925 try: 926 shutil.rmtree(serveur_dir) 927 except: 928 return 1, u("""erreur de supression du repertoire du serveur""") 929 # supression du site de surveillance si présent 930 if os.path.exists(os.path.abspath(config.PATH_ZEPHIR)+os.sep+"data"+os.sep+str(id_serveur)): 931 stat_dir = os.path.abspath(config.PATH_ZEPHIR)+os.sep+"data"+os.sep+str(id_serveur) 932 else: 933 stat_dir = os.path.abspath(config.PATH_ZEPHIR)+os.sep+"sites"+os.sep+str(id_serveur) 934 try: 935 shutil.rmtree(stat_dir) 936 except: 937 # pas encore de stats 938 pass 939 # suppression des fichiers de md5 et des listes de paquets 940 for fic_data in ['config%s.md5' % str(id_serveur),'packages%s.list' % str(id_serveur)]: 941 if os.path.isfile(os.path.join(os.path.abspath(config.PATH_ZEPHIR),"data",fic_data)): 942 try: 943 os.unlink(os.path.join(os.path.abspath(config.PATH_ZEPHIR),"data",fic_data)) 944 except: 945 pass 946 if os.path.exists("/var/spool/uucppublic/site%s.tar" % id_serveur): 947 try: 948 os.unlink("/var/spool/uucppublic/site%s.tar" % id_serveur) 949 os.unlink("/var/spool/uucppublic/site%s.md5" % id_serveur) 950 except: 951 pass 952 953 # spool uucp du serveur 954 if os.path.exists("/var/spool/uucp/"+id_uucp): 955 shutil.rmtree("/var/spool/uucp/"+id_uucp) 956 # supression de la configuration uucp 957 try: 958 os.unlink("/etc/uucp/serveurs/"+id_uucp+".sys") 959 except: 960 pass 961 fic_config=open("/etc/uucp/config_zephir","r") 962 config_uucp=fic_config.readlines() 963 fic_config.close() 964 try: 965 config_uucp.remove('sysfile /etc/uucp/serveurs/'+id_uucp+'.sys\n') 966 except ValueError: 967 return 1, u("""configuration uucp non retouvée""") 968 else: 969 try: 970 fic_config=open("/etc/uucp/config_zephir","w") 971 fic_config.writelines(config_uucp) 972 fic_config.close() 973 except: 974 return 1, u("""erreur d'écriture dans /etc/uucp/config_zephir""") 975 else: 976 # suppression du login / password du serveur 977 fic_config=open("/etc/uucp/passwd_zephir","r") 978 config_uucp=fic_config.readlines() 979 fic_config.close() 980 for line in config_uucp: 981 if line.startswith(id_uucp+' '): 982 config_uucp.remove(line) 983 try: 984 fic_config=open("/etc/uucp/passwd_zephir","w") 985 fic_config.writelines(config_uucp) 986 fic_config.close() 987 except: 988 return 1, u("""erreur d'écriture dans /etc/uucp/passwd_zephir""") 989 # supression de la cle publique dans 'authorized_keys' si on la connait 990 if cle_pub != "": 991 try: 992 self._remove_ssh_key(cle_pub) 993 except: 994 # erreur de suppression de la clé 995 return 1, u("""clé rsa du serveur non retrouvée""") 996 return 1, 'ok'
997
998 - def xmlrpc_serveurs_etab(self,cred_user,rne=None):
999 """Liste des serveurs d'un etablissement 1000 """ 1001 if rne : 1002 query="""select * from serveurs where rne ilike %s""" 1003 return self.dbpool.runQuery(query, (rne,)).addCallbacks(self._got_serveur,db_client_failed,callbackArgs=[cred_user]) 1004 else : 1005 query="""select * from serveurs""" 1006 return self.dbpool.runQuery(query).addCallbacks(self._got_serveur,db_client_failed,callbackArgs=[cred_user])
1007 1008
1009 - def xmlrpc_get_serveur(self,cred_user,id_serveur=None):
1010 """récupération d'un serveur particulier (ou tous) 1011 """ 1012 if id_serveur: 1013 query="""select * from serveurs where id = %s""" 1014 return self.dbpool.runQuery(query, (int(id_serveur),)).addCallbacks(self._got_serveur,db_client_failed,callbackArgs=[cred_user]) 1015 else: 1016 query="""select * from serveurs""" 1017 return self.dbpool.runQuery(query).addCallbacks(self._got_serveur,db_client_failed,callbackArgs=[cred_user])
1018
1019 - def xmlrpc_creole_version(self,cred_user,id_serveur):
1020 """renvoie la version de creole d'un serveur particulier 1021 """ 1022 try: 1023 serv = self.parent.s_pool.get(cred_user,int(id_serveur)) 1024 return 1, u(serv.version) 1025 except (KeyError, ValueError): 1026 return 0, u("""serveur inconnu : %s""" % str(id_serveur))
1027
1028 - def xmlrpc_groupe_serveur(self,cred_user,criteres={},variables={},strict=True):
1029 """récupération d'un groupe de serveurs à partir de critères 1030 """ 1031 # construction de la requête SQL de recherche 1032 if ('type_etab_lib' in criteres and criteres['type_etab_lib'] != '') or \ 1033 ('type_etab' in criteres and criteres['type_etab'] != ''): 1034 query = ["select serveurs.* from serveurs, etablissements, types_etab "] 1035 else: 1036 query = ["select * from serveurs "] 1037 params = [] 1038 if criteres != {}: 1039 query.append("where ") 1040 for nom_champ in criteres.keys(): 1041 if criteres[nom_champ] != "": 1042 if nom_champ == 'type_etab_lib': 1043 query.append("(serveurs.rne = etablissements.rne) and \ 1044 (etablissements.type = types_etab.id) and \ 1045 (types_etab.libelle ilike %s) and ") 1046 params.append(str(criteres[nom_champ])) 1047 elif nom_champ == 'type_etab': 1048 query.append("(serveurs.rne = etablissements.rne) and \ 1049 (etablissements.type = types_etab.id) and \ 1050 (etablissements.type = %s) and ") 1051 params.append(int(criteres[nom_champ])) 1052 else: 1053 query.append("(serveurs."+str(nom_champ)) 1054 if (nom_champ == 'last_contact') or (nom_champ == 'etat' and criteres[nom_champ] == "null"): 1055 query.append(" is null) and ") 1056 elif nom_champ == 'etat' and criteres[nom_champ] != '': 1057 if criteres[nom_champ] == "alertes": 1058 query.append(" <> 1) and (etat is not null) and ") 1059 else: 1060 query.append(" = %s) and ") 1061 params.append(criteres[nom_champ]) 1062 elif (nom_champ == 'md5s' and criteres[nom_champ] == "null"): 1063 query.append(" is null) and ") 1064 elif nom_champ in ['module_actuel','module_initial','variante','timeout','md5s', 'id','no_alert'] and criteres[nom_champ] != '': 1065 query.append(" = %s) and ") 1066 params.append(int(criteres[nom_champ])) 1067 elif nom_champ == 'date_install': 1068 # cas particulier : l'operateur est inclus dans les données 1069 query.append(" %s) and " % str(criteres[nom_champ])) 1070 elif nom_champ == 'maj': 1071 if str(criteres[nom_champ]) == 'outdated': 1072 query.append(" > 0) and ") 1073 elif str(criteres[nom_champ]) == 'uptodate': 1074 query.append(" = 0) and ") 1075 else: 1076 query.append(" < 0 or %s is null) and " % str(nom_champ)) 1077 else: 1078 query.append(" ilike %s) and ") 1079 params.append(str(criteres[nom_champ])) 1080 query[-1] = query[-1][:query[-1].rindex('and')] 1081 1082 query.append("order by RNE,module_actuel") 1083 query = "".join(query) 1084 if variables != {}: 1085 return self.dbpool.runQuery(query, params).addCallbacks(self._groupe_serveur_vars, db_client_failed, callbackArgs=[variables, strict, cred_user]) 1086 else: 1087 return self.dbpool.runQuery(query, params).addCallbacks(self._got_serveur, db_client_failed,callbackArgs=[cred_user])
1088
1089 - def _groupe_serveur_vars(self, serveurs, variables, strict, cred_user):
1090 """Recherche des serveurs en fonction d'un variable de configuration 1091 """ 1092 l=[] 1093 auth_error = False 1094 for serveur in serveurs: 1095 # on ne renvoie que les serveurs accessibles 1096 try: 1097 serv = self.parent.s_pool.get(cred_user,int(serveur[0])) 1098 except ResourceAuthError: 1099 auth_error = True 1100 continue 1101 # lecture de la configuration du serveur 1102 try: 1103 d = serv.parsedico(encode=True) 1104 except: 1105 # pas de config définie ? 1106 continue 1107 val_found = False 1108 for var, criteres in variables.items(): 1109 name, val, negate = criteres 1110 if serv.version != "creole1": 1111 val = val.split('| ') 1112 val = [value.strip() for value in val] 1113 try: 1114 if (d[name].split('| ') == val and not negate) or (d[name].split('| ') != val and negate): 1115 val_found = True 1116 if not strict: 1117 # mode non strict : un seul critère suffit 1118 break 1119 elif strict: 1120 # mode strict : tous les critères doivent être remplis 1121 val_found = False 1122 break 1123 except: 1124 # variable inconnue ? 1125 pass 1126 if val_found: 1127 l.append(self._format_serv(serveur,serv)) 1128 if l == [] and auth_error == True: 1129 # aucun serveur n'est autorisé dans ce groupe 1130 raise ResourceAuthError("""Vous n'avez accès à aucun serveur dans ce groupe""") 1131 return 1,u(l)
1132
1133 - def xmlrpc_groupe_reload(self,cred_user,liste_serveurs):
1134 """renvoie un groupe à partir d'une liste d'id de serveurs 1135 """ 1136 if liste_serveurs != []: 1137 params = [] 1138 # construction de la requête SQL de recherche 1139 query=["select * from serveurs where id=%s"] 1140 for serveur in liste_serveurs: 1141 params.append(int(serveur)) 1142 query.append(" or id=%s") 1143 query = "".join(query) 1144 query = query[:query.rindex('or')] 1145 query += "order by rne,module_actuel" 1146 return self.dbpool.runQuery(query, params).addCallbacks(self._got_serveur, db_client_failed,callbackArgs=[cred_user])
1147 1148 #FIXME : trou de sécu si on peut étendre les groupes 1149 # faire un nouveau groupe de droits ? 1150 # (ex: cas de l'envoi de clés ssh de connexion)
1151 - def xmlrpc_groupe_extend(self,cred_user,id_groupe,liste_serveurs):
1152 """ajoute une liste de serveurs à un groupe enregistré 1153 """ 1154 if liste_serveurs != [] and type(liste_serveurs) == list: 1155 try: 1156 self.parent.s_pool.extend_groupe(cred_user,int(id_groupe),liste_serveurs) 1157 except (KeyError, ValueError): 1158 return 0, u("""groupe non trouvé dans la base""") 1159 else: 1160 return 1, "ok" 1161 else: 1162 return 1, u("liste de serveurs à insérer vide")
1163 1164
1165 - def xmlrpc_groupe_params(self,cred_user,liste_serveurs,dico_modifs):
1166 """modification d'un serveur 1167 cette fonction prend en compte un dictionnaire qui indique les 1168 champs à modifier et leur nouvelle valeur. l'application cliente 1169 doit s'assurer que ces champs existent dans la base""" 1170 # on autorise seulement le timeout et la variante 1171 modifs = {} 1172 if dico_modifs.has_key('timeout'): 1173 modifs['timeout'] = int(dico_modifs['timeout']) 1174 if dico_modifs.has_key('variante'): 1175 modifs['variante'] = int(dico_modifs['variante']) 1176 if dico_modifs.has_key('no_alert'): 1177 modifs['no_alert'] = int(dico_modifs['no_alert']) 1178 1179 # on vérifie l'existence des serveurs 1180 liste_serv = [] 1181 for id_serveur in liste_serveurs: 1182 try: 1183 id_serveur = int(id_serveur) 1184 serv = self.parent.s_pool.get(cred_user, id_serveur) 1185 liste_serv.append(serv) 1186 except (KeyError, ValueError): 1187 return 0, u("""id de serveur non valide : %s""" % str(id_serveur)) 1188 1189 if modifs != {}: 1190 # on parcourt les serveurs 1191 erreurs = [] 1192 for serveur in liste_serv: 1193 code = 1 1194 if 'variante' in modifs.keys(): 1195 # on vérifie que la variante appartient à ce module 1196 cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD) 1197 cursor = cx.cursor() 1198 cursor.execute("""select module from variantes where id=%s""", (int(modifs['variante']),)) 1199 var_mod = cursor.fetchone() 1200 cursor.close() 1201 cx.close() 1202 libelle = serveur.get_libelle() 1203 if serveur.id_mod in var_mod: 1204 code,raison = self.parent.s_pool.edit_serveur(serveur.id_s, dico_modifs) 1205 raison = "%s (%s) : erreur d'application de la variante" % (libelle,serveur.id_s) 1206 else: 1207 code = 0 1208 raison = "%s (%s) : le module ne correspond pas à la variante" % (libelle,serveur.id_s) 1209 if code == 0: 1210 erreurs.append(raison) 1211 else: 1212 # ok , on modifie les infos dans la base postgresql 1213 params = [] 1214 query=["update serveurs set "] 1215 for cle in modifs.keys(): 1216 query.append(str(cle)) 1217 query.append("=%s, ") 1218 params.append(modifs[cle]) 1219 query="".join(query)[:-2] 1220 query += """ where id=%s""" 1221 params.append(int(serveur.id_s)) 1222 # exécution de la requête 1223 try: 1224 cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD) 1225 cursor=cx.cursor() 1226 cursor.execute(query, params) 1227 cursor.close() 1228 cx.commit() 1229 cx.close() 1230 except: 1231 erreurs.append("%s (%s) : erreur de modification de la base" % (serveur.get_libelle(),serveur.id_s)) 1232 # mise à jour du pool de serveurs 1233 serveur.update_data() 1234 1235 if erreurs != []: 1236 return 1, u(erreurs) 1237 else: 1238 return 1, u("OK") 1239 else: 1240 return 1,u("Pas de modifications à effectuer")
1241 1242
1243 - def xmlrpc_edit_serveur(self,cred_user,id_serveur,dico_modifs):
1244 """modification d'un serveur 1245 cette fonction prend en compte un dictionnaire qui indique les 1246 champs à modifier et leur nouvelle valeur. l'application cliente 1247 doit s'assurer que ces champs existent dans la base""" 1248 try: 1249 id_serveur = int(id_serveur) 1250 serv = self.parent.s_pool.get(cred_user, id_serveur) 1251 return self.parent.s_pool.edit_serveur(id_serveur, dico_modifs) 1252 except (KeyError, ValueError): 1253 return 0, u("""id de serveur non valide : %s""" % str(id_serveur))
1254
1255 - def multi_call(proxy, results, err_not_allowed=False):
1256 """renvoie le résultat d'une liste de deffered 1257 @param err_not_allowed: on sort en erreur à la première erreur si True""" 1258 result = [] 1259 for res in results: 1260 code, res = res[1] 1261 if code == 0: 1262 if err_not_allowed: 1263 return code, res 1264 result.append(res) 1265 return 1, u(result)
1266
1267 - def xmlrpc_get_status(self,cred_user,id_serveur):
1268 """fonction qui renvoie différentes informations sur les(s) serveur(s) : 1269 - présence de dico.eol 1270 - présence de config.eol 1271 - présence de la clé rsa (uucp) 1272 - état des différentes actions 1273 """ 1274 if type(id_serveur) == list: 1275 results = [] 1276 for id_serv in id_serveur: 1277 code, res = self._get_status(cred_user,id_serv) 1278 if code == 1: 1279 results.append(u(res)) 1280 return 1, results 1281 else: 1282 return self._get_status(cred_user,id_serveur)
1283
1284 - def _get_status(self,cred_user,id_serveur):
1285 # récupération des infos sur le serveur 1286 try: 1287 id_serveur = int(id_serveur) 1288 serv = self.parent.s_pool.get(cred_user, id_serveur) 1289 res = serv.get_params() 1290 except (KeyError, ValueError): 1291 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 1292 else: 1293 return 1, u(res)
1294
1295 - def xmlrpc_get_maj_infos(self, cred_user, id_serveur, show_installed=False, debnames=[]):
1296 """retourne la liste des paquets non à jour""" 1297 try: 1298 id_serveur = int(id_serveur) 1299 serv = self.parent.s_pool.get(cred_user, id_serveur) 1300 if self.parent.maj_checker: 1301 res = serv.check_maj_status(self.parent.maj_checker, show_installed, debnames) 1302 else: 1303 # service de vérification des mises à jour non disponible (instance) 1304 res = [] 1305 except (KeyError, ValueError): 1306 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 1307 else: 1308 return 1, u(res)
1309
1310 - def xmlrpc_get_alertes(self, cred_user):
1311 """renvoie la liste des serveurs en alerte""" 1312 serveurs = self.parent.s_pool.get_alertes(cred_user) 1313 # mise en forme des informations renvoyées 1314 res = [] 1315 for serv in serveurs: 1316 if not serv.no_alert: 1317 res.append([serv.get_rne(), serv.get_etab(), serv.get_libelle(), serv.get_module(), serv.id_s, serv.get_status()]) 1318 1319 return 1, u(res)
1320
1321 - def xmlrpc_get_migration_status(self, cred_user):
1322 """renvoie la liste des serveurs en alerte""" 1323 serveurs_migration = self.parent.s_pool.get_migration_status(cred_user) 1324 # mise en forme des informations renvoyées 1325 res = {} 1326 for mod_vers, serveurs in serveurs_migration.items(): 1327 res_mod = res.get(mod_vers, [[],[]]) 1328 for type_serv in [0,1]: 1329 for serv in serveurs[type_serv]: 1330 res_mod[type_serv].append([serv.get_rne(), serv.get_etab(), serv.get_libelle(), serv.get_module(), serv.id_s, type_serv]) 1331 res[mod_vers] = res_mod 1332 return 1, u(res)
1333
1334 - def xmlrpc_add_files(self,cred_user,id_serveur,dico_files,encode=False):
1335 """ajoute des fichiers, patchs, dictionnaires à un serveur 1336 """ 1337 # récupération des infos sur le serveur 1338 try: 1339 id_serveur = int(id_serveur) 1340 serv = self.parent.s_pool.get(cred_user, id_serveur) 1341 except (KeyError, ValueError): 1342 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 1343 1344 # on vérifie si des paquets non autorisés sont listés 1345 if dico_files.has_key('rpms'): 1346 use_pool = self.parent.dictpool.check_module(serv.id_mod) and len(''.join(dico_files['rpms'])) > 0 1347 if use_pool: 1348 # liste des paquets gérés au niveau variante/module 1349 denied = self.parent.dictpool.list_module(serv.id_mod, False) 1350 denied.extend(self.parent.dictpool.list_variante(serv.id_var, False)) 1351 denied = set([paq_name for paq_name in denied if not paq_name.endswith('.xml')]) 1352 # si un paquet demandé est dans la liste, on l'interdit 1353 bad_paqs = denied.intersection(set(dico_files['rpms'])) 1354 if bad_paqs: 1355 return 0, u("""paquet déjà référencé au niveau du module ou de la variante : %s""" % ', '.join(bad_paqs)) 1356 # dans le cas d'un serveur eole1, on encode le contenu des fichiers en iso8859 si nécessaire 1357 if serv.version == 'creole1' and encode == True: 1358 for type_f, files in dico_files.items(): 1359 if type_f in ['dicos','patchs','persos','fichiers_zeph']: 1360 encoded_files = [] 1361 for fichier in dico_files[type_f]: 1362 content = unicode(base64.decodestring(fichier[1]),config.charset).encode('ISO-8859-1') 1363 localpath = "" 1364 if len(fichier) == 3: 1365 localpath = fichier[2] 1366 encoded_files.append([fichier[0], base64.encodestring(content),localpath]) 1367 dico_files[type_f] = encoded_files 1368 1369 # on met en place les différents types de fichiers 1370 dest_dir = serv.get_confdir() 1371 # on récupère la liste des fichiers à supprimer existante 1372 liste_remove = [] 1373 if os.path.isfile(dest_dir+os.sep+'fichiers_zephir/removed'): 1374 f_rem = open(dest_dir+os.sep+'fichiers_zephir/removed') 1375 for fic in f_rem.read().strip().split('\n'): 1376 liste_remove.append(fic) 1377 f_rem.close() 1378 def check_removed(nom_dest): 1379 # on regarde si le fichier était dans la liste des fichiers obsolètes 1380 if nom_dest in liste_remove: 1381 liste_remove.remove(nom_dest) 1382 f_rem = open(dest_dir+os.sep+'fichiers_zephir/removed', 'w') 1383 f_rem.write('\n'.join(liste_remove)) 1384 f_rem.close()
1385 # dictionnaires locaux 1386 if dico_files.has_key('dicos'): 1387 for dico in dico_files['dicos']: 1388 try: 1389 if dico[0] != "": 1390 if serv.version == 'creole1': 1391 f=open(dest_dir+os.sep+'dicos/'+os.sep+os.path.basename(dico[0].replace("\\","/")),'w') 1392 else: 1393 f=open(dest_dir+os.sep+'dicos/local/'+os.sep+os.path.basename(dico[0].replace("\\","/")),'w') 1394 f.write(base64.decodestring(dico[1])) 1395 f.close() 1396 except: 1397 return 0,u("erreur de sauvegarde de %s" % dico) 1398 1399 if dico_files.has_key('persos'): 1400 for template in dico_files['persos']: 1401 try: 1402 if template[0] != "": 1403 f=open(dest_dir+os.sep+'fichiers_perso'+os.sep+os.path.basename(template[0].replace("\\","/")),'w') 1404 f.write(base64.decodestring(template[1])) 1405 f.close() 1406 check_removed(os.path.join('fichiers_perso', template[0].replace("\\","/"))) 1407 except: 1408 return 0,u("erreur de sauvegarde de %s" % template) 1409 1410 if dico_files.has_key('patchs'): 1411 for patch in dico_files['patchs']: 1412 try: 1413 if patch[0] != "": 1414 f=open(dest_dir+os.sep+'patchs'+os.sep+os.path.basename(patch[0].replace("\\","/")),'w') 1415 f.write(base64.decodestring(patch[1])) 1416 f.close() 1417 except: 1418 return 0,u("erreur de sauvegarde de %s" % patch) 1419 1420 # on reprend la liste des fichiers existants 1421 try: 1422 f=open(dest_dir+os.sep+'fichiers_zephir/fichiers_zephir') 1423 old_content=f.read() 1424 f.close() 1425 fichiers=old_content.split('%%\n')[0] 1426 rpms=old_content.split('%%\n')[1] 1427 except: 1428 fichiers=FILE_SECTION 1429 rpms=RPM_SECTION 1430 1431 if dico_files.has_key('fichiers_zeph'): 1432 # récupération de la liste des fichiers obsolètes 1433 for fichier in dico_files['fichiers_zeph']: 1434 localpath = "" 1435 if len(fichier) == 3: 1436 localpath = fichier[2] 1437 # on enlève le nom de conteneur si présent 1438 conteneur = "" 1439 if '::' in fichier[0]: 1440 fic_path, conteneur = fichier[0].split('::') 1441 else: 1442 fic_path = fichier[0] 1443 # nettoyage du nom de fichier 1444 nom_fic = fic_path.replace("\\","/") 1445 # on supprime les séparateurs en fin de ligne 1446 if fic_path.endswith('/'): 1447 nom_fic = fic_path[:-1] 1448 if fic_path.endswith("\\"): 1449 nom_fic = fic_path[:-2] 1450 if conteneur: 1451 nom_final = "%s::%s" % (nom_fic, conteneur) 1452 else: 1453 nom_final = nom_fic 1454 check_removed(nom_final) 1455 # 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 1456 if nom_final not in fichiers.split('\n') and localpath == "": 1457 fichiers = fichiers.strip() + '\n' + nom_final +'\n' 1458 # on écrit le contenu du fichier 1459 try: 1460 if nom_fic != "": 1461 if localpath == "": 1462 f=open(os.path.join(dest_dir,'fichiers_zephir',os.path.basename(nom_final)),'w') 1463 else: 1464 f=open(os.path.join(dest_dir,localpath,os.path.basename(nom_final)),'w') 1465 f.write(base64.decodestring(fichier[1])) 1466 f.close() 1467 except: 1468 return 0,u("erreur de sauvegarde de %s" % fichier) 1469 1470 # rpms 1471 if dico_files.has_key('rpms'): 1472 for rpm in dico_files['rpms']: 1473 # on ajoute le rpm si il n'est pas présent 1474 if rpm not in rpms.split('\n'): 1475 rpms = rpms.strip() + '\n' + rpm +'\n' 1476 1477 f=open(dest_dir+os.sep+'fichiers_zephir/fichiers_zephir','w') 1478 f.write(fichiers+"%%\n" + rpms) 1479 f.close() 1480 1481 if use_pool: 1482 # synchronisation des fichiers de dictionnaires 1483 # si gérés pour ce module 1484 self.parent.dictpool.sync_serveur_packages(serv.id_s) 1485 # recalcul de l'état de la configuration 1486 new_method = serv.check_min_version(self.parent.maj_checker, 'zephir-client', '2.3-eole54~1') 1487 serv.check_md5conf(new_method) 1488 return 1,u("ok")
1489
1490 - def xmlrpc_del_files(self,cred_user,id_serveur,dico_files, remove=False):
1491 """suppression de fichiers, patchs, dictionnaires d'un serveur 1492 @remove : si True, les fichiers (divers) retirés seront également 1493 supprimés sur le serveur cible 1494 """ 1495 try: 1496 id_serveur = int(id_serveur) 1497 serv = self.parent.s_pool.get(cred_user, id_serveur) 1498 except (KeyError, ValueError): 1499 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 1500 # répertoire de destination du serveur 1501 dest_dir = serv.get_confdir() 1502 if remove: 1503 liste_remove = [] 1504 # on récupère la liste des fichiers à supprimer existante 1505 if os.path.isfile(dest_dir+os.sep+'fichiers_zephir/removed'): 1506 f_rem = open(dest_dir+os.sep+'fichiers_zephir/removed') 1507 for fic in f_rem.read().strip().split('\n'): 1508 liste_remove.append(fic) 1509 f_rem.close() 1510 # dictionnaires locaux 1511 if dico_files.has_key('dicos'): 1512 for dico in dico_files['dicos']: 1513 try: 1514 if dico != "": 1515 if serv.version == 'creole1': 1516 os.unlink(dest_dir+os.sep+'dicos'+os.sep+dico) 1517 else: 1518 os.unlink(dest_dir+os.sep+'dicos/local'+os.sep+dico) 1519 except: 1520 return 0,u("erreur de suppression de %s" % dico) 1521 1522 # fichiers templates creole 1523 if dico_files.has_key('persos'): 1524 for template in dico_files['persos']: 1525 try: 1526 if template != "": 1527 os.unlink(dest_dir+os.sep+'fichiers_perso'+os.sep+template) 1528 except: 1529 return 0,u("erreur de supression de %s" % template) 1530 # on supprime les droits associés si nécessaire 1531 self.parent.s_pool.del_file_perms(dest_dir,'fichiers_perso'+os.sep+template) 1532 # si demandé, on ajoute le template à la liste des fichiers à supprimer sur le serveur 1533 if remove: 1534 fic_sup = os.path.join('fichiers_perso', template) 1535 if fic_sup not in liste_remove: 1536 liste_remove.append(fic_sup) 1537 1538 1539 # patchs 1540 if dico_files.has_key('patchs'): 1541 for patch in dico_files['patchs']: 1542 try: 1543 if patch != "": 1544 os.unlink(dest_dir+os.sep+'patchs'+os.sep+patch) 1545 except: 1546 return 0,u("erreur de suppression de %s" % patch) 1547 1548 if dico_files.has_key('fichiers_zeph') or dico_files.has_key('rpms'): 1549 # on reprend la liste des fichiers existants 1550 try: 1551 f=open(dest_dir+os.sep+'fichiers_zephir/fichiers_zephir') 1552 old_content=f.read() 1553 f.close() 1554 fichiers=old_content.split('%%\n')[0] 1555 rpms=old_content.split('%%\n')[1] 1556 except: 1557 fichiers="""# section 1 1558 # liste des fichiers à sauvegarder pour la variante 1559 # (ne pas modifier sauf pour créer ou mettre à jour la variante)""" 1560 rpms="""# section 2 1561 # inscrire les noms des paquetages qui seront installés à la mise à jour du serveur 1562 # (ils doivent être présents sur le serveur de mise à jour)""" 1563 1564 # fichiers divers 1565 if dico_files.has_key('fichiers_zeph'): 1566 liste=fichiers.split('\n') 1567 for fichier in dico_files['fichiers_zeph']: 1568 localpath = "fichiers_zephir" 1569 if type(fichier) in (list, tuple) and len(fichier) == 2: 1570 localpath = fichier[1] 1571 fichier = fichier[0] 1572 fichier = fichier.replace("\\","/") 1573 # on supprime le fichier de la liste 1574 if fichier in liste: 1575 liste.remove(fichier) 1576 fichiers = "\n".join(liste) 1577 fic_path = os.path.join(dest_dir,localpath,os.path.basename(fichier)) 1578 # on efface le fichier 1579 try: 1580 if fichier != "": 1581 if os.path.isdir(fic_path): 1582 shutil.rmtree(fic_path) 1583 elif os.path.isfile(fic_path): 1584 os.unlink(fic_path) 1585 except: 1586 f=open(dest_dir+os.sep+'fichiers_zephir/fichiers_zephir','w') 1587 f.write(fichiers+"%%\n"+rpms) 1588 f.close() 1589 return 0,u("erreur de suppression de %s" % fichier) 1590 # on supprime les droits associés si nécessaire 1591 fic_sup = os.path.join(localpath,os.path.basename(fichier)) 1592 self.parent.s_pool.del_file_perms(dest_dir,fic_sup,True) 1593 # si demandé, on ajoute le fichier à la liste des fichiers à supprimer 1594 # sur le serveur cible 1595 if remove: 1596 if fichier not in liste_remove: 1597 liste_remove.append(fichier) 1598 1599 # rpms 1600 if dico_files.has_key('rpms'): 1601 for rpm in dico_files['rpms']: 1602 # on supprime le rpm si il existe 1603 liste=rpms.split('\n') 1604 if rpm in liste: 1605 liste.remove(rpm) 1606 else: 1607 f=open(dest_dir+os.sep+'fichiers_zephir/fichiers_zephir','w') 1608 f.write(fichiers+"%%\n"+rpms) 1609 f.close() 1610 return 0,u("rpm non trouvé dans la liste : %s" % rpm) 1611 1612 rpms = "\n".join(liste) 1613 1614 f=open(dest_dir+os.sep+'fichiers_zephir/fichiers_zephir','w') 1615 f.write(fichiers+"%%\n"+rpms) 1616 f.close() 1617 if remove and liste_remove: 1618 # liste des fichiers à supprimer 1619 f=open(dest_dir+os.sep+'fichiers_zephir/removed', 'w') 1620 f.write("\n".join(liste_remove)) 1621 f.close() 1622 # recalcul de l'état de la configuration 1623 new_method = serv.check_min_version(self.parent.maj_checker, 'zephir-client', '2.3-eole54~1') 1624 serv.check_md5conf(new_method) 1625 1626 return 1,u("ok")
1627
1628 - def xmlrpc_get_file_content(self,cred_user,id_serveur,path,show_details=False):
1629 """renvoie le contenu d'un fichier de serveur 1630 si le fichier est un fichier binaire, renvoie la chaine BINARY""" 1631 try: 1632 id_serveur = int(id_serveur) 1633 serv = self.parent.s_pool.get(cred_user, id_serveur) 1634 except (KeyError, ValueError): 1635 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 1636 # définition du répertoire du serveur 1637 try: 1638 dest_dir=serv.get_confdir() 1639 except: 1640 return 0,u("""lecture du fichier: paramètres non valides""") 1641 # on lit le fichier 1642 try: 1643 if serv.version == "creole1": 1644 path = path.replace('dicos/local','dicos') 1645 # cas d'un répertoire 1646 if os.path.isdir(dest_dir + os.sep + path): 1647 dirfiles = os.listdir(dest_dir + os.sep + path) 1648 content = [] 1649 if show_details: 1650 for f in dirfiles: 1651 f_local = os.path.join(dest_dir,path,f) 1652 f_info = config.get_file_info(f_local) 1653 content.append((f,f_info)) 1654 else: 1655 content = dirfiles 1656 return 1, u(content) 1657 else: 1658 # on regarde si c'est un fichier texte ou binaire 1659 if istextfile(dest_dir + os.sep + path): 1660 f=file(dest_dir + os.sep + path) 1661 content=f.read() 1662 f.close() 1663 # encoding dans le charset du systeme pour les fichier eole1 1664 if serv.version == "creole1": 1665 try: 1666 content = unicode(content,'ISO-8859-1').encode(config.charset) 1667 except: 1668 # le fichier n'est pas en unicode ?? 1669 log.msg("echec d'encoding du fichier %s provenant d'un serveur eole1" % path) 1670 content = base64.encodestring(content) 1671 else: 1672 content = "BINARY" 1673 return 1, content 1674 except: 1675 return 0,u("""erreur de lecture du fichier""")
1676
1677 - def xmlrpc_get_groupe_vars(self,cred_user,serveurs,encode=False):
1678 """récupère la liste des variables communes à un groupe de serveur""" 1679 # vérification de l'existence des serveurs 1680 liste_serv = [] 1681 for id_serveur in serveurs: 1682 try: 1683 serv = self.parent.s_pool.get(cred_user, id_serveur) 1684 liste_serv.append(serv) 1685 except (KeyError, ValueError): 1686 return 0, u("""serveur inconnu dans la base zephir : %s""" % str(id_serveur)) 1687 liste_vars = {} 1688 liste_modules = [] 1689 erreurs = [] 1690 group_vars = [] 1691 first_iter=1 1692 for serveur in liste_serv: 1693 # chemin vers le dictionnaire et les dicos persos 1694 serveur_dir = serveur.get_confdir() 1695 # instance du dictionnaire 1696 d = serveur.get_config('modif_config',encode=encode) 1697 if d == None: 1698 # on ne prend pas en compte les serveurs non configurés 1699 erreurs.append("""le serveur %s (%s) n'a pas de fichier zephir.eol""" % (serveur.id_s,serveur.get_libelle())) 1700 else: 1701 # liste des variables groupées 1702 info_groups = {} 1703 if d.version == "creole2": 1704 info_groups = d.dico.groups 1705 elif d.version == "creole3": 1706 info_groups = d.groups 1707 for master, slaves in info_groups.items(): 1708 if master not in group_vars: 1709 group_vars.append(master) 1710 for slave in slaves: 1711 if slave not in group_vars: 1712 group_vars.append(slave) 1713 # on stocke la liste des variables 1714 if first_iter == 1: 1715 for var in d.liste_vars.keys(): 1716 if d.version != "creole1": 1717 liste_vars[var]=[" | ".join(d.get_value(var))] 1718 else: 1719 liste_vars[var]=[d.get_value(var)] 1720 first_iter = 0 1721 else: 1722 for var in liste_vars.keys(): 1723 if var not in d.liste_vars.keys(): 1724 # on supprime les variables qui ne sont pas dans ce dictionnaire 1725 del(liste_vars[var]) 1726 else: 1727 val=d.get_value(var) 1728 if d.version != "creole1": 1729 val = " | ".join(val) 1730 if val not in liste_vars[var]: 1731 liste_vars[var].append(val) 1732 # liste des différents modules 1733 if serveur.id_mod not in liste_modules: 1734 liste_modules.append(serveur.id_mod) 1735 # on retourne la liste des variables et des modules 1736 return 1, u([liste_vars,liste_modules,erreurs,group_vars])
1737
1738 - def xmlrpc_set_groupe_var(self,cred_user,serveurs,var,val,encode=False):
1739 """modifie une variable commune à un groupe de serveur""" 1740 # vérification de l'existence des serveurs 1741 liste_serv = [] 1742 for id_serveur in serveurs: 1743 try: 1744 serv = self.parent.s_pool.get(cred_user, id_serveur) 1745 liste_serv.append(serv) 1746 except (KeyError, ValueError): 1747 return 0, u("""serveur inconnu dans la base zephir : %s""" % str(id_serveur)) 1748 erreurs = [] 1749 for serveur in liste_serv: 1750 # chemin vers le dictionnaire et les dicos persos 1751 serveur_dir = serveur.get_confdir() 1752 # instance du dictionnaire 1753 try: 1754 d = serveur.get_config('modif_config',encode) 1755 assert d is not None 1756 except Exception,e: 1757 erreurs.append('%s-%s (%s)' % (str(serv.id_s),serveur.get_libelle(),str(e))) 1758 else: 1759 # mise en place de la valeur 1760 try: 1761 final_val = val 1762 var_info = d.get_var(var) 1763 if d.version == "creole2": 1764 # on regarde si la variable est multivaluée 1765 multi = True 1766 if d.dico.variables[var].multi == False: 1767 multi = False 1768 for master, slaves in d.dico.groups.items(): 1769 if var in slaves: 1770 multi = True 1771 if multi: 1772 final_val = [value.strip() for value in val.split("|")] 1773 elif d.version == "creole3": 1774 try: 1775 option = d.dico.unwrap_from_path(d.var_paths[var][0]) 1776 except PropertiesOptionError: 1777 # variable désactivée ou non accessible, on passe ce serveur 1778 continue 1779 multi = option.impl_is_multi() 1780 if multi: 1781 final_val = [value.strip() for value in val.split("|")] 1782 d.set_value(final_val) 1783 except Exception,e: 1784 traceback.print_exc() 1785 erreurs.append('%s-%s (%s)' % (str(serv.id_s),serveur.get_libelle(),str(e))) 1786 else: 1787 # on sauvegarde zephir.eol 1788 new_method = serveur.check_min_version(self.parent.maj_checker, 'zephir-client', '2.3-eole54~1') 1789 res = serveur.save_config(d,'modif_config',encode,force=True,new_method=new_method) 1790 if res != "": 1791 erreurs.append(res) 1792 return 1, u(erreurs)
1793
1794 - def xmlrpc_get_dico(self,cred_user,id_serveur,mode='config',encode=False):
1795 """récupération du dictionnaire de configuration selon le mode demandé 1796 (gen_dico, gen_config, modification du fichier déjà rempli""" 1797 try: 1798 id_serveur = int(id_serveur) 1799 serv = self.parent.s_pool.get(cred_user, id_serveur) 1800 except (KeyError, ValueError): 1801 return 0, u("""Serveur inconnu : %s""" % str(id_serveur)) 1802 # récupération de la configuration: 1803 try: 1804 config_serv = serv.get_config(mode,encode) 1805 except Exception, e: 1806 return 0, u("""Erreur de lecture du dictionnaire : %s""" % str(e)) 1807 # on envoie le dictionnaire en base64 1808 try: 1809 data = config_serv.get_dict() 1810 except Exception, e: 1811 return 0, u("""Erreur de lecture de la configuration : %s""" % str(e)) 1812 return 1, u(data)
1813
1814 - def xmlrpc_get_config(self,cred_user,id_serveur,encode=False):
1815 """renvoie un dictionnaire contenant la configuration du serveur demandé 1816 format {variable:valeur}""" 1817 try: 1818 id_serveur = int(id_serveur) 1819 serv = self.parent.s_pool.get(cred_user, id_serveur) 1820 except (KeyError, ValueError): 1821 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 1822 # récupération de la configuration: 1823 try: 1824 data = serv.parsedico(encode=encode) 1825 except Exception, e: 1826 return 0, u("""erreur de lecture du dictionnaire : %s""" % str(e)) 1827 # on envoie le dictionnaire en base64 1828 return 1, u(data)
1829
1830 - def xmlrpc_save_conf(self,cred_user,id_serveur,dico_zeph,mode='config',encode=False):
1831 """sauvegarde d'un dictionnaire de configuration sur zephir 1832 (soit sur zephir.eol, soit sur dico.eol)""" 1833 try: 1834 id_serveur = int(id_serveur) 1835 serv = self.parent.s_pool.get(cred_user, id_serveur) 1836 except (KeyError, ValueError): 1837 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 1838 try: 1839 # décodage du dictionnaire 1840 if mode.endswith('migration'): 1841 # initialisation du dictionnaire creole2 1842 variante = serv.variante_migration() 1843 assert int(variante) > 0 1844 cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD) 1845 cursor = cx.cursor() 1846 query = "select modules.id, modules.version from modules, variantes where modules.id=variantes.module and variantes.id=%s" 1847 cursor.execute(query, (int(variante),)) 1848 var_mod, mod_version = cursor.fetchone() 1849 cursor.close() 1850 cx.close() 1851 creole_version = config.CREOLE_VERSIONS[mod_version] 1852 d = serv.migrate_config(var_mod, variante, 'modif_migration', creole_version) 1853 else: 1854 d = serv.get_config('modif_config', encode) 1855 # mise en place des valeurs 1856 new_method = serv.check_min_version(self.parent.maj_checker, 'zephir-client', '2.3-eole54~1') 1857 d.init_from_zephir(dico_zeph) 1858 serv.save_config(d,mode,encode,new_method=new_method) 1859 except Exception, e: 1860 return 0,u(str(e)) 1861 else: 1862 return 1,u('ok')
1863
1864 - def xmlrpc_save_bastion(self,cred_user,id_serveur,bastion_base64,modele,encode=False):
1865 """sauvegarde d'un modèle de firewall 1866 """ 1867 try: 1868 id_serveur = int(id_serveur) 1869 serv = self.parent.s_pool.get(cred_user, id_serveur) 1870 except (KeyError, ValueError): 1871 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 1872 return self._save_bastion([serv],bastion_base64,'fichiers_zephir/modeles/%s.xml' % modele, encode)
1873
1874 - def xmlrpc_save_bastion_groupe(self,cred_user,groupe,bastion_base64,modele,encode=False):
1875 """ récupère les informations sur les serveurs du groupe 1876 """ 1877 query = """select serveurs from groupes_serveurs where id = %s""" 1878 return self.dbpool.runQuery(query, (int(groupe),)).addCallbacks(self._save_bastion_groupe,db_client_failed,callbackArgs=[cred_user,bastion_base64,modele,encode])
1879
1880 - def _save_bastion_groupe(self,data,cred_user,bastion_base64,modele,encode):
1881 """sauvegarde d'un modèle de firewall sur un groupe de serveurs 1882 """ 1883 try: 1884 serveurs=eval(data[0][0]) 1885 except: 1886 return 0, u("impossible de retrouver les serveurs du groupe") 1887 # vérification de la validité des serveurs 1888 liste_serv = [] 1889 for id_serveur in serveurs: 1890 try: 1891 serv = self.parent.s_pool.get(cred_user, int(id_serveur)) 1892 except (KeyError, ValueError): 1893 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 1894 if serv.get_module().startswith('amon'): 1895 liste_serv.append(serv) 1896 return self._save_bastion(liste_serv, bastion_base64, 'fichiers_zephir/modeles/%s.xml' % modele, encode)
1897
1898 - def _save_bastion(self,serveurs,fichier_base64,filename,encode):
1899 """sauvegarde d'un fichier dans l'arborescence d'un serveur""" 1900 # décodage du fichier 1901 contenu = base64.decodestring(fichier_base64) 1902 # sauvegarde 1903 erreurs = [] 1904 for serveur in serveurs: 1905 # on ajoute les fichiers du modèle 1906 serveur_dir = serveur.get_confdir() 1907 # on cherche le nom du modèle 1908 try: 1909 d = serveur.get_config('modif_config',encode) 1910 try: 1911 if not os.path.isdir(serveur_dir+'/fichiers_zephir/modeles'): 1912 os.mkdir(serveur_dir+'/fichiers_zephir/modeles') 1913 # on ajoute le répertoire des modèles à la liste des fichiers à sauvegarder 1914 # (il devrait déjà y être si une sauvegarde a eu lieu) 1915 modele=open(serveur_dir+'/fichiers_zephir/modeles'+os.sep+os.path.basename(filename),'w') 1916 modele.write(contenu) 1917 modele.close() 1918 except: 1919 # le répertoire des modèles n'est peut-être pas encore remonté sur zephir 1920 pass 1921 else: 1922 # on demande à amon d'utiliser modele.xml 1923 d.get_var('type_amon') 1924 d.set_value(os.path.splitext(os.path.basename(filename))[0]) 1925 # sauvegarde du dictionnaire 1926 new_method = serveur.check_min_version(self.parent.maj_checker, 'zephir-client', '2.3-eole54~1') 1927 serveur.save_config(d,'modif_config',encode,new_method=new_method) 1928 except: 1929 # problème avec le fichier zephir.eol 1930 erreurs.append(str(serveur.id_s)) 1931 # on ajoute le répertoire des modèles à la liste des fichiers zephir si il n'y est pas déjà 1932 # on reprend la liste des fichiers existants 1933 try: 1934 f=open(serveur_dir+os.sep+'fichiers_zephir/fichiers_zephir') 1935 old_content=f.read() 1936 f.close() 1937 fichiers=old_content.split('%%\n')[0] 1938 rpms=old_content.split('%%\n')[1] 1939 except: 1940 fichiers=FILE_SECTION 1941 rpms=RPM_SECTION 1942 1943 # on ajoute le fichier à la liste si il n'est pas déjà présent 1944 ligne = "/usr/share/eole/bastion/modeles" 1945 if ligne not in fichiers.split('\n'): 1946 fichiers = fichiers.strip() + '\n' + ligne +'\n' 1947 try: 1948 f=open(serveur_dir+os.sep+'fichiers_zephir/fichiers_zephir','w') 1949 f.write(fichiers+"%%\n"+rpms) 1950 f.close() 1951 except: 1952 erreur.append("ajout à la liste des fichiers zephir") 1953 if erreurs != []: 1954 return 0,u("""erreur de sauvegarde du fichier %s sur le(s) serveur(s) %s""" % (filename,",".join(erreurs))) 1955 1956 return 1,u('ok')
1957
1958 - def xmlrpc_get_bastion(self,cred_user,id_serveur,encode=False):
1959 """récupération d'un modèle de firewall 1960 """ 1961 try: 1962 id_serveur = int(id_serveur) 1963 serv = self.parent.s_pool.get(cred_user,id_serveur) 1964 except (KeyError, ValueError): 1965 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 1966 # lecture 1967 try: 1968 d = serv.parsedico(encode=encode) 1969 modele = d['type_amon'].split("| ")[0] 1970 data_dir = os.path.join(serv.get_confdir(),'fichiers_zephir') 1971 model_files = [ os.path.join(data_dir, 'modeles/%s.xml' % modele), 1972 os.path.join(data_dir, '%s.xml' % modele), 1973 os.path.join(data_dir, 'variante/%s.xml' % modele) 1974 ] 1975 contenu = None 1976 for model_file in model_files: 1977 if os.path.isfile(model_file): 1978 fic_zephir = open(model_file) 1979 contenu = fic_zephir.read() 1980 fic_zephir.close() 1981 assert contenu is not None 1982 except: 1983 return 0,u("""fichier de modele non trouvé pour le serveur %s""" % serv.id_s) 1984 else: 1985 return 1,base64.encodestring(contenu),modele
1986
1987 - def xmlrpc_get_log(self,cred_user,id_serveur=None,mode='zlog',liste_types=[]):
1988 """rècupère les logs d'un serveur particulier 1989 mode : - zlog : tous les logs remontés par le serveur (ou spécifiés) 1990 - autre : récupère la liste des actions zephir effectuées sur ce serveur 1991 """ 1992 params = [] 1993 query = """select id,id_serveur,date,type,message,etat from log_serveur where """ 1994 if id_serveur: 1995 query += """id_serveur=%s and""" 1996 params.append(int(id_serveur)) 1997 if mode == 'zlog': 1998 # défaut : tout sauf les commandes 1999 comp = ["<> 'COMMAND'"] 2000 # si filtre spécifié, on l'applique 2001 if liste_types != []: 2002 comp=[" in ('"] 2003 for typelog in liste_types: 2004 comp.append(typelog) 2005 comp.append("','") 2006 comp = comp[:-1] 2007 comp.append("')") 2008 else: 2009 comp = ["= 'COMMAND'"] 2010 query += """ type%s order by date desc, id desc""" % "".join(comp) 2011 return self.dbpool.runQuery(query, params).addCallbacks(self._got_log,db_client_failed,callbackArgs=[cred_user])
2012
2013 - def xmlrpc_del_log(self,cred_user,liste_serveurs,liste_types,date):
2014 """supression des logs d'un certain type antérieurs à une certaine date 2015 Attention, cette purge est effectuée sur l'ensemble des serveurs du zephir ! 2016 liste_serveurs : liste des serveurs dont on veut purger les logs 2017 liste_types : spécifie les types d'action à purger (ex : ['COMMAND','SURVEILLANCE','MAJ'] 2018 """ 2019 # création de la condition 'type de logs' de la query 2020 cond_params = [] 2021 if liste_types != []: 2022 # supression de tous les listes de log 2023 if 'TOUT' in liste_types: 2024 cond_types = "" 2025 else: 2026 #spécification des types à supprimer 2027 cond_liste = [] 2028 for type_log in liste_types: 2029 cond_liste.append("type=%s") 2030 cond_params.append(type_log) 2031 cond_types = " and (" + " or ".join(cond_liste) + ")" 2032 else: 2033 return 0,u("paramètres invalides") 2034 2035 date = str(self.dbpool.dbapi.Timestamp(int(date[2]),int(date[1]),int(date[0]),0,0,0).adapted) 2036 for serveur in liste_serveurs: 2037 # pour chaque serveur de la liste 2038 # on vérifie les droits d'accès au serveur 2039 try: 2040 self.parent.s_pool.get(cred_user, int(serveur)) 2041 except (KeyError, ValueError): 2042 return 0, u("""serveur inconnu : %s""" % str(serveur)) 2043 if int(serveur) > 0 and type(date) == str and type(liste_types) == list: 2044 query = """delete from log_serveur where id_serveur=%s""" + cond_types + " and date <= %s" 2045 params = [int(serveur)] 2046 params.extend(cond_params) 2047 params.append(date) 2048 try: 2049 # on supprime les champs 2050 self.dbpool.runOperation(query, params) 2051 except: 2052 pass 2053 else: 2054 return 0,u("paramètres invalides") 2055 2056 return 1,u("ok")
2057
2058 - def xmlrpc_fichiers_zephir(self,cred_user,id_serveur,show_details=False):
2059 """retourne la liste des fichiers personnalisés pour ce serveur 2060 @param show_detail : ajoute une information pour chaque fichier de type fichiers divers (serveur et variante) 2061 types de fichiers dispos : missing, dir ou file 2062 """ 2063 try: 2064 id_serveur = int(id_serveur) 2065 serv = self.parent.s_pool.get(cred_user,id_serveur) 2066 except (KeyError, ValueError): 2067 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 2068 else: 2069 # répertoire de stockage du serveur sur zephir 2070 serveur_dir = serv.get_confdir() 2071 # création du dictionnaire de listes des différents fichiers 2072 dico_res={} 2073 try: 2074 # dictionnaires additionnels 2075 liste_dicos = [] 2076 liste_dicos_var = [] 2077 if serv.version == 'creole1': 2078 dico_dir = serveur_dir+os.sep+'dicos' 2079 else: 2080 dico_dir = serveur_dir+os.sep+'dicos/local' 2081 for fic in os.listdir(dico_dir): 2082 if fic == 'variante': 2083 pass 2084 elif fic.endswith('.eol') or fic.endswith('.xml'): 2085 liste_dicos.append(fic) 2086 dico_res['dicos'] = liste_dicos 2087 try: 2088 # dictionnaires de la variante 2089 for fic in os.listdir(serveur_dir+os.sep+'dicos/variante'): 2090 if fic.endswith('.eol') or fic.endswith('.xml'): 2091 liste_dicos_var.append(fic) 2092 dico_res['dicos_var'] = liste_dicos_var 2093 except OSError: 2094 dico_res['dicos_var'] = ['répertoire non trouvé !'] 2095 except OSError: 2096 dico_res['dicos'] = ['répertoire non trouvé !'] 2097 try: 2098 # fichiers personnels 2099 dico_res['persos'] = os.listdir(serveur_dir+os.sep+'fichiers_perso') 2100 try: 2101 dico_res['persos'].remove('variante') 2102 except: 2103 pass 2104 except OSError: 2105 dico_res['persos'] = ['répertoire non trouvé !'] 2106 try: 2107 # fichiers personnels variante 2108 dico_res['persos_var'] = (os.listdir(serveur_dir+os.sep+'fichiers_perso/variante')) 2109 except OSError: 2110 dico_res['persos_var'] = ['répertoire non trouvé !'] 2111 try: 2112 # patchs 2113 dico_res['patchs'] = os.listdir(serveur_dir+os.sep+'patchs') 2114 try: 2115 dico_res['patchs'].remove('variante') 2116 except: 2117 pass 2118 except OSError: 2119 dico_res['patchs'] = ['répertoire non trouvé !'] 2120 try: 2121 # patchs variante 2122 dico_res['patchs_var'] = os.listdir(serveur_dir+os.sep+'patchs/variante') 2123 except OSError: 2124 dico_res['patchs_var'] = ['répertoire non trouvé !'] 2125 try: 2126 # RPMS 2127 # lecture de la liste des rpms supplémentaires 2128 fic = open(serveur_dir+'/fichiers_zephir/fichiers_zephir') 2129 data = fic.read().strip().split("\n") 2130 fic.close() 2131 # recherche de la section des RPMS 2132 liste_pkg = [] 2133 section_rpm = 0 2134 for ligne in data: 2135 ligne = ligne.strip() 2136 if section_rpm == 1: 2137 # on regarde si on a bien affaire à un paquetage 2138 if not ligne.startswith('#') and ligne != '': 2139 # on affiche le nom du paquetage 2140 liste_pkg.append(ligne) 2141 if ligne == '%%': 2142 section_rpm = 1 2143 dico_res['rpms'] = liste_pkg 2144 except IOError: 2145 dico_res['rpms'] = [] 2146 try: 2147 # RPMS variante 2148 # lecture de la liste des rpms supplémentaires 2149 fic = open(serveur_dir+'/fichiers_zephir/variante/fichiers_variante') 2150 data = fic.read().strip().split("\n") 2151 fic.close() 2152 # recherche de la section des RPMS 2153 liste_pkg_var = [] 2154 section_rpm = 0 2155 for ligne in data: 2156 ligne = ligne.strip() 2157 if section_rpm == 1: 2158 # on regarde si on a bien affaire à un paquetage 2159 if not ligne.startswith('#') and ligne != '': 2160 # on affiche le nom du paquetage 2161 liste_pkg_var.append(ligne) 2162 if ligne == '%%': 2163 section_rpm = 1 2164 dico_res['rpms_var'] = liste_pkg_var 2165 except IOError: 2166 dico_res['rpms_var'] = [] 2167 # fichiers du module 2168 liste_fic=[] 2169 # templates du serveur 2170 try: 2171 f=open(serveur_dir+os.sep+'fichiers_zephir/fichiers_zephir') 2172 old_content=f.read() 2173 f.close() 2174 fichiers=old_content.split('%%\n')[0] 2175 except: 2176 fichiers="" 2177 for f_zeph in fichiers.split('\n'): 2178 # si conteneur présent, on garde seulement le chemin de fichier 2179 if f_zeph.strip().startswith("""/"""): 2180 f_local = os.path.join(serveur_dir,'fichiers_zephir',os.path.basename(f_zeph.strip())) 2181 if show_details: 2182 f_info = config.get_file_info(f_local) 2183 liste_fic.append((f_zeph,f_info)) 2184 elif os.path.exists(f_local): 2185 liste_fic.append(f_zeph) 2186 dico_res['fichiers_zeph'] = liste_fic 2187 liste_fic=[] 2188 try: 2189 f=open(serveur_dir+os.sep+'fichiers_zephir/variante/fichiers_variante') 2190 old_content=f.read() 2191 f.close() 2192 fichiers=old_content.split('%%\n')[0] 2193 except: 2194 fichiers="" 2195 for f_zeph in fichiers.split('\n'): 2196 if f_zeph.strip().startswith("/"): 2197 f_local = os.path.join(serveur_dir,'fichiers_zephir','variante',os.path.basename(f_zeph.strip())) 2198 if show_details: 2199 f_info = config.get_file_info(f_local) 2200 liste_fic.append((f_zeph,f_info)) 2201 elif os.path.exists(f_local): 2202 liste_fic.append(f_zeph) 2203 dico_res['fichiers_var'] = liste_fic 2204 2205 return 1,u(dico_res)
2206
2207 - def xmlrpc_get_serveur_perms(self, cred_user, id_serveur, filepath=""):
2208 """renvoie les informations de permissions associées à un fichier 2209 """ 2210 try: 2211 id_serveur = int(id_serveur) 2212 serv = self.parent.s_pool.get(cred_user,id_serveur) 2213 except (KeyError, ValueError): 2214 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 2215 else: 2216 result = self.parent.s_pool.get_file_perms(serv.get_confdir(), filepath) 2217 return 1, u(result)
2218
2219 - def xmlrpc_del_serveur_perms(self, cred_user, id_serveur, filepath=""):
2220 """renvoie les informations de permissions associées à un fichier 2221 """ 2222 try: 2223 id_serveur = int(id_serveur) 2224 serv = self.parent.s_pool.get(cred_user,id_serveur) 2225 except (KeyError, ValueError): 2226 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 2227 else: 2228 result = self.parent.s_pool.del_file_perms(serv.get_confdir(), filepath) 2229 return 1, u(result)
2230
2231 - def xmlrpc_set_serveur_perms(self, cred_user, id_serveur, rights):
2232 """enregistre les informations de permissions associées à un(des) fichier(s) 2233 @param rights: dictionnaire au format suviant : {'filepath':[mode,ownership]} 2234 """ 2235 try: 2236 id_serveur = int(id_serveur) 2237 serv = self.parent.s_pool.get(cred_user,id_serveur) 2238 except (KeyError, ValueError): 2239 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 2240 else: 2241 data_dir = serv.get_confdir() 2242 res = self.parent.s_pool.set_file_perms(rights, data_dir) 2243 if res: 2244 return 1,"OK" 2245 else: 2246 return 0, u("""erreur d'enregistrement des permissions""")
2247
2248 - def xmlrpc_copy_perms(self, cred_user, id_src, serveurs, keep=True):
2249 """copie les permissions définies sur le serveur id_src 2250 sur le groupe de serveurs serveurs 2251 @param keep: si True, on n'écrase pas les permissions restantes pour un fichier 2252 """ 2253 try: 2254 id_src = int(id_src) 2255 src = self.parent.s_pool.get(cred_user,id_src) 2256 # on récupère les permissions à insérer 2257 perms = self.parent.s_pool.get_file_perms(src.get_confdir()) 2258 except (KeyError, ValueError): 2259 return 0, u("""serveur inconnu : %s""" % str(id_src)) 2260 else: 2261 forbidden = [] 2262 # on recherche les destinations accessibles 2263 for id_dst in serveurs: 2264 try: 2265 id_dst = int(id_dst) 2266 dst = self.parent.s_pool.get(cred_user, id_dst) 2267 except: 2268 forbidden.append(id_dst) 2269 else: 2270 if id_dst != id_src: 2271 # si keep est vrai, on récupère les permissions existantes 2272 existing = [] 2273 if keep == True: 2274 existing = self.parent.s_pool.get_file_perms(dst.get_confdir()).keys() 2275 # calcul des permissions a modifier 2276 updates = {} 2277 for ficperm, data in perms.items(): 2278 if ficperm not in existing: 2279 updates[ficperm] = perms[ficperm] 2280 # application 2281 self.parent.s_pool.set_file_perms(updates, dst.get_confdir()) 2282 # on renvoie la liste des serveurs non accessibles 2283 return 1, u(forbidden)
2284
2285 - def xmlrpc_global_status(self,cred_user,id_serveur):
2286 """récupère l'etat général d'un ou plusieurs serveur(s) 2287 """ 2288 if type(id_serveur) == list: 2289 results = [] 2290 for id_serv in id_serveur: 2291 code, res = self._global_status(cred_user,id_serv) 2292 if code == 0: 2293 return code, res 2294 else: 2295 results.append(res) 2296 return 1, u(results) 2297 else: 2298 return self._global_status(cred_user,id_serveur)
2299
2300 - def _global_status(self, cred_user, id_serveur):
2301 """lit l'état d'un serveur dans la base 2302 """ 2303 try: 2304 id_serveur = int(id_serveur) 2305 serv = self.parent.s_pool.get(cred_user,id_serveur) 2306 except (KeyError, ValueError): 2307 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 2308 etat = serv.get_status() 2309 if etat == None: 2310 return 1, -1 2311 if etat in [0,2]: 2312 return 1, 0 2313 else: 2314 return 1, etat 2315 return 0, u("""erreur de récupération des données""")
2316
2317 - def xmlrpc_get_measure(self, cred_user, serveurs=None):
2318 """renvoie les données de la dernière mesure des agents 2319 """ 2320 if serveurs == None: 2321 serveurs = self.agent_manager.keys() 2322 elif type(serveurs) != list: 2323 serveurs = [serveurs] 2324 measures = [] 2325 for id_serveur in serveurs: 2326 try: 2327 serv = self.parent.s_pool.get(cred_user,int(id_serveur)) 2328 except (KeyError, ValueError): 2329 # serveur non accessible 2330 pass 2331 if self.agent_manager[str(id_serveur)] != None: 2332 measures.append("%s:%s" % (str(id_serveur), str(self.agent_manager[str(id_serveur)].get_measure()))) 2333 #measures[str(id_serveur)] = self.agent_manager[str(id_serveur)].get_measure() 2334 # on remplace la dernière virgule par la fermeture du dictionnaire 2335 measures = "{" + ",".join(measures) + "}" 2336 #measures = base64.encodestring(measures) 2337 return 1, u(measures)
2338
2339 - def xmlrpc_agents_status(self,cred_user,id_serveur):
2340 """récupère l'etat des agents d'un serveur 2341 """ 2342 if type(id_serveur) == list: 2343 results = [] 2344 for id_serv in id_serveur: 2345 try: 2346 code, res = self._agents_status(cred_user,id_serv) 2347 assert code == 1 2348 results.append(u(res)) 2349 except: 2350 results.append({}) 2351 return 1, results 2352 else: 2353 return self._agents_status(cred_user,id_serveur)
2354
2355 - def _agents_status(self,cred_user,id_serveur):
2356 try: 2357 id_serveur = int(id_serveur) 2358 serv = self.parent.s_pool.get(cred_user,id_serveur) 2359 except (KeyError, ValueError): 2360 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 2361 try: 2362 if self.agent_manager.has_key(str(id_serveur)): 2363 result=self.agent_manager[str(id_serveur)].agents_status() 2364 else: 2365 try: 2366 agent = ServeurStatus(id_serveur) 2367 result = agent.get_agents_status() 2368 except: 2369 # pas de données disponibles 2370 result = {} 2371 except Exception, e: 2372 return 0, u("""erreur de récupération des données""") 2373 else: 2374 return 1, u(result)
2375 2376 ################################### 2377 ## Gestion des groupes de serveurs 2378 ################################### 2379
2380 - def xmlrpc_save_group(self,cred_user,libelle,serveurs):
2381 """enregistre un groupe de serveurs dans la base 2382 """ 2383 if self.parent.s_pool.add_groupe(cred_user, libelle, serveurs): 2384 return 1, "ok" 2385 else: 2386 return 0, u("erreur lors de l'insertion du groupe")
2387
2388 - def xmlrpc_del_group(self,cred_user,id_groupe):
2389 """supprime un groupe de serveurs de la base 2390 """ 2391 try: 2392 id_groupe = int(id_groupe) 2393 self.parent.s_pool.del_groupe(cred_user, id_groupe) 2394 except (KeyError, ValueError): 2395 return 0, u("""id de groupe invalide : %s""" % str(id_groupe)) 2396 return 1, "ok"
2397
2398 - def xmlrpc_edit_group(self,cred_user,id_groupe,libelle,serveurs):
2399 """modifie un groupe existant 2400 """ 2401 try: 2402 id_groupe = int(id_groupe) 2403 self.parent.s_pool.edit_groupe(cred_user, id_groupe, libelle, serveurs) 2404 except (KeyError, ValueError): 2405 return 0, u("""id de groupe invalide : %s""" % str(id_groupe)) 2406 return 1, "ok"
2407
2408 - def xmlrpc_get_groups(self,cred_user,id_groupe=None):
2409 """récupère un ou plusieur groupe de serveurs dans la base 2410 """ 2411 try: 2412 liste_gr = self.parent.s_pool.get_groupes(cred_user, id_groupe) 2413 except (KeyError, ValueError): 2414 return 0, u("""id de groupe invalide : %s""" % str(id_groupe)) 2415 return 1, u(liste_gr)
2416
2417 - def xmlrpc_authorize_user(self,cred_user,username,serveurs):
2418 """autorise la connexion ssh par clé pour un utilisateur 2419 """ 2420 query="""select login from users where login = %s""" 2421 return self.dbpool.runQuery(query, (username,)).addCallbacks(self._authorize_user, db_client_failed, callbackArgs=[username, serveurs])
2422
2423 - def _authorize_user(self,data,username,serveurs):
2424 try: 2425 user = data[0][0] 2426 except: 2427 return 0, u("L'utilisateur %s est inconnu" % username) 2428 for serveur in serveurs: 2429 query="""insert into serveur_auth values (%s,%s)""" 2430 self.dbpool.runOperation(query, (int(serveur), user)).addErrback(db_client_failed) 2431 return 1, u('ok')
2432
2433 - def xmlrpc_deny_user(self,cred_user,username,serveurs):
2434 """enlève la connexion ssh par clé pour un utilisateur 2435 """ 2436 liste=[int(i) for i in serveurs] 2437 query="""delete from serveur_auth where login=%s and (id_serveur=""" + " or id_serveur=".join(["%s" for serv in liste]) + ")" 2438 params = [username] 2439 params.extend(liste) 2440 return self.dbpool.runOperation(query, params).addCallbacks(lambda x : [1,'ok'], db_client_failed)
2441
2442 - def xmlrpc_get_locks(self,cred_user,serveur=None):
2443 """liste des tags de procédures interdites pour un serveur 2444 """ 2445 if serveur is None: 2446 query = """select tag,libelle from procedures""" 2447 return self.dbpool.runQuery(query).addCallbacks(self._get_locks, db_client_failed) 2448 else: 2449 query = """select lock_serveur.tag,libelle from lock_serveur,procedures where lock_serveur.tag=procedures.tag and id_serveur=%s""" 2450 return self.dbpool.runQuery(query, (int(serveur),)).addCallbacks(self._get_locks, db_client_failed)
2451
2452 - def _get_locks(self,data):
2453 """formatte la sortie pour la recherche des fonctions lockées""" 2454 locks=[] 2455 for tag in data: 2456 locks.append([tag[0],tag[1]]) 2457 return 1, u(locks)
2458
2459 - def xmlrpc_maj_locks(self,cred_user,serveurs,tags,notags=[]):
2460 """interdit un type de procédure sur un ensemble de serveurs 2461 tags : liste des tags à interdire 2462 """ 2463 if type(serveurs) != list: 2464 # si on passe un seul serveur, on le met dans une liste 2465 serveurs=[serveurs] 2466 cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD) 2467 cursor=cx.cursor() 2468 erreur= "" 2469 for serveur in serveurs: 2470 try: 2471 id_serveur = int(serveur) 2472 serv = self.parent.s_pool.get(cred_user,id_serveur) 2473 except (KeyError, ValueError): 2474 erreur = """serveur %s non retrouvé""" % str(serveur) 2475 try: 2476 # on supprime les anciennes interdictions annulées 2477 if len(notags) > 0: 2478 cursor.executemany("delete from lock_serveur where id_serveur=%s and tag=%s", [(serveur, tag) for tag in notags]) 2479 # on met à jour les interdictions 2480 query = "insert into lock_serveur (id_serveur,tag) values (%s,%s)" 2481 cursor.executemany(query, [(serveur, tag) for tag in tags]) 2482 except Exception,e: 2483 erreur = """erreur de mise à jour des locks : serveur %s""" % (str(serveur)) 2484 # si il y a une erreur, on annule tout 2485 if erreur != "": 2486 cx.rollback() 2487 cx.close() 2488 return 0, u(erreur) 2489 # mise à jour ok 2490 cursor.close() 2491 cx.commit() 2492 cx.close() 2493 return 1, 'OK'
2494
2495 - def xmlrpc_get_timeout(self,cred_user,id_serveur):
2496 """récupère le délai de connexion des serveurs (en secondes) 2497 """ 2498 try: 2499 id_serveur = int(id_serveur) 2500 serv = self.parent.s_pool.get(cred_user,id_serveur) 2501 except (KeyError, ValueError): 2502 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 2503 try: 2504 timeout = serv.get_timeout() 2505 except: 2506 return 0, "erreur de récupération du timeout" 2507 return 1, timeout
2508
2509 - def xmlrpc_check_min_version(self, cred_user, id_serveur, nom_paq, version):
2510 try: 2511 id_serveur = int(id_serveur) 2512 serv = self.parent.s_pool.get(cred_user,id_serveur) 2513 except (KeyError, ValueError): 2514 return 0, u("""serveur inconnu : %s""" % str(id_serveur)) 2515 try: 2516 res = serv.check_min_version(self.parent.maj_checker, nom_paq, version) 2517 except: 2518 # pas d'info sur la version, on considère que le paquet n'est pas ok ? 2519 return 1, False 2520 return 1, res
2521