Package zephir :: Package backend :: Module uucp_rpc
[hide private]
[frames] | no frames]

Source Code for Module zephir.backend.uucp_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  # uucp_rpc.py 
   9  #   
  10  # fonctions xmlrpc pour la gestion des actions sur les serveurs dans Zephir 
  11  #        
  12  ########################################################################### 
  13  """Module gérant les actions sur les serveurs (via uucp) 
  14  """ 
  15  from zephir.backend.db_utils import * 
  16  from zephir.backend.uucp_utils import uucp_pool, UUCPError, COMMANDS 
  17  from zephir.backend import config 
  18  from zephir.backend.config import u 
  19  from zephir.backend.xmlrpceole import XMLRPCEole as XMLRPC 
  20  from zephir.monitor.collecteur import AgentCollecteur, ServeurStatus 
  21  from twisted.enterprise import adbapi 
  22  from twisted.internet import defer, reactor 
  23  from twisted.python import log 
  24   
  25  import sys,os,shutil,time,smtplib,re,time,base64,glob 
  26  from datetime import datetime 
  27  import traceback 
  28  import psycopg2 as PgSQL 
  29  from cStringIO import StringIO 
  30   
  31   
32 -class RPCUucp(XMLRPC):
33 """serveur XMLRPC zephir pour la gestion des actions sur les serveurs 34 """ 35
36 - def __init__(self,parent,agent_manager,bdd='zephir-parc'):
37 self.dbpool = db_connect() 38 self.dbpool.noisy = 0 39 XMLRPC.__init__(self) 40 self.agent_manager = agent_manager 41 self.parent=parent 42 # booléen pour empêcher le lancement de plusieurs boucles 43 # de vérification des timeouts 44 self.scan_delay = config.SCAN_DELAY 45 # au lancement, on modifie la date de dernier contact 46 # des serveurs pour éviter des alertes injustifiées 47 self.start_time = str(time.time())
48
49 - def _send_files(self,serv,archive,files,uucp=0):
50 """met en queue des fichiers ou répertoires pour un serveur distant 51 et stocke la somme md5 des fichiers envoyés dans le fichier cheksum.txt du 52 systeme en question (dans zephir/conf/rne/serveur/)""" 53 # définition du nodename uucp du système 54 id_uucp = str(serv.get_rne())+'-'+str(serv.id_s) 55 # chemin vers les fichiers du serveur sur zephir 56 serveur_dir = serv.get_confdir() 57 cmd_tar = ['cd ',serveur_dir,';','/bin/tar','--same-owner','-chpf',archive+'.tar'] 58 # création du fichier tar à envoyer 59 for fic in files: 60 # on vérifie l'existence du fichier 61 if os.path.isfile(serveur_dir+os.sep+fic) or os.path.isdir(serveur_dir+os.sep+fic): 62 cmd_tar.append(fic) 63 else: 64 # cas spécial : lien sur dico.eol, zephir.eol, droits_zephir et droits_variante (si conf pas encore saisie) 65 if fic not in ['dico.eol','zephir.eol', 'droits_variante', 'droits_zephir']: 66 # un fichier n'est pas trouvé, on annule 67 return 0, u("""fichier %s introuvable""" % serveur_dir+os.sep+fic) 68 cmd_tar.append('>/dev/null 2>&1') 69 res=os.system(" ".join(cmd_tar)) 70 if res != 0: 71 return 0, u("""erreur de creation de l'archive %s.tar dans %s""" % (archive,serveur_dir)) 72 # calcul et stockage d'un checksum md5 de l'archive 73 cmd_checksum = """cd %s ;md5sum -b %s.tar > %s.md5""" % (serveur_dir,archive,archive) 74 os.system(cmd_checksum) 75 if uucp: 76 # envoi de l'archive par uucp si demandé 77 try: 78 res = uucp_pool.add_file(id_uucp,serveur_dir+os.sep+archive+".tar") 79 except UUCPError,e: 80 return 0, u("Erreur UUCP %s" % str(e)) 81 return 1,u(archive+'.tar')
82
83 - def xmlrpc_reconfigure(self,cred_user,id_serveur):
84 """prépare la reconfiguration d'un serveur""" 85 try: 86 id_serveur = int(id_serveur) 87 serv = self.parent.s_pool.get(cred_user,id_serveur) 88 except KeyError, ValueError: 89 return 0,u("serveur inconnnu dans la base zephir") 90 else: 91 id_uucp = str(serv.get_rne())+'-'+str(id_serveur) 92 try: 93 res = uucp_pool.add_cmd(id_uucp,"zephir_client reconfigure") 94 except UUCPError,e: 95 return 0, u("Erreur UUCP %s" % str(e)) 96 return 1, u('ok')
97
98 - def xmlrpc_service_restart_groupe(self,cred_user,liste,service):
99 """prépare le redémarrage d'un service sur un groupe""" 100 erreurs=[] 101 for serveur in liste: 102 retour = self.xmlrpc_service_restart(cred_user, serveur['id'], service) 103 if retour[0] == 0: 104 erreurs.append(str(serveur['id'])+' : '+retour[1]) 105 if erreurs != []: 106 return 0,u(erreurs) 107 else: 108 return 1, u('ok')
109
110 - def xmlrpc_service_restart(self,cred_user,id_serveur,service):
111 """exécution de la commande uucp pour redémarrer un service""" 112 try: 113 id_serveur = int(id_serveur) 114 serv = self.parent.s_pool.get(cred_user, id_serveur) 115 except KeyError, ValueError: 116 return 0,u("serveur inconnnu dans la base zephir") 117 else: 118 id_uucp = str(serv.get_rne()) + '-' + str(id_serveur) 119 # appel uucp 120 try: 121 uucp_pool.add_cmd(id_uucp,"zephir_client service_restart %s" % service) 122 except UUCPError,e: 123 return 0, u("erreur uucp (%s)" % str(e)) 124 return 1,u("ok")
125
126 - def xmlrpc_reboot_groupe(self,cred_user,liste):
127 """prépare le redémarrage d'un groupe de serveurs""" 128 erreurs=[] 129 for serveur in liste: 130 retour = self.xmlrpc_reboot(cred_user, serveur['id']) 131 if retour[0] == 0: 132 erreurs.append(str(serveur['id'])+' : '+retour[1]) 133 if erreurs != []: 134 return 0,u(erreurs) 135 else: 136 return 1, u('ok')
137
138 - def xmlrpc_reboot(self,cred_user,id_serveur):
139 """exécution de la commande uucp pour redémarrer un serveur""" 140 try: 141 id_serveur = int(id_serveur) 142 serv = self.parent.s_pool.get(cred_user, id_serveur) 143 except KeyError, ValueError: 144 return 0,u("serveur inconnnu dans la base zephir") 145 else: 146 id_uucp = str(serv.get_rne()) + '-' + str(id_serveur) 147 # appel uucp 148 try: 149 uucp_pool.add_cmd(id_uucp,"zephir_client reboot") 150 except UUCPError,e: 151 return 0, u("serveur %s : erreur uucp (%s)" % (str(id_serveur), str(e))) 152 return 1,u("ok")
153 154
155 - def xmlrpc_configure(self,cred_user,id_serveur,restart = 0):
156 """prépare la configuration automatique d'un serveur 157 (envoi des fichiers de configuration)""" 158 159 return self._configure(id_serveur,restart, cred_user)
160
161 - def xmlrpc_configure_groupe(self,cred_user,liste,restart = 0):
162 """prépare la configuration automatique d'un groupe de serveurs 163 (envoi des fichiers de configuration)""" 164 erreurs = [] 165 for serveur in liste: 166 retour = self._configure(serveur['id'],restart, cred_user) 167 if retour[0] == 0: 168 erreurs.append(str(serveur['id'])+' : '+retour[1]) 169 if erreurs != []: 170 return 0, u(erreurs) 171 else: 172 return 1, u("ok")
173 174
175 - def _configure(self,id_serveur, restart, cred_user):
176 """envoie les fichiers de configuration et demande un configure-zephir""" 177 try: 178 id_serveur = int(id_serveur) 179 serv = self.parent.s_pool.get(cred_user, id_serveur) 180 except KeyError, ValueError: 181 return 0,u("serveur inconnnu dans la base zephir") 182 query = """select users.cle from users,serveur_auth where users.login=serveur_auth.login and serveur_auth.id_serveur=%s""" % id_serveur 183 cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD) 184 cursor=cx.cursor() 185 cursor.execute(query) 186 data=cursor.fetchall() 187 cursor.close() 188 cx.close() 189 id_uucp = str(serv.get_rne())+'-'+str(id_serveur) 190 # définition du répertoire du serveur 191 serveur_dir = serv.get_confdir() 192 # définition des fichiers à transférer 193 try: 194 # on prépare le fichier des clefs ssh à transférer 195 if data == []: 196 cles = "" 197 else: 198 cles = ("\n".join([base64.decodestring(i[0]) for i in data])) 199 fic_cle = open(serveur_dir+os.sep+'auth_keys','w') 200 fic_cle.writelines(base64.encodestring(cles)) 201 fic_cle.close() 202 except: 203 return 0, u("erreur de création du fichier des cles de connexion ssh") 204 files = ['dicos','patchs','fichiers_perso','fichiers_zephir','zephir.eol','dico.eol','auth_keys','droits_zephir', 'droits_variante'] 205 # files = ['dicos','patchs','fichiers_perso','fichiers_zephir','zephir.eol','dico.eol'] 206 # appel de la fonction d'envoi et de calcul des md5 207 code, message = self._send_files(serv,'config-zephir',files,uucp=1) 208 try: 209 os.unlink('auth_keys') 210 except: 211 pass 212 if code == 0: 213 return code, u(message) 214 else: 215 # les fichiers sont prêts à l'envoi, on demande un 216 # configure sur le serveur distant 217 try: 218 res = uucp_pool.add_cmd(id_uucp,"zephir_client configure") 219 except UUCPError, e: 220 return 0, u("Erreur uucp : %s" % str(e)) 221 if restart == 1: 222 # on demande un reconfigure 223 return self.xmlrpc_reconfigure(cred_user, id_serveur) 224 else: 225 return 1, u(message)
226
227 - def xmlrpc_save_conf(self,cred_user,id_serveur):
228 """prépare la sauvegarde de configuration d'un serveur""" 229 # on vérifie l'existence du serveur dans la base 230 return self._save_conf(cred_user, id_serveur)
231 232
233 - def xmlrpc_save_conf_groupe(self,cred_user,liste):
234 """prépare la sauvegarde de configuration d'un serveur""" 235 erreurs=[] 236 for serveur in liste: 237 retour = self._save_conf(cred_user, serveur['id']) 238 if retour[0] == 0: 239 erreurs.append(str(serveur['id'])+' : '+retour[1]) 240 if erreurs != []: 241 return 0,u(erreurs) 242 else: 243 return 1, u('ok')
244 245
246 - def _save_conf(self,cred_user,id_serveur):
247 """exécution de la commande uucp pour la mise à jour""" 248 try: 249 id_serveur = int(id_serveur) 250 serv = self.parent.s_pool.get(cred_user, id_serveur) 251 except KeyError, ValueError: 252 return 0,u("serveur inconnnu dans la base zephir") 253 else: 254 id_uucp = str(serv.get_rne()) + '-' + str(id_serveur) 255 # appel uucp 256 try: 257 uucp_pool.add_cmd(id_uucp,"zephir_client save_files") 258 except UUCPError,e: 259 return 0, u("erreur uucp (%s)" % str(e)) 260 return 1,u("ok")
261
262 - def xmlrpc_maj(self,cred_user,id_serveur,reconf = 0, delay = ""):
263 """prépare la mise à jour d'un serveur Eole par l'intermédiare d'uucp""" 264 # on vérifie l'existence du serveur dans la base 265 return self._maj(cred_user, id_serveur, reconf, delay)
266
267 - def xmlrpc_maj_groupe(self,cred_user,liste,reconf = 0, delay = ""):
268 """prépare la mise à jour d'un groupe de serveurs Eole par l'intermédiare d'uucp""" 269 erreurs=[] 270 for serveur in liste: 271 retour = self._maj(cred_user, serveur['id'],reconf,delay) 272 if retour[0] == 0: 273 erreurs.append("serveur "+str(serveur['id'])+' : '+retour[1]) 274 if erreurs != []: 275 return 0,u(erreurs) 276 else: 277 return 1, u('ok')
278
279 - def _maj(self,cred_user, id_serveur, reconf,delay):
280 """exécution de la commande uucp pour la mise à jour""" 281 try: 282 id_serveur = int(id_serveur) 283 serv = self.parent.s_pool.get(cred_user,id_serveur) 284 except KeyError, ValueError: 285 return 0,u("serveur inconnnu dans la base zephir") 286 else: 287 id_uucp = str(serv.get_rne()) + '-' + str(id_serveur) 288 # construction de la commande 289 try: 290 assert int(delay) > 0 291 except: 292 delay = "" 293 try: 294 uucp_pool.add_cmd(id_uucp,"zephir_client maj_auto %s" % str(delay)) 295 except UUCPError, e: 296 return 0, u("Erreur UUCP (%s)" % str(e)) 297 # si cela est demandé, on reconfigure le serveur 298 # query = """insert into log_serveur (id_serveur,date,type,message,etat) values (%s,'%s','%s','Mise a jour',0)""" % (int(id_serveur),str(time.ctime()),'COMMAND') 299 # self.dbpool.runOperation(query) 300 if reconf == 1: 301 return self.xmlrpc_reconfigure(cred_user, id_serveur) 302 else: 303 return 1, u("ok")
304 305
306 - def xmlrpc_maj_client(self,cred_user,id_serveur):
307 """prépare la mise à jour de zephir-client sur un serveur""" 308 # on vérifie l'existence du serveur dans la base 309 return self._maj_client(cred_user, id_serveur)
310
311 - def xmlrpc_maj_client_groupe(self,cred_user,liste):
312 """prépare la mise à jour de zephir-client sur un groupe de serveurs""" 313 erreurs=[] 314 for serveur in liste: 315 retour = self._maj_client(cred_user, serveur['id']) 316 if retour[0] == 0: 317 erreurs.append("serveur "+str(serveur['id'])+' : '+retour[1]) 318 if erreurs != []: 319 return 0, u(erreurs) 320 else: 321 return 1, u('ok')
322
323 - def _maj_client(self,cred_user, id_serveur):
324 """exécution de la commande uucp pour la mise à jour de zephir-client""" 325 try: 326 id_serveur = int(id_serveur) 327 serv = self.parent.s_pool.get(cred_user,id_serveur) 328 except KeyError, ValueError: 329 return 0,u("serveur inconnnu dans la base zephir") 330 else: 331 id_uucp = str(serv.get_rne()) + '-' + str(id_serveur) 332 # construction de la commande 333 try: 334 uucp_pool.add_cmd(id_uucp,"zephir_client maj_client") 335 except UUCPError, e: 336 return 0, u("Erreur UUCP (%s)" % str(e)) 337 else: 338 return 1, u("ok")
339
340 - def xmlrpc_sphynx_add(self,cred_user,id_sphynx,id_amon,content):
341 """stocke la configuration vpn d'un amon vers ce sphynx""" 342 try: 343 id_sphynx = int(id_sphynx) 344 id_amon = int(id_amon) 345 sphynx = self.parent.s_pool.get(cred_user,id_sphynx) 346 amon = self.parent.s_pool.get(cred_user,id_amon) 347 except KeyError, ValueError: 348 return 0,u("serveur inconnnu dans la base zephir") 349 # on vérifie l'existence d'amon 350 if not amon.get_module().startswith('amon-'): 351 return 0, "serveur invalide : %s" % str(id_amon) 352 # on regarde si ce tunnel existe déjà 353 cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD) 354 cursor=cx.cursor() 355 query = """select id_amon from conf_vpn where id_sphynx=%s""" % id_sphynx 356 cursor.execute(query) 357 data=cursor.fetchall() 358 cursor.close() 359 cx.close() 360 361 # chemin de sauvegarde de l'archive contenant la conf VPN 362 sphynx_dir = sphynx.get_confdir() 363 if not os.path.exists(sphynx_dir + os.sep + 'vpn'): 364 os.makedirs(sphynx_dir + os.sep + 'vpn') 365 archive = sphynx_dir + os.sep + 'vpn' + os.sep + str(id_amon) + '.tar.gz' 366 # mise à jour de la table des tunnels configurés 367 confs = [ligne[0] for ligne in data] 368 if int(id_amon) in confs: 369 # on a déjà une conf vpn pour cet amon, mise à jour 370 query = """update conf_vpn set etat=%s where id_sphynx=%s and id_amon=%s""" % (0,int(id_sphynx),int(id_amon)) 371 else: 372 # sinon, insertion 373 query = """insert into conf_vpn (id_sphynx,id_amon,etat) values (%s,%s,%s)""" % (int(id_sphynx),int(id_amon),0) 374 return self.dbpool.runOperation(query).addCallbacks(self._sphynx_add,db_client_failed,callbackArgs=[archive,content])
375
376 - def _sphynx_add(self,result,archive,content):
377 """écriture de la conf vpn""" 378 try: 379 file = StringIO() 380 data = base64.decodestring(content) 381 fd = open(archive,'wb') 382 # sauvegarde du fichier 383 file.write(data) 384 file.seek(0) 385 fd.write(file.read()) 386 fd.close() 387 except: 388 return 0, u("erreur de sauvegarde de l'archive") 389 return 1, "OK"
390
391 - def xmlrpc_sphynx_del(self,cred_user,id_sphynx,id_amon,del_row=0):
392 """supprime la configuration vpn d'un amon vers ce sphynx""" 393 try: 394 id_sphynx = int(id_sphynx) 395 id_amon = int(id_amon) 396 sphynx = self.parent.s_pool.get(cred_user,id_sphynx) 397 amon = self.parent.s_pool.get(cred_user,id_amon) 398 except KeyError, ValueError: 399 return 0,u("serveur inconnnu dans la base zephir") 400 cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD) 401 cursor=cx.cursor() 402 query = """select etat from conf_vpn where id_sphynx=%s and id_amon=%s""" % (str(id_sphynx),str(id_amon)) 403 cursor.execute(query) 404 data=cursor.fetchone() 405 etat = data[0] 406 cursor.close() 407 cx.close() 408 try: 409 # chemin de l'archive contenant la conf VPN 410 sphynx_dir = sphynx.get_confdir() 411 archive = sphynx_dir + os.sep + 'vpn' + os.sep + str(id_amon) + '.tar.gz' 412 os.unlink(archive) 413 except: 414 if del_row == 0: 415 return 0, u("fichier de configuration vpn non supprimé (ou inexistant)") 416 if del_row == 1: 417 query = """delete from conf_vpn where id_sphynx=%s and id_amon=%s""" % (id_sphynx,id_amon) 418 else: 419 nouv_etat=2 420 # si l'archive n'a pas été récupérée : anomalie 421 if int(etat) == 0: 422 nouv_etat=3 423 query = """update conf_vpn set etat=%s where id_sphynx=%s and id_amon=%s""" % (nouv_etat,id_sphynx,id_amon) 424 return self.dbpool.runOperation(query).addCallbacks(lambda x : [1,u("OK")],db_client_failed)
425
426 - def xmlrpc_sphynx_get(self,cred_user,id_sphynx,id_amon):
427 """envoie la configuration vpn d'un amon vers ce sphynx""" 428 try: 429 id_sphynx = int(id_sphynx) 430 id_amon = int(id_amon) 431 sphynx = self.parent.s_pool.get(cred_user,id_sphynx) 432 amon = self.parent.s_pool.get(cred_user,id_amon) 433 except KeyError, ValueError: 434 return 0,u("serveur inconnnu dans la base zephir") 435 try: 436 # chemin de l'archive contenant la conf VPN 437 sphynx_dir = sphynx.get_confdir() 438 archive = sphynx_dir + os.sep + 'vpn' + os.sep + str(id_amon) + '.tar.gz' 439 file_conf=open(archive) 440 content=base64.encodestring(file_conf.read()) 441 file_conf.close() 442 except: 443 return 0, u("fichier de configuration vpn non trouvé") 444 query = """update conf_vpn set etat=1 where id_sphynx=%s and id_amon=%s""" % (id_sphynx,id_amon) 445 return self.dbpool.runOperation(query).addCallbacks(lambda x : [1,content],db_client_failed)
446
447 - def xmlrpc_sphynx_list(self,cred_user,id_sphynx):
448 """liste les configs vpn amon présentes pour un sphynx""" 449 cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD) 450 cursor=cx.cursor() 451 query = """select id_amon,etat from conf_vpn where id_sphynx=%s order by etat,id_amon desc""" % id_sphynx 452 cursor.execute(query) 453 data=cursor.fetchall() 454 cursor.close() 455 cx.close() 456 # on retourne l'id amon et son état 457 liste_amons=[] 458 for ligne in data: 459 liste_amons.append([int(ligne[0]),int(ligne[1])]) 460 return 1,liste_amons
461
462 - def xmlrpc_confirm_transfer(self,cred_user,id_serveur,archive):
463 """confirme la réception d'une archive par un serveur""" 464 try: 465 id_serveur = int(id_serveur) 466 serv = self.parent.s_pool.get(cred_user,id_serveur) 467 except KeyError, ValueError: 468 return 0,u("serveur inconnnu dans la base zephir") 469 # définition du répertoire du serveur 470 serveur_dir = serv.get_confdir() 471 try: 472 # suppression de l'archive 473 os.unlink(serveur_dir+os.sep+archive+'.tar') 474 # supression du fichier de checksum 475 os.unlink(serveur_dir+os.sep+archive+'.md5') 476 except: 477 return 0, u("""erreur de suppression de l'archive""") 478 else: 479 return 1, u('ok')
480
481 - def xmlrpc_get_checksum(self,cred_user,id_serveur,archive):
482 """confirme la réception d'une archive par un serveur""" 483 try: 484 id_serveur = int(id_serveur) 485 serv = self.parent.s_pool.get(cred_user,id_serveur) 486 except KeyError, ValueError: 487 return 0,u("serveur inconnnu dans la base zephir") 488 # définition du répertoire du serveur 489 serveur_dir = serv.get_confdir() 490 # lecture du fichier md5 491 try: 492 fic_md5=open(serveur_dir+os.sep+archive+'.md5') 493 md5sum = fic_md5.readlines() 494 fic_md5.close() 495 except: 496 return 0, u("""fichier %s.md5 non trouve""" % (archive)) 497 else: 498 # ok, on renvoie la chaine de contrôle 499 return 1, base64.encodestring(md5sum[0])
500
501 - def xmlrpc_install_module(self,cred_user,id_module,dico_b64):
502 """installation d'un module (récupération d'un dictionnaire)""" 503 # pour l'instant, cette procédure sert à créer ou 504 # mettre à jour le dictionnaire principal du module 505 # on récupère le libellé du module dans la base 506 query = """select id, libelle, version from modules where id=%s""" % id_module 507 return self.dbpool.runQuery(query).addCallbacks(self._install_module,db_client_failed,callbackArgs=[dico_b64])
508
509 - def _install_module(self,data,dico_b64):
510 if data == []: 511 return 0,u("""erreur, module non trouvé""") 512 else: 513 id_module = data[0][0] 514 libelle = data[0][1] 515 version = data[0][2] 516 if version == 1: 517 #creole 1 518 dico_path = os.path.abspath(config.ROOT_DIR)+os.sep+'dictionnaires' 519 dico_b64 = {'dico-'+str(libelle):dico_b64} 520 else: 521 #creole 2 522 dico_path = os.path.abspath(config.ROOT_DIR)+os.sep+'dictionnaires'+os.sep+str(libelle) 523 # traitement des dictionnaires définis 524 for dic_name, data in dico_b64.items(): 525 dico = os.path.join(dico_path, dic_name) 526 try: 527 if os.path.isfile(dico): 528 # le dictionnaire existe déjà 529 os.unlink(dico) 530 # recréation du fichier avec les données transmises 531 fic_dico = open(dico,'w') 532 fic_dico.write(base64.decodestring(data)) 533 fic_dico.close() 534 except: 535 return 0,u("erreur de mise a jour du dictionnaire du module") 536 537 return 1,u("ok")
538 539
540 - def xmlrpc_save_files(self,cred_user,id_serveur,checksum):
541 """sauvegarde des fichiers de configuration d'un serveur""" 542 try: 543 id_serveur = int(id_serveur) 544 serv = self.parent.s_pool.get(cred_user, id_serveur) 545 except KeyError, ValueError: 546 return 0,u("serveur inconnnu dans la base zephir") 547 module = serv.id_mod 548 variante = serv.id_var 549 archive='fichiers_zephir'+str(id_serveur) 550 public_dir = '/var/spool/uucppublic' 551 temp_dir = public_dir+os.sep+str(id_serveur) 552 # création d'un répertoire temporaire pour éviter que tout le monde 553 # écrive dans le même répertoire 554 if os.path.isdir(temp_dir): 555 shutil.rmtree(temp_dir) 556 try: 557 os.mkdir(temp_dir) 558 except: 559 return 0,u("""erreur de creation du repertoire temporaire""") 560 serveur_dir = serv.get_confdir() 561 # on vérifie la validité de l'archive 562 try: 563 fic_md5 = open(public_dir+os.sep+archive+'.md5','w') 564 fic_md5.write(checksum) 565 fic_md5.close() 566 except: 567 return 0, u("""erreur d'écriture du fichier de checksum""") 568 cmd_md5 = """cd %s ; md5sum -c %s.md5 2>&1 > /dev/null""" % (public_dir,archive) 569 res=os.system(cmd_md5) 570 if res != 0: 571 return 0,u("""archive corrompue""") 572 else: 573 # l'archive est valide, on la décompresse 574 cmd_tar = """cd %s ; tar -C %s --same-owner -xhpf %s.tar >/dev/null 2>&1""" % (public_dir,str(id_serveur),archive) 575 os.system(cmd_tar) 576 # on met ensuite les fichiers en place 577 # supression des anciens fichiers ? 578 directories = ['dicos','fichiers_perso','patchs','fichiers_zephir'] 579 for rep in directories: 580 try: 581 if rep == 'dicos' and os.path.isdir(os.path.join(os.path.abspath(config.PATH_MODULES),str(module),'dicos')): 582 # creole2 : on conserve module et variante 583 shutil.rmtree(serveur_dir+os.sep+rep+'/local') 584 else: 585 shutil.rmtree(serveur_dir+os.sep+rep) 586 except: 587 # le repertoire (ou fichier) n'existe pas encore 588 pass 589 # on déplace les fichiers de l'archive 590 res = 0 591 for rep in directories: 592 if res == 0: 593 if os.path.isdir(os.path.join(os.path.abspath(config.PATH_MODULES),str(module),'dicos')) and rep == 'dicos': 594 # cas d'eole2 : répertoire de dictionnaires locaux 595 res = os.system("mv -f %s %s" % (temp_dir+'/temp_zephir/'+rep+'/local', os.path.join(serveur_dir,rep))) 596 else: 597 res = os.system("mv -f %s %s" % (temp_dir+'/temp_zephir/'+rep,serveur_dir)) 598 if res == 0: 599 res = os.system('ln -s '+os.path.abspath(config.PATH_MODULES)+os.sep+str(module)+'/variantes/'+str(variante)+os.sep+rep+' '+serveur_dir+os.sep+rep+os.sep+'variante') 600 601 if res != 0: 602 return 0, u("""erreur de mise en place des fichiers""") 603 604 # mise en place de zephir.eol 605 res = os.system("mv -f %s %s" % (temp_dir+'/temp_zephir/zephir.eol',serveur_dir)) 606 if res != 0: 607 return 0, u("""erreur de mise en place de zephir.eol""") 608 else: 609 # mise à jour de l'état du serveur 610 serv.maj_params({'config_ok':1}) 611 612 # vérification des md5 de la configuration 613 serv.check_md5conf() 614 # vidage du répertoire public 615 try: 616 # on supprime les fichiers temporaires 617 os.unlink(public_dir+os.sep+archive+'.tar') 618 os.unlink(public_dir+os.sep+archive+'.md5') 619 shutil.rmtree(temp_dir) 620 except: 621 return 0, u("""erreur de supression des fichiers temporaires""") 622 return 1, u('ok')
623 624
625 - def xmlrpc_install_variante(self,cred_user,id_serveur,checksum,login,passwd_md5):
626 """installation d'une variante pour un module""" 627 try: 628 id_serveur = int(id_serveur) 629 serv = self.parent.s_pool.get(cred_user, id_serveur) 630 except KeyError, ValueError: 631 return 0,u("serveur inconnnu dans la base zephir") 632 module = serv.id_mod 633 variante = serv.id_var 634 query="""select id,module,owner,passmd5 from variantes where id = %s and module = %s""" % (variante,module) 635 return self.dbpool.runQuery(query).addCallbacks(self._install_variante2,db_client_failed,callbackArgs=[cred_user,checksum,login,passwd_md5,serv.get_rne(),id_serveur])
636 637
638 - def _install_variante2(self,data,cred_user,checksum,login,passwd_md5,rne,id_serveur):
639 """vérification de l'archive et stockage des fichiers""" 640 if data == []: 641 return 0, u("""variante non retrouvée dans la base""") 642 variante = data[0][0] 643 module = data[0][1] 644 owner_var = data[0][2] 645 passwd_var= data[0][3] 646 archive='variante'+str(id_serveur) 647 public_dir = '/var/spool/uucppublic' 648 temp_dir = public_dir+os.sep+str(id_serveur) 649 variante_dir = os.path.abspath(config.PATH_ZEPHIR)+os.sep+'modules'+os.sep+str(module)+os.sep+'variantes'+os.sep+str(variante) 650 # si le mot de passe de la variante n'existe pas (première installation), on le stocke dans la base 651 # si on est propriétaire de la variante : ok 652 if cred_user != owner_var: 653 # si pas de mot de passe : ok 654 if passwd_var not in [None,'']: 655 # sinon on vérifie le mot de passe 656 if passwd_md5 != passwd_var: 657 return 0,u("""erreur, le mot de passe est invalide""") 658 659 # création d'un répertoire temporaire pour éviter que tout le monde 660 # écrive dans le même répertoire 661 if os.path.isdir(temp_dir): 662 shutil.rmtree(temp_dir) 663 try: 664 os.mkdir(temp_dir) 665 except: 666 return 0,u("""erreur de création du repertoire temporaire""") 667 # on vérifie la validité de l'archive 668 try: 669 fic_md5 = open(public_dir+os.sep+archive+'.md5','w') 670 fic_md5.write(checksum) 671 fic_md5.close() 672 except: 673 return 0, u("""erreur d'écriture du fichier de checksum""") 674 cmd_md5 = """cd %s ; md5sum -c %s.md5 2>&1 > /dev/null""" % (public_dir,archive) 675 res=os.system(cmd_md5) 676 if res != 0: 677 return 0,u("""archive corrompue""") 678 else: 679 # l'archive est valide, on la décompresse 680 cmd_tar = """cd %s ; tar -C %s --same-owner -xhpf %s.tar > /dev/null""" % (public_dir,str(id_serveur),archive) 681 os.system(cmd_tar) 682 # on met ensuite les fichiers en place 683 # supression des anciens patchs et dictionnaires locaux 684 try: 685 shutil.rmtree(variante_dir+os.sep+'dicos') 686 shutil.rmtree(variante_dir+os.sep+'patchs') 687 shutil.rmtree(variante_dir+os.sep+'fichiers_perso') 688 shutil.rmtree(variante_dir+os.sep+'fichiers_zephir') 689 except: 690 return 0, u("""erreur de supression de l'ancienne variante""") 691 # on déplace les fichiers de l'archive 692 res = os.system("mv %s %s" % (temp_dir+os.sep+'patch/variante',variante_dir+os.sep+'patchs')) 693 if res == 0: 694 res = os.system("mv %s %s" % (temp_dir+os.sep+'dicos/variante',variante_dir+os.sep+'dicos')) 695 if res == 0: 696 res = os.system("mv %s %s" % (temp_dir+os.sep+'fichiers_perso',variante_dir+os.sep+'fichiers_perso')) 697 if res == 0: 698 res = os.system("mv %s %s" % (temp_dir+os.sep+'fichiers_zephir',variante_dir+os.sep+'fichiers_zephir')) 699 if res != 0: 700 return 0, u("""erreur de mise en place de la variante""") 701 # vidage du répertoire public 702 try: 703 # on supprime les fichiers temporaires 704 os.unlink(public_dir+os.sep+archive+'.tar') 705 os.unlink(public_dir+os.sep+archive+'.md5') 706 shutil.rmtree(temp_dir) 707 except: 708 return 0, u("""erreur de supression des fichiers temporaires""") 709 710 if passwd_var in [None,'']: 711 # stockage des informations d'authentification 712 query = """update variantes set owner ='%s', passmd5='%s' where id = %s and module = %s""" % (login,passwd_md5,variante,module) 713 return self.dbpool.runOperation(query).addCallbacks(lambda x : [1,'ok'],lambda x : [0,'erreur de stockage du mot de passe']) 714 else: 715 return 1,u('ok')
716
717 - def xmlrpc_log_serveur(self,cred_user,id_serveur,date,type_action,etat,msg):
718 """ met à jour la table d'état du serveur pour une action précise 719 (ex: MAJ ou CONFIG) afin de refléter l'état de cohérence actuelle du serveur 720 """ 721 params = {'last_log':str(date)} 722 if type_action in ['MAJ','CONFIGURE','RECONFIGURE','SAUVEGARDE','REBOOT','SERVICE_RESTART']: 723 # on met à jour le champs params du serveur pour refléter un éventuel changement d'état 724 if int(etat) == -1: 725 params['%s_ok' % type_action.lower()] = [2, str(date), msg] 726 elif int(etat) > 0: 727 params['%s_ok' % type_action.lower()] = [0, str(date), msg] 728 elif int(etat) == 0: 729 if type_action == "MAJ": 730 # cas spécial, maj lancée : on force query_maj à 0 (plus de paquets non à jour) 731 params['query_maj'] = [0, str(date)] 732 elif type_action == "CONFIGURE": 733 # cas de la fin d'envoi de configuration 734 # on estime que les données de configuration sont synchronisées (md5) 735 # si ce n'est pas le cas, la non concordance sera détectée au prochain envoi de stats 736 md5file = os.path.join(os.path.abspath(config.PATH_ZEPHIR),'data','config%s.md5' % id_serveur) 737 if os.path.isfile(md5file): 738 self.parent.s_pool.edit_serveur(id_serveur,{'md5s':1}) 739 params['md5s'] = [1,""] 740 params['%s_ok' % type_action.lower()] = [1, str(date), msg] 741 elif type_action == 'LOCK': 742 if int(etat) == 1: 743 params['lock_ok'] = [2, str(date), msg] 744 else: 745 params['lock_ok'] = [1,''] 746 elif type_action == 'QUERY-MAJ': 747 if int(etat) == 0: 748 if 'paquets' in msg: 749 try: 750 nb_paquets = int(msg.split()[0]) 751 params['query_maj'] = [nb_paquets,str(date)] 752 except: 753 params['query_maj'] = [-2,'erreur de lecture du résultat'] 754 else: 755 params['query_maj'] = [0, str(date)] 756 elif int(etat) > 0: 757 params['query_maj'] = [-1, str(msg)] 758 try: 759 id_serveur = int(id_serveur) 760 serv = self.parent.s_pool[id_serveur] 761 except KeyError, ValueError: 762 return 0,u("serveur inconnnu dans la base zephir") 763 else: 764 # on met à jour la date de dernier contact dans la base 765 self.parent.s_pool.update_contact(id_serveur) 766 767 # on regarde si l'action en question a déjà un état 768 query = """select id,etat,date,type from last_log_serveur where id_serveur=%s and type='%s'""" %(id_serveur,type_action.replace("'","\\\'")) 769 return self.dbpool.runQuery(query).addCallbacks(self._log_serveur,db_client_failed,callbackArgs=[id_serveur,type_action,date,int(etat),msg, params, serv])
770
771 - def _log_serveur(self,data,id_serveur,type_action,date,etat,msg,params,serv):
772 # si l'action existe déjà on la met à jour, sinon on l'insère 773 if data != []: 774 # on insère que si la date du nouveau log est > à l'ancien (cas d'anciens logs non remontés) 775 last_date = data[0][2] 776 new_date = datetime.strptime(str(date), "%c") 777 if new_date >= last_date: 778 query = """update last_log_serveur set id_serveur=%s,date='%s',type='%s',message='%s',etat=%s where id=%s""" % \ 779 (int(id_serveur),date,type_action.replace("'","\\\'"),msg.replace("'","\\\'"),etat,data[0][0]) 780 # on met à jour le champs params et le cache mémoire 781 if params.has_key('query_maj'): 782 self.parent.s_pool.edit_serveur(id_serveur,{'maj':params['query_maj'][0]}) 783 serv.maj_params(params) 784 else: 785 # on a reçu un ancien log (reprise d'anciens logs ayant échoué) -> pas de maj de last_log 786 return self._log_serveur2(None,id_serveur,type_action,date,etat,msg) 787 else: 788 query = """insert into last_log_serveur (id_serveur,date,type,message,etat) values (%s,'%s','%s','%s',%s)""" % (int(id_serveur),date,type_action.replace("'","\\\'"),msg.replace("'","\\\'"),etat) 789 return self.dbpool.runOperation(query).addCallbacks(self._log_serveur2,db_client_failed,callbackArgs=[id_serveur,type_action,date,etat,msg])
790
791 - def _log_serveur2(self,data,id_serveur,type_action,date,etat,msg):
792 query = """insert into log_serveur (id_serveur,date,type,message,etat) values (%s,'%s','%s','%s',%s)""" % (int(id_serveur),date,type_action.replace("'","\\\'"),msg.replace("'","\\\'"),etat) 793 # on effectue la mise à jour de la base 794 return self.dbpool.runOperation(query).addCallbacks(lambda x : [1,'ok'],db_client_failed)
795
796 - def xmlrpc_release_lock_groupe(self,cred_user,liste):
797 """prépare la suppression des verrous sur un groupe""" 798 erreurs=[] 799 for serveur in liste: 800 retour = self.xmlrpc_release_lock(cred_user, serveur['id']) 801 if retour[0] == 0: 802 erreurs.append(str(serveur['id'])+' : '+retour[1]) 803 if erreurs != []: 804 return 0,u(erreurs) 805 else: 806 return 1, u('ok')
807
808 - def xmlrpc_release_lock(self,cred_user,id_serveur):
809 """demande la libération des verrous sur un serveur""" 810 try: 811 id_serveur = int(id_serveur) 812 serv = self.parent.s_pool.get(cred_user,id_serveur) 813 except KeyError, ValueError: 814 return 0,u("serveur inconnnu dans la base zephir") 815 else: 816 serv.maj_params({'del_locks':True}) 817 return 1, 'ok'
818
819 - def xmlrpc_unlock(self,cred_user,id_serveur,unlocked=False):
820 """indique si les locks doivent être ignorés 821 @params unlocked: si True, on enlève l'attibut del_lock de params""" 822 try: 823 id_serveur = int(id_serveur) 824 serv = self.parent.s_pool.get(cred_user,id_serveur) 825 except KeyError, ValueError: 826 return 0,u("serveur inconnnu dans la base zephir") 827 params = serv.get_params() 828 if params.has_key('del_locks'): 829 if params['del_locks'] == True: 830 if unlocked: 831 # les verrous ont été supprimés, on revient en état normal 832 serv.maj_params({'del_locks':False}) 833 # les verrous doivent être bypassés 834 return 1, True 835 return 1, False
836
837 - def _sendmail(self,adresses,subject,msg):
838 """envoi d'un message d'alerte à une liste d'adresses mail 839 """ 840 bad_addr={} 841 mail_content = "Subject: [Zephir] %s\n\n%s" % (subject,msg) 842 mail_client=smtplib.SMTP() 843 try: 844 smtplib.socket.setdefaulttimeout(3) 845 if config.MAIL_PORT != '': 846 mail_client.connect(config.MAIL_ADRESSE,config.MAIL_PORT) 847 else: 848 mail_client.connect(config.MAIL_ADRESSE) 849 except: 850 return 0, u('erreur de connexion au serveur smtp') 851 else: 852 try: 853 bad_addr = mail_client.sendmail(config.MAIL_ACCOUNT,adresses,mail_content) 854 except: 855 return 0, u("erreur d'envoi du mail d'alerte") 856 return 1, bad_addr
857 858
859 - def xmlrpc_maj_site(self,cred_user,id_serveur,checksum,new_agents=0):
860 """vérifie l'archive envoyée par le serveur et met le site et les données xml en place 861 """ 862 log.msg ("connexion du serveur %s" % str(id_serveur)) 863 # on regarde dans les logs si un lock est indiqué 864 cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD) 865 query="""select type,etat from last_log_serveur where id_serveur=%s and type='LOCK' order by date desc,id desc""" % id_serveur 866 cursor=cx.cursor() 867 cursor.execute(query) 868 data=cursor.fetchall() 869 cursor.close() 870 cx.close() 871 etat=0 872 if data != []: 873 etat=int(data[0][1]) 874 if etat == 1: 875 # si il y avait un lock sur uucp, on l'annule 876 self.xmlrpc_log_serveur(cred_user,id_serveur,str(time.ctime()),'LOCK','0',"""Reprise de l'activité uucp""") 877 # on met à jour la date de dernier contact dans la base 878 self.parent.s_pool.update_contact(id_serveur) 879 # vérification du md5 de l'archive 880 public_dir = '/var/spool/uucppublic' 881 archive = 'site%s' % id_serveur 882 try: 883 fic_md5 = open(public_dir+os.sep+archive+'.md5','w') 884 fic_md5.writelines(checksum) 885 fic_md5.close() 886 except: 887 return 0, u("""erreur d'écriture du fichier de checksum""") 888 cmd_md5 = """cd %s ; md5sum -c %s.md5 2>&1 > /dev/null""" % (public_dir, archive) 889 res=os.system(cmd_md5) 890 if res != 0: 891 return 0,u("""archive corrompue""") 892 else: 893 compressed='' 894 # l'archive est valide, on la décompresse 895 if int(new_agents) == 1: 896 # l'archive est zippée avec les nouveaux agents 897 compressed = 'z' 898 rep_dest = os.path.abspath(config.PATH_ZEPHIR) 899 # on supprime l'ancien répertoire 900 try: 901 shutil.rmtree(rep_dest+os.sep+"data"+os.sep+str(id_serveur)) 902 except: 903 pass 904 else: 905 rep_dest = os.path.abspath(config.PATH_ZEPHIR)+os.sep+"sites"+os.sep+str(id_serveur) 906 # on supprime l'ancien répertoire 907 if os.path.exists(rep_dest): 908 shutil.rmtree(rep_dest) 909 os.makedirs(rep_dest) 910 911 cmd_tar = """cd %s ; /bin/tar -C %s -x%sf %s.tar 2> /dev/null""" % (public_dir, rep_dest, compressed, archive) 912 res=os.system(cmd_tar) 913 if res != 0: 914 return 0,u("erreur de mise en place du site sur zephir") 915 serv = self.parent.s_pool[int(id_serveur)] 916 serv.check_md5conf() 917 # si serveur eole 1, on convertit le xml en utf-8 918 if serv.version == 'creole1': 919 f_site = file(os.path.join(rep_dest,'data',str(id_serveur),'site.cfg')) 920 data = f_site.read() 921 f_site.close() 922 try: 923 data = unicode(data,'ISO-8859-1').encode(config.charset) 924 except: 925 pass 926 else: 927 f_site = file(os.path.join(rep_dest,'data',str(id_serveur),'site.cfg'),'w') 928 f_site.write(data) 929 f_site.close() 930 for xml_file in glob.glob(os.path.join(rep_dest,'data',str(id_serveur),'*/agent.xml')): 931 try: 932 xml = file(xml_file).read() 933 # conversion du contenu 934 for ori, dst in config.xml_table.items(): 935 xml = xml.replace(ori,dst) 936 file(xml_file,'w').write(xml) 937 except: 938 print "erreur lors de la conversion de %s en %s" % (xml_file, config.charset) 939 940 # on met à jour la liste d'agents (en cas de nouvel agent) 941 # et on regarde si un des agents a remonté une erreur 942 try: 943 if self.agent_manager.has_key(str(id_serveur)): 944 # nouvelle API des agents 945 # on force un update du cache pour ce serveur (prise en compte de nouveaux agents sans redémarrer l'application) 946 self.agent_manager[str(id_serveur)].update_structure() 947 stats = self.agent_manager[str(id_serveur)].get_measure() 948 result_ag = self.agent_manager[str(id_serveur)].global_status() 949 else: 950 # anciens agents 951 # mise à jour des données depuis les xml remontés 952 AgentCollecteur(id_serveur) 953 result_ag = ServeurStatus(id_serveur).get_status() 954 except: 955 traceback.print_exc() 956 result_ag = 1 957 958 # on vérifie la cohérence du serveur au niveau des logs zephir 959 try: 960 result_zeph = self.parent.getSubHandler('serveurs').xmlrpc_get_status(cred_user,id_serveur) 961 except: 962 return 0, u("erreur de récupération de l'état zephir du serveur %s" % id_serveur) 963 964 d = defer.Deferred() 965 d.addCallback(self._alerte,result_zeph[1],result_ag) 966 d.callback(id_serveur) 967 968 return 1,u("ok")
969 970
971 - def _alerte(self,id_serveur,etat_zeph,etat_ag):
972 """vérification de l'état du serveur et envoi mail si nécessaire 973 """ 974 # on récupére la liste des utilisateurs à contacter 975 query="select serveurs.id,serveurs.rne,installateur,serveurs.libelle,modules.libelle,etablissements.libelle,serveurs.etat,serveurs.params \ 976 from serveurs,etablissements,modules \ 977 where serveurs.id=%s and etablissements.rne=serveurs.rne and modules.id=module_actuel" % id_serveur 978 self.dbpool.runQuery(query).addCallbacks(self._alerte2,db_client_failed,callbackArgs=[etat_zeph,etat_ag])
979
980 - def _alerte2(self,data,etat_zeph,etat_ag):
981 # si erreur zephir ou agent --> mail 982 if data == []: 983 # pas de données récupérées (serveur inexistant ?) 984 pass 985 else: 986 id_serveur = data[0][0] 987 rne = data[0][1] 988 libelle = data[0][3] 989 module = data[0][4] 990 libel_etab = data[0][5] 991 etat_precedent = data[0][6] 992 if etat_precedent != None: 993 try: 994 etat_precedent = int(etat_precedent) 995 except Exception, e: 996 etat_precedent = 1 997 erreur = 0 998 msg = """le serveur %s (%s - %s)\n établissement : %s (%s)""" % (libelle, id_serveur, module, rne, libel_etab) 999 # vérification de l'état du serveur 1000 for cle in etat_zeph.keys(): 1001 etat = etat_zeph[cle] 1002 if type(etat) == list: 1003 if len(etat) == 3: 1004 if etat[0] == 0: 1005 if erreur == 0: 1006 msg += """\n(se reporter à la page d'état du serveur dans l'application web)""" 1007 erreur = 1 1008 msg +="""\n\nlog du %s : %s""" % (etat[1].encode(config.charset),etat[2].encode(config.charset)) 1009 if (cle == 'lock_ok') and (etat[0] != 1): 1010 msg += """\n\n Fonction Zephir verouillées, connectez vous sur le serveur pour vérifier son état 1011 (commande '/usr/share/zephir/scripts/zephir_client del_lock' pour dévérouiller)""" 1012 1013 # on stocke l'etat global des agents dans le champs params du serveur 1014 serv = self.parent.s_pool[id_serveur] 1015 try: 1016 params=eval(data[0][7]) 1017 assert type(params) == dict 1018 params['agents'] = etat_ag 1019 except: 1020 # pas encore de données dans params 1021 params={'agents':etat_ag} 1022 serv.maj_params(params) 1023 1024 if etat_ag == 0: 1025 erreur = 2 1026 # erreur remontée dans le site de surveillance 1027 msg+="""\n\nerreur remontée par le serveur (cf. https://%s:%s/agents/%s)""" % (config.ADRESSE_ZEPHIR,config.PORT_HTTP,id_serveur) 1028 # envoi de message si erreur non envoyée précédemment 1029 # on regarde le dernier état enregistré pour ce serveur 1030 if erreur != 0: 1031 if etat_precedent not in [0,4]: 1032 if etat_precedent == 3: 1033 serv.set_status(4) 1034 else: 1035 serv.set_status(0) 1036 # début d'alerte 1037 if etat_precedent == 2: 1038 # on vient de reprendre contact et il y a un problème 1039 subject = "problème détecté à la reprise de contact: serveur %s (%s)" % (libelle,rne) 1040 else: 1041 subject = "problème détecté : serveur %s (%s)" % (libelle,rne) 1042 msg = "\nproblème détecté sur " + msg 1043 self._send_alerte("problème détecté : serveur ",{int(id_serveur):msg}) 1044 else: 1045 # pas d'erreur détectée, si l'état était à 2, on ne le change pas 1046 # (l'état sera remis à 1 par la fonction de vérification du timeout) 1047 if etat_precedent in [0,4]: 1048 if etat_precedent == 4: 1049 serv.set_status(3) 1050 else: 1051 serv.set_status(1) 1052 # fin d'alerte 1053 subject = "fin d'alerte : serveur %s (%s)" % (libelle,rne) 1054 msg = "\n fin d'alerte pour " + msg 1055 self._send_alerte("fin d'alerte : ",{int(id_serveur):msg}) 1056 # si on n'avait pas d'info : etat ok 1057 if etat_precedent == None: 1058 serv.set_status(1)
1059
1060 - def _send_alerte(self,subject,msgs):
1061 """recherche les mails et sms des personnes surveillant un serveur particulier 1062 """ 1063 if msgs != {}: 1064 query = """select id,serveurs from groupes_serveurs""" 1065 self.dbpool.runQuery(query).addCallbacks(self._send_alerte2,db_client_failed,callbackArgs=[subject,msgs])
1066
1067 - def _send_alerte2(self,data,subject,msg):
1068 # on récupère les groupes 1069 # et on regarde quels groupes contiennent ce serveur 1070 groupes=[] 1071 for id_serveur in msg.keys(): 1072 for groupe in data: 1073 if id_serveur in eval(groupe[1]): 1074 if groupe[0] not in groupes: 1075 groupes.append(groupe[0]) 1076 query = """select groupes,mail,sms,mail_actif,sms_actif from users \ 1077 where groupes != '' and (mail_actif=1 or sms_actif=1)""" 1078 self.dbpool.runQuery(query).addCallbacks(self._send_alerte3,db_client_failed,callbackArgs=[groupes,subject,msg])
1079
1080 - def _send_alerte3(self,data,groupes,subject,msg):
1081 """regarde quels utilisateurs surveillent les groupes 1082 en question et envoie un mail ou sms si besoin 1083 """ 1084 # utilisateurs avec les bons groupes 1085 destinataires = [] 1086 for user in data: 1087 try: 1088 groupes_user=eval(user[0]) 1089 except: 1090 groupes_user=[] 1091 for groupe in groupes_user: 1092 # un des groupes contient ce serveur 1093 if groupe in groupes: 1094 # on regarde si il faut envoyer des mails ou sms 1095 if user[3]==1: 1096 # on vérifie la syntaxe de l'adresse mail 1097 for adresse in user[1].split(','): 1098 r=re.match("""^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9]+)*$""",adresse) 1099 if r is not None: 1100 # adresse valide : on envoie le mail 1101 if adresse not in destinataires: 1102 destinataires.append(adresse) 1103 # envoi effectif des messages à tous les utilisateurs concernés 1104 if destinataires != []: 1105 self._sendmail(destinataires,subject + str(msg.keys()),"\n".join(msg.values()))
1106
1107 - def xmlrpc_scan_timeouts(self,*args):
1108 """vérifie toutes les x minutes si des serveurs ont dépassé leur timeout. 1109 vérification toutes les 5 miuntes par défaut""" 1110 # requete de récupération des données 1111 try: 1112 # premier démarrage de la boucle de vérification des contacts 1113 if self.start_time is not None: 1114 query = "update serveurs set last_contact = '%s' where last_contact is not null and etat <> 2" % self.start_time 1115 self.dbpool.runOperation(query).addCallbacks(lambda x : [1, "OK"],db_client_failed) 1116 reactor.callLater(5, self._scan_timeouts) 1117 self.start_time = None 1118 except: 1119 return 0, "erreur de démarrage de la boucle de surveillance" 1120 return 1,""
1121
1122 - def _scan_timeouts(self):
1123 reactor.callLater(self.scan_delay,self._scan_timeouts) 1124 query = """select serveurs.id,timeout,last_contact,serveurs.libelle, \ 1125 serveurs.rne,etablissements.libelle,modules.libelle,serveurs.etat \ 1126 from serveurs,etablissements,modules where timeout > 0 and last_contact is not null and \ 1127 serveurs.rne=etablissements.rne and module_actuel=modules.id""" 1128 self.dbpool.runQuery(query).addCallbacks(self._scan_timeouts2,db_client_failed)
1129
1130 - def _scan_timeouts2(self,data):
1131 """vérifie si le dernier contact est moins ancien que le timeout du serveur. 1132 """ 1133 erreurs={} 1134 reprises={} 1135 bloquages={} 1136 debloquages={} 1137 cmds=uucp_pool._scan_pool() 1138 for serveur in data: 1139 # calcul du temps écoulé depuis le dernier contact (en secondes) 1140 serv = self.parent.s_pool[int(serveur[0])] 1141 params = {'timeout':[-2, ""]} 1142 last = float(serveur[2]) 1143 delta = float(time.time()) - last 1144 try: 1145 etat_actuel = int(serveur[7]) 1146 except: 1147 etat_actuel = 1 1148 # on regarde si on a dépassé le timeout 1149 try: 1150 timeout = int(serveur[1]) 1151 except: 1152 pass 1153 else: 1154 params['timeout'] = [1, time.ctime(last)] 1155 # on laisse un délai de 2x le délai de connexion + 4 minutes avant de lever une alerte 1156 # (on autorise de rater une connexion) 1157 max_delay = int(timeout) * 2 + 240 1158 if ( delta > max_delay ) and timeout != 0: 1159 params['timeout'][0]=0 1160 if etat_actuel != 2: 1161 # on prévient les utilisateurs concernés si ce n'est pas déjà fait 1162 log.msg("timeout du serveur %s" % serveur[0]) 1163 serv.set_status(2) 1164 # construction du message d'erreur 1165 subject = """perte du contact : serveur(s) %s (%s)""" % (serveur[3],serveur[4]) 1166 msg="""Dernier contact avec le serveur n°%s - %s (%s) de l'établissement %s (%s) : %s""" % (serveur[0],serveur[3],serveur[6],serveur[4],serveur[5],time.ctime(last)) 1167 # ajout de l'alerte 1168 erreurs[serveur[0]]=msg 1169 else: 1170 if etat_actuel == 2: 1171 # on était en timeout auparavant 1172 serv.set_status(1) 1173 subject = """reprise du contact : serveur(s) %s (%s)""" % (serveur[3],serveur[4]) 1174 msg = """reprise du contact avec le serveur n°%s - %s (%s) de l'établissement %s (%s) : %s""" % \ 1175 (serveur[0],serveur[3],serveur[6],serveur[4],serveur[5],time.ctime(last)) 1176 reprises[serveur[0]]=msg 1177 1178 # vérification de la bonne exécution des commandes 1179 id_uucp = serveur[4]+"-"+str(serveur[0]) 1180 old_cmds = uucp_pool.check_timeout(max_delay, id_uucp) 1181 if old_cmds != {}: 1182 if etat_actuel not in [3,4]: 1183 # mail pour le bloquage des commandes en attente 1184 msg = """commandes bloquées en attente pour le serveur n°%s - %s (%s) de l'établissement %s (%s) 1185 Vous pouvez afficher les logs de transfert UUCP sur ce serveur à l'aide de la commande uulog""" 1186 bloquages[serveur[0]] = msg % (serveur[0],serveur[3],serveur[6],serveur[4],serveur[5]) 1187 if etat_actuel == 0: 1188 # bloquage + erreur agents 1189 serv.set_status(4) 1190 else: 1191 # bloquage 1192 serv.set_status(3) 1193 else: 1194 if etat_actuel in [3,4]: 1195 # les commandes sont débloquées 1196 msg = """débloquage des commandes (reprise d'activité uucp) pour le serveur n°%s - %s (%s) de l'établissement %s (%s)""" 1197 debloquages[serveur[0]] = msg % (serveur[0],serveur[3],serveur[6],serveur[4],serveur[5]) 1198 if etat_actuel == 4: 1199 # erreur agents 1200 serv.set_status(0) 1201 else: 1202 # aucune erreur 1203 serv.set_status(1) 1204 1205 # mise à jour du champ params du serveur 1206 serv.maj_params(params) 1207 1208 self._send_alerte("commandes non lancées : ",bloquages) 1209 self._send_alerte("commandes débloquées : ",debloquages) 1210 self._send_alerte("perte de contact : ",erreurs) 1211 self._send_alerte("reprise du contact : ",reprises)
1212
1213 - def xmlrpc_get_actions(self,cred_user,id_serveur):
1214 """retourne la liste des actions uucp en attente""" 1215 # on vérifie l'existence du serveur dans la base 1216 try: 1217 id_serveur = int(id_serveur) 1218 serv = self.parent.s_pool.get(cred_user, id_serveur) 1219 except KeyError, ValueError: 1220 return 0,u("serveur inconnnu dans la base zephir") 1221 else: 1222 id_uucp = str(serv.get_rne()) + '-' + str(id_serveur) 1223 # on commence par mettre à jour le pool uucp 1224 cmds=uucp_pool._scan_pool() 1225 # construction de la commande 1226 try: 1227 cmds=uucp_pool.list_cmd(id_uucp)[id_uucp] 1228 except: 1229 cmds={} 1230 try: 1231 files=uucp_pool.list_files(id_uucp)[id_uucp] 1232 except: 1233 files={} 1234 return 1,u([cmds,files])
1235
1236 - def xmlrpc_check_queue(self,cred_user,id_serveur):
1237 """indique à un serveur si il doit ou non effectuer des actions 1238 """ 1239 # on vérifie l'existence du serveur dans la base 1240 try: 1241 id_serveur = int(id_serveur) 1242 serv = self.parent.s_pool.get(cred_user, id_serveur) 1243 except KeyError, ValueError: 1244 return 0,u("serveur inconnnu dans la base zephir") 1245 else: 1246 id_uucp = str(serv.get_rne()) + '-' + str(id_serveur) 1247 # on commence par mettre à jour le pool uucp 1248 cmds=uucp_pool._scan_pool() 1249 if len(uucp_pool.pool[id_uucp]) > 0: 1250 return 1, True 1251 else: 1252 return 1, False
1253
1254 - def xmlrpc_purge_actions(self,cred_user,serveurs,id_tache=None):
1255 """annule toutes les actions en attente sur un/plusieurs serveur(s)""" 1256 # on vérifie l'existence du serveur dans la base 1257 try: 1258 for id_serveur in serveurs: 1259 id_serveur = int(id_serveur) 1260 assert self.parent.s_pool.has_key(id_serveur) 1261 except KeyError, ValueError: 1262 return 0,u("serveur inconnnu dans la base zephir") 1263 else: 1264 for id_serveur in serveurs: 1265 rne = self.parent.s_pool.get(cred_user,int(id_serveur)).get_rne() 1266 id_uucp = str(rne) + '-' + str(id_serveur) 1267 # on regarde si un transfert est lié à cette action (configure) 1268 if id_tache is None: 1269 try: 1270 uucp_pool.flush([id_uucp]) 1271 except UUCPError, e: 1272 return 0, u("erreur de purge des commandes : %" % str(e)) 1273 else: 1274 try: 1275 if str(uucp_pool.pool[id_uucp][int(id_tache)][1]) == COMMANDS["zephir_client configure"]: 1276 # dans le cas d'un envoi de configuration, on supprime également 1277 # le transfert de fichier correspondant 1278 if str(uucp_pool.pool[id_uucp][int(id_tache)-1][0]) == "transfert": 1279 uucp_pool.remove_cmd(id_uucp,int(id_tache)-1) 1280 uucp_pool.remove_cmd(id_uucp,int(id_tache)) 1281 except UUCPError, e: 1282 return 0,u("Erreur de supression de la commande uucp : %" %str(e)) 1283 except KeyError: 1284 pass 1285 1286 return 1,"OK"
1287