zephir.backend.uucp_rpc

Package zephir :: Package backend :: Module uucp_rpc |
[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, log
      19  from zephir.backend.xmlrpceole import XMLRPCEole as XMLRPC
      20  from zephir.backend.lib_backend import AptChecker
      21  from zephir.monitor.collecteur import AgentCollecteur, ServeurStatus
      22  from zephir.lib_zephir import save_modes
      23  from twisted.internet import defer, reactor, threads
      24
      25  import sys,os,shutil,time,smtplib,re,time,base64,glob,email
      26  from email.header import Header
      27  from datetime import datetime
      28  import traceback
      29  import psycopg2 as PgSQL
      30  from cStringIO import StringIO
      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):
      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.exists(os.path.join(serveur_dir,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""" % os.path.join(serveur_dir,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,os.path.join(serveur_dir,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,delay=0):
      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 inconnu dans la base zephir")
      90          else:
      91              if delay != 0:
      92                  delay_opt = " %s" % str(delay)
      93              else:
      94                  delay_opt = ""
      95              id_uucp = str(serv.get_rne())+'-'+str(id_serveur)
      96              try:
      97                  res = uucp_pool.add_cmd(id_uucp,"zephir_client reconfigure%s" % delay_opt)
      98              except UUCPError,e:
      99                  return 0, u("Erreur UUCP %s" % str(e))
     100          return 1, u('ok')
     101
     102 -    def xmlrpc_service_restart_groupe(self,cred_user,liste,service, delay=0):
     103          """prépare le redémarrage d'un service sur un groupe"""
     104          erreurs=[]
     105          old_clients=[]
     106          for serveur in liste:
     107              new_cli = False
     108              if delay:
     109                  try:
     110                      id_serveur = int(serveur['id'])
     111                      serv = self.parent.s_pool.get(cred_user, id_serveur)
     112                      new_cli = serv.check_min_version(self.parent.maj_checker, 'zephir-client', '2.3-eole54~1')
     113                  except (KeyError, ValueError):
     114                      return 0, u("serveur inconnu dans la base zephir")
     115                  if new_cli:
     116                      # si un délai est demandé on n'applique pas l'action aux serveurs non compatibles
     117                      retour = self.xmlrpc_service_restart(cred_user, serveur['id'], service, delay)
     118                  else:
     119                      retour = (1, "ok")
     120                      old_clients.append(id_serveur)
     121              else:
     122                  retour = self.xmlrpc_service_restart(cred_user, serveur['id'], service, delay)
     123              if retour[0] == 0:
     124                  erreurs.append(str(serveur['id'])+' : '+retour[1])
     125          if erreurs != []:
     126              return 0, u(erreurs)
     127          else:
     128              return 1, u(old_clients)
     129
     130 -    def xmlrpc_service_restart(self,cred_user,id_serveur,service, delay=0):
     131          """exécution de la commande uucp pour redémarrer un service"""
     132          try:
     133              id_serveur = int(id_serveur)
     134              serv = self.parent.s_pool.get(cred_user, id_serveur)
     135          except (KeyError, ValueError):
     136              return 0, u("serveur inconnu dans la base zephir")
     137          else:
     138              if delay != 0:
     139                  delay_opt = " %s" % str(delay)
     140              else:
     141                  delay_opt = ""
     142              id_uucp = str(serv.get_rne()) + '-' + str(id_serveur)
     143              # appel uucp
     144              try:
     145                  uucp_pool.add_cmd(id_uucp,"zephir_client service_restart %s%s" % (service, delay_opt))
     146              except UUCPError,e:
     147                  return 0, u("erreur uucp (%s)" % str(e))
     148              return 1,u("ok")
     149
     150 -    def xmlrpc_reboot_groupe(self,cred_user,liste, delay=0):
     151          """prépare le redémarrage d'un groupe de serveurs"""
     152          erreurs=[]
     153          for serveur in liste:
     154              retour = self.xmlrpc_reboot(cred_user, serveur['id'], delay)
     155              if retour[0] == 0:
     156                  erreurs.append(str(serveur['id'])+' : '+retour[1])
     157          if erreurs != []:
     158              return 0, u(erreurs)
     159          else:
     160              return 1, u('ok')
     161
     162 -    def xmlrpc_reboot(self,cred_user,id_serveur, delay=0):
     163          """exécution de la commande uucp pour redémarrer un serveur"""
     164          try:
     165              id_serveur = int(id_serveur)
     166              serv = self.parent.s_pool.get(cred_user, id_serveur)
     167          except (KeyError, ValueError):
     168              return 0, u("serveur inconnu dans la base zephir")
     169          else:
     170              if delay != 0:
     171                  delay_opt = " %s" % str(delay)
     172              else:
     173                  delay_opt = ""
     174              id_uucp = str(serv.get_rne()) + '-' + str(id_serveur)
     175              # appel uucp
     176              try:
     177                  uucp_pool.add_cmd(id_uucp,"zephir_client reboot%s" % delay_opt)
     178              except UUCPError,e:
     179                  return 0, u("serveur %s : erreur uucp (%s)" % (str(id_serveur), str(e)))
     180              return 1,u("ok")
     181
     182
     183 -    def xmlrpc_configure(self,cred_user,id_serveur,restart=0,content=0):
     184          """prépare la configuration automatique d'un serveur
     185          (envoi des fichiers de configuration)"""
     186
     187          return self._configure(id_serveur, restart, cred_user, content)
     188
     189 -    def xmlrpc_configure_groupe(self,cred_user,liste,restart=0,content=0):
     190          """prépare la configuration automatique d'un groupe de serveurs
     191          (envoi des fichiers de configuration)"""
     192          erreurs = []
     193          old_clients = []
     194          for serveur in liste:
     195              retour = self._configure(serveur['id'], restart, cred_user, content)
     196              if retour[0] == 0:
     197                  erreurs.append(str(serveur['id'])+' : '+retour[1])
     198              else:
     199                  old_clients.extend(retour[1])
     200          if erreurs != []:
     201              return 0, u(erreurs)
     202          else:
     203              return 1, u(old_clients)
     204
     205 -    def _configure(self, id_serveur,restart,cred_user,content):
     206          """envoie les fichiers de configuration et demande un configure-zephir"""
     207          try:
     208              id_serveur = int(id_serveur)
     209              serv = self.parent.s_pool.get(cred_user, id_serveur)
     210          except (KeyError, ValueError):
     211              return 0, u("serveur inconnu dans la base zephir")
     212          query = """select users.cle from users,serveur_auth where users.login=serveur_auth.login and serveur_auth.id_serveur=%s"""
     213          cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD)
     214          cursor=cx.cursor()
     215          cursor.execute(query, (int(id_serveur),))
     216          data=cursor.fetchall()
     217          cursor.close()
     218          cx.close()
     219          id_uucp = str(serv.get_rne())+'-'+str(id_serveur)
     220          # définition du répertoire du serveur
     221          serveur_dir = serv.get_confdir()
     222          # définition des fichiers à transférer
     223          try:
     224              cles = ""
     225              # on prépare le fichier des clefs ssh à transférer
     226              for cle in data:
     227                  if cle[0]:
     228                      cles += base64.decodestring(cle[0]) + "\n"
     229              cles.strip()
     230              fic_cle = open(serveur_dir+os.sep+'auth_keys','w')
     231              fic_cle.writelines(base64.encodestring(cles))
     232              fic_cle.close()
     233          except:
     234              return 0, u("erreur de création du fichier des cles de connexion ssh")
     235          old_clients = []
     236          # si le client présent sur le serveur n'est pas assez récent, on fait une sauvegarde complète
     237          files = ['dicos','patchs','fichiers_perso','fichiers_zephir','zephir.eol','dico.eol','auth_keys','droits_zephir', 'droits_variante']
     238          if serv.version != 'creole1' and serv.check_min_version(self.parent.maj_checker, 'zephir-client', '2.2-eole97'):
     239              # envoi partiel
     240              if content not in config.data_files:
     241                  return 0, u("le type de données à envoyer est invalide")
     242              files = config.data_files[content][1]
     243          else:
     244              # client trop ancien : envoi de toutes les données
     245              old_clients = [id_serveur]
     246          if 'fichiers_zephir' in files:
     247              if self.parent.dictpool.check_module(serv.id_mod):
     248                  # synchronisation des paquets de dictionnaires avant envoi
     249                  self.parent.dictpool.sync_serveur_packages(serv.id_s)
     250          # appel de la fonction d'envoi et de calcul des md5
     251          code, message = self._send_files(serv,'config-zephir',files,uucp=1)
     252          try:
     253              os.unlink('auth_keys')
     254          except:
     255              pass
     256          if code == 0:
     257              return code, u(message)
     258          else:
     259              # les fichiers sont prêts à l'envoi, on demande un
     260              # configure sur le serveur distant
     261              try:
     262                  res = uucp_pool.add_cmd(id_uucp,"zephir_client configure")
     263              except UUCPError, e:
     264                  return 0, u("Erreur uucp : %s" % str(e))
     265              if restart == 1:
     266                  # on demande un reconfigure
     267                  code, data = self.xmlrpc_reconfigure(cred_user, id_serveur)
     268                  if code == 1:
     269                      return 1, u(old_clients)
     270                  else:
     271                      return code, data
     272              else:
     273                  return 1, u(old_clients)
     274
     275 -    def xmlrpc_save_conf(self,cred_user,id_serveur,mode=0):
     276          """prépare la sauvegarde de configuration d'un serveur"""
     277          # on vérifie l'existence du serveur dans la base
     278          return self._save_conf(cred_user, id_serveur, mode)
     279
     280 -    def xmlrpc_save_conf_groupe(self,cred_user,liste,mode=0):
     281          """prépare la sauvegarde de configuration d'un serveur"""
     282          erreurs=[]
     283          old_clients = []
     284          for serveur in liste:
     285              retour = self._save_conf(cred_user, serveur['id'], mode)
     286              if retour[0] == 0:
     287                  erreurs.append(str(serveur['id'])+' : '+retour[1])
     288              else:
     289                  old_clients.extend(retour[1])
     290          if erreurs != []:
     291              return 0, u(erreurs)
     292          else:
     293              return 1, u(old_clients)
     294
     295 -    def _save_conf(self,cred_user,id_serveur,mode):
     296          """exécution de la commande uucp pour la mise à jour"""
     297          try:
     298              id_serveur = int(id_serveur)
     299              serv = self.parent.s_pool.get(cred_user, id_serveur)
     300          except (KeyError, ValueError):
     301              return 0, u("serveur inconnu dans la base zephir")
     302          else:
     303              old_clients = []
     304              id_uucp = str(serv.get_rne()) + '-' + str(id_serveur)
     305              # appel uucp
     306              # vérification du mode demandé
     307              cmd_mode = ""
     308              if serv.version != 'creole1' and mode in save_modes:
     309                  # pour éviter les problèmes avec d'anciens clients, on ne passe pas
     310                  # le mode si le client n'est pas assez récent
     311                  if serv.check_min_version(self.parent.maj_checker, 'zephir-client', '2.2-eole97'):
     312                      cmd_mode = " %s" % str(mode)
     313                  else:
     314                      old_clients.append(id_serveur)
     315              try:
     316                  uucp_pool.add_cmd(id_uucp,"zephir_client save_files%s" % cmd_mode)
     317              except UUCPError,e:
     318                  return 0, u("erreur uucp (%s)" % str(e))
     319              return 1, (old_clients)
     320
     321 -    def xmlrpc_maj(self,cred_user,id_serveur,reconf = 0, delay = "", options = ""):
     322          """prépare la mise à jour d'un serveur Eole par l'intermédiare d'uucp"""
     323          # on vérifie l'existence du serveur dans la base
     324          if delay > 0:
     325              # mise à jour différée : reconfigure est géré par la mise à jour ead
     326              reconf = 0
     327          return self._maj(cred_user, id_serveur, reconf, delay, options)
     328
     329 -    def xmlrpc_maj_groupe(self,cred_user,liste,reconf = 0, delay = "", options = ""):
     330          """prépare la mise à jour d'un groupe de serveurs Eole par l'intermédiare d'uucp"""
     331          erreurs=[]
     332          for serveur in liste:
     333              retour = self._maj(cred_user, serveur['id'],reconf,delay,options)
     334              if retour[0] == 0:
     335                  erreurs.append("serveur "+str(serveur['id'])+' : '+retour[1])
     336          if erreurs != []:
     337              return 0, u(erreurs)
     338          else:
     339              return 1, u('ok')
     340
     341 -    def _maj(self, cred_user, id_serveur, reconf, delay,options):
     342          """exécution de la commande uucp pour la mise à jour"""
     343          try:
     344              id_serveur = int(id_serveur)
     345              serv = self.parent.s_pool.get(cred_user,id_serveur)
     346          except (KeyError, ValueError):
     347              return 0, u("serveur inconnu dans la base zephir")
     348          else:
     349              id_uucp = str(serv.get_rne()) + '-' + str(id_serveur)
     350              # construction de la commande
     351              try:
     352                  assert int(delay) > 0
     353                  # si delai, on ne lance pas reconfigure par une action (lancé par la maj différée)
     354                  reconf = 0
     355              except:
     356                  delay = ""
     357              try:
     358                  if serv.version == 'creole1':
     359                      uucp_pool.add_cmd(id_uucp,"zephir_client maj_auto %s" % (str(delay)))
     360                  else:
     361                      uucp_pool.add_cmd(id_uucp,"zephir_client maj_auto %s %s" % (str(delay), options))
     362              except UUCPError, e:
     363                  return 0, u("Erreur UUCP (%s)" % str(e))
     364              # si cela est demandé, on reconfigure le serveur
     365              # 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')
     366              # self.dbpool.runOperation(query)
     367              if reconf == 1:
     368                  return self.xmlrpc_reconfigure(cred_user, id_serveur)
     369              else:
     370                  return 1, u("ok")
     371
     372 -    def xmlrpc_maj_client(self,cred_user,id_serveur):
     373          """prépare la mise à jour de zephir-client sur un serveur"""
     374          # on vérifie l'existence du serveur dans la base
     375          return self._maj_client(cred_user, id_serveur)
     376
     377 -    def xmlrpc_maj_client_groupe(self,cred_user,liste):
     378          """prépare la mise à jour de zephir-client sur un groupe de serveurs"""
     379          erreurs=[]
     380          for serveur in liste:
     381              retour = self._maj_client(cred_user, serveur['id'])
     382              if retour[0] == 0:
     383                  erreurs.append("serveur "+str(serveur['id'])+' : '+retour[1])
     384          if erreurs != []:
     385              return 0, u(erreurs)
     386          else:
     387              return 1, u('ok')
     388
     389 -    def _maj_client(self,cred_user,id_serveur):
     390          """exécution de la commande uucp pour la mise à jour de zephir-client"""
     391          try:
     392              id_serveur = int(id_serveur)
     393              serv = self.parent.s_pool.get(cred_user,id_serveur)
     394          except (KeyError, ValueError):
     395              return 0, u("serveur inconnu dans la base zephir")
     396          else:
     397              id_uucp = str(serv.get_rne()) + '-' + str(id_serveur)
     398              # construction de la commande
     399              try:
     400                  uucp_pool.add_cmd(id_uucp,"zephir_client maj_client")
     401              except UUCPError, e:
     402                  return 0, u("Erreur UUCP (%s)" % str(e))
     403              else:
     404                  return 1, u("ok")
     405
     406 -    def xmlrpc_sphynx_add(self,cred_user,id_sphynx,id_amon,content):
     407          """stocke la configuration RVP d'un amon vers ce sphynx"""
     408          try:
     409              id_sphynx = int(id_sphynx)
     410              id_amon = int(id_amon)
     411              sphynx = self.parent.s_pool.get(cred_user,id_sphynx)
     412              amon = self.parent.s_pool.get(cred_user,id_amon)
     413          except (KeyError, ValueError):
     414              return 0, u("serveur inconnu dans la base zephir")
     415          # on regarde si ce tunnel existe déjà
     416          cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD)
     417          cursor=cx.cursor()
     418          query = """select id_amon from conf_vpn where id_sphynx=%s"""
     419          cursor.execute(query, (int(id_sphynx),))
     420          data=cursor.fetchall()
     421          cursor.close()
     422          cx.close()
     423          # chemin de sauvegarde de l'archive contenant la conf RVP
     424          sphynx_dir = sphynx.get_confdir()
     425          if not os.path.exists(sphynx_dir + os.sep + 'vpn'):
     426              os.makedirs(sphynx_dir + os.sep + 'vpn')
     427          archive = sphynx_dir + os.sep + 'vpn' + os.sep + str(id_amon) + '.tar.gz'
     428          # mise à jour de la table des tunnels configurés
     429          confs = [ligne[0] for ligne in data]
     430          if int(id_amon) in confs:
     431              # on a déjà une conf vpn pour cet amon, mise à jour
     432              query = """update conf_vpn set etat=%s where id_sphynx=%s and id_amon=%s"""
     433              params = (0, int(id_sphynx), int(id_amon))
     434          else:
     435              # sinon, insertion
     436              query = """insert into conf_vpn (id_sphynx,id_amon,etat) values (%s,%s,%s)"""
     437              params = (int(id_sphynx), int(id_amon), 0)
     438          return self.dbpool.runOperation(query, params).addCallbacks(self._sphynx_add,db_client_failed,callbackArgs=[archive,content])
     439
     440 -    def _sphynx_add(self,result,archive,content):
     441          """écriture de la conf RVP"""
     442          try:
     443              file = StringIO()
     444              data = base64.decodestring(content)
     445              fd = open(archive,'wb')
     446              # sauvegarde du fichier
     447              file.write(data)
     448              file.seek(0)
     449              fd.write(file.read())
     450              fd.close()
     451          except:
     452              return 0, u("erreur de sauvegarde de l'archive")
     453          return 1, "OK"
     454
     455 -    def xmlrpc_sphynx_del(self,cred_user,id_sphynx,id_amon,del_row=0):
     456          """supprime la configuration RVP d'un amon vers ce sphynx"""
     457          try:
     458              id_sphynx = int(id_sphynx)
     459              id_amon = int(id_amon)
     460              sphynx = self.parent.s_pool.get(cred_user,id_sphynx)
     461              amon = self.parent.s_pool.get(cred_user,id_amon)
     462          except (KeyError, ValueError):
     463              return 0, u("serveur inconnu dans la base zephir")
     464          cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD)
     465          cursor=cx.cursor()
     466          query = """select etat from conf_vpn where id_sphynx=%s and id_amon=%s"""
     467          params = (int(id_sphynx), int(id_amon))
     468          cursor.execute(query, params)
     469          data=cursor.fetchone()
     470          etat = data[0]
     471          cursor.close()
     472          cx.close()
     473          try:
     474              # chemin de l'archive contenant la conf RVP
     475              sphynx_dir = sphynx.get_confdir()
     476              archive = sphynx_dir + os.sep + 'vpn' + os.sep + str(id_amon) + '.tar.gz'
     477              os.unlink(archive)
     478          except:
     479              if del_row == 0:
     480                  return 0, u("fichier de configuration RVP non supprimé (ou inexistant)")
     481          if del_row == 1:
     482              query = """delete from conf_vpn where id_sphynx=%s and id_amon=%s"""
     483              params = (int(id_sphynx), int(id_amon))
     484          else:
     485              nouv_etat=2
     486              # si l'archive n'a pas été récupérée : anomalie
     487              if int(etat) == 0:
     488                  nouv_etat=3
     489              query = """update conf_vpn set etat=%s where id_sphynx=%s and id_amon=%s"""
     490              params = (int(nouv_etat), int(id_sphynx), int(id_amon))
     491          return self.dbpool.runOperation(query, params).addCallbacks(lambda x : [1,u("OK")],db_client_failed)
     492
     493 -    def xmlrpc_sphynx_get(self,cred_user,id_sphynx,id_amon):
     494          """envoie la configuration RVP d'un amon vers ce sphynx"""
     495          try:
     496              id_sphynx = int(id_sphynx)
     497              id_amon = int(id_amon)
     498              sphynx = self.parent.s_pool.get(cred_user,id_sphynx)
     499              amon = self.parent.s_pool.get(cred_user,id_amon)
     500          except (KeyError, ValueError):
     501              return 0, u("serveur inconnu dans la base zephir")
     502          try:
     503              # chemin de l'archive contenant la conf RVP
     504              sphynx_dir = sphynx.get_confdir()
     505              archive = sphynx_dir + os.sep + 'vpn' + os.sep + str(id_amon) + '.tar.gz'
     506              file_conf=open(archive)
     507              content=base64.encodestring(file_conf.read())
     508              file_conf.close()
     509          except:
     510              return 0, u("fichier de configuration RVP non trouvé")
     511          query = """update conf_vpn set etat=1 where id_sphynx=%s and id_amon=%s"""
     512          params = (int(id_sphynx), int(id_amon))
     513          return self.dbpool.runOperation(query, params).addCallbacks(lambda x : [1,content],db_client_failed)
     514
     515 -    def xmlrpc_sphynx_list(self,cred_user,id_sphynx):
     516          """liste les configs RVP amon présentes pour un sphynx"""
     517          cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD)
     518          cursor=cx.cursor()
     519          query = """select id_amon,etat from conf_vpn where id_sphynx=%s order by etat,id_amon desc""" % id_sphynx
     520          cursor.execute(query, (int(id_sphynx),))
     521          data=cursor.fetchall()
     522          cursor.close()
     523          cx.close()
     524          # on retourne l'id amon et son état
     525          liste_amons=[]
     526          for ligne in data:
     527              liste_amons.append([int(ligne[0]),int(ligne[1])])
     528          return 1,liste_amons
     529
     530 -    def xmlrpc_add_replication(self, cred_user, id_serv, id_client, content):
     531          """ajoute un fichier de configuration pour réplication d'un annuaire sur seshat (ou autre)"""
     532          try:
     533              id_serv = int(id_serv)
     534              id_client = int(id_client)
     535              serv = self.parent.s_pool.get(cred_user,id_serv)
     536              client = self.parent.s_pool.get(cred_user,id_client)
     537          except (KeyError, ValueError):
     538              return 0, u("serveur inconnu dans la base zephir")
     539          try:
     540              rne = client.parsedico()['numero_etab']
     541              assert rne != ""
     542          except:
     543              # si pas défini dans la configuration, on prend le rne
     544              # de l'établissement du serveur dans la base zephir
     545              rne = client.rne
     546          code, message = serv.add_replication(rne, content, id_client)
     547          if code == 0:
     548              return code, message
     549          else:
     550              # configuration ajoutée, on demande automatiquement
     551              # une prise en compte sur le serveur de réplication
     552              return self._update_replication(serv)
     553
     554 -    def xmlrpc_del_replication(self, cred_user, id_serv, conf_file):
     555          """supprime un fichier de configuration de réplication"""
     556          try:
     557              id_serv = int(id_serv)
     558              serv = self.parent.s_pool.get(cred_user,id_serv)
     559          except (KeyError, ValueError):
     560              return 0, u("serveur inconnu dans la base zephir")
     561          return serv.del_replication(conf_file)
     562
     563 -    def xmlrpc_update_replication(self, cred_user, id_serveur):
     564          """prépare l'envoi des configurations de réplication à un serveur central,
     565          et demande une regénération de la configuration
     566          """
     567          try:
     568              id_serveur = int(id_serveur)
     569              serv = self.parent.s_pool.get(cred_user,id_serveur)
     570          except (KeyError, ValueError):
     571              return 0, u("serveur inconnu dans la base zephir")
     572          # on effectue une mise à jour des informations sur les établissements répliqués
     573          # (infos utilisées par eole-sso et par le service dispatcher)
     574          try:
     575              self.parent.s_pool.check_replication_infos(id_serveur)
     576          except:
     577              traceback.print_exc()
     578              log.msg('Erreur de mise à jour du fichier etabs.ini')
     579          return self._update_replication(serv)
     580
     581 -    def _update_replication(self, serv):
     582          # définition du répertoire du serveur
     583          id_uucp = '%s-%s' % (str(serv.get_rne()), str(serv.id_s))
     584          code, message = self._send_files(serv, 'replication', ['replication'], uucp=1)
     585          if code == 0:
     586              return code, u(message)
     587          else:
     588              # les fichiers sont prêts à l'envoi, on demande la prise en compte sur le serveur seshat
     589              try:
     590                  res = uucp_pool.add_cmd(id_uucp, "zephir_client update_replication")
     591              except UUCPError, e:
     592                  return 0, u("Erreur uucp : %s" % str(e))
     593          if os.path.isfile(os.path.join(serv.get_confdir(), 'replication', '.modified')):
     594              os.unlink(os.path.join(serv.get_confdir(), 'replication', '.modified'))
     595          return 1, "OK"
     596
     597 -    def xmlrpc_get_replication_info(self, cred_user, id_serveur):
     598          try:
     599              id_serveur = int(id_serveur)
     600              serv = self.parent.s_pool.get(cred_user,id_serveur)
     601          except (KeyError, ValueError):
     602              return 0, u("serveur inconnu dans la base zephir")
     603          # on force une vérification du fichier etabs.ini avant l'envoi
     604          try:
     605              self.parent.s_pool.check_replication_infos(id_serveur)
     606          except:
     607              traceback.print_exc()
     608              return 0, u('Erreur de mise à jour du fichier etabs.ini')
     609          # lecture du fichier et envoi des informations
     610          try:
     611              data_etab = serv.get_replication_infos()
     612          except:
     613              return 0, u('Erreur de lecture du fichier etabs.ini')
     614          return  1, base64.encodestring(data_etab)
     615
     616
     617 -    def xmlrpc_check_replication(self, cred_user, id_serveur):
     618          """renvoie l'état de la configuration de réplication LDAP
     619          0 : pas de réplication gérée sur ce serveur
     620          1 : configurations de réplication en place
     621          2 : la configuration doit être renvoyée au serveur (si suppression manuelle de fichiers)
     622          """
     623          try:
     624              id_serveur = int(id_serveur)
     625              serv = self.parent.s_pool.get(cred_user,id_serveur)
     626          except (KeyError, ValueError):
     627              return 0, u("serveur inconnu dans la base zephir")
     628          return serv.check_replication()
     629
     630 -    def xmlrpc_get_replication(self, cred_user, id_serveur):
     631          """renvoie la liste des configurations de réplication présentes sur un serveur
     632          """
     633          try:
     634              id_serveur = int(id_serveur)
     635              serv = self.parent.s_pool.get(cred_user,id_serveur)
     636          except (KeyError, ValueError):
     637              return 0, u("serveur inconnu dans la base zephir")
     638          return serv.get_replication()
     639
     640 -    def xmlrpc_confirm_transfer(self,cred_user,id_serveur,archive):
     641          """confirme la réception d'une archive par un serveur"""
     642          try:
     643              id_serveur = int(id_serveur)
     644              serv = self.parent.s_pool.get(cred_user,id_serveur)
     645          except (KeyError, ValueError):
     646              return 0, u("serveur inconnu dans la base zephir")
     647          # définition du répertoire du serveur
     648          serveur_dir = serv.get_confdir()
     649          try:
     650              # suppression de l'archive
     651              os.unlink(serveur_dir+os.sep+archive+'.tar')
     652              # supression du fichier de checksum
     653              os.unlink(serveur_dir+os.sep+archive+'.md5')
     654          except:
     655              return 0, u("""erreur de suppression de l'archive""")
     656          else:
     657              return 1, u('ok')
     658
     659 -    def xmlrpc_get_checksum(self,cred_user,id_serveur,archive):
     660          """confirme la réception d'une archive par un serveur"""
     661          try:
     662              id_serveur = int(id_serveur)
     663              serv = self.parent.s_pool.get(cred_user,id_serveur)
     664          except (KeyError, ValueError):
     665              return 0, u("serveur inconnu dans la base zephir")
     666          # définition du répertoire du serveur
     667          serveur_dir = serv.get_confdir()
     668          # lecture du fichier md5
     669          try:
     670              fic_md5=open(serveur_dir+os.sep+archive+'.md5')
     671              md5sum = fic_md5.readlines()
     672              fic_md5.close()
     673          except:
     674              return 0, u("""fichier %s.md5 non trouve""" % (archive))
     675          else:
     676              # ok, on renvoie la chaine de contrôle
     677              return 1, base64.encodestring(md5sum[0])
     678
     679 -    def xmlrpc_install_module(self,cred_user,id_module,dico_b64):
     680          """installation d'un module (récupération d'un dictionnaire)"""
     681          # pour l'instant, cette procédure sert à créer ou
     682          # mettre à jour le dictionnaire principal du module
     683          # on récupère le libellé du module dans la base
     684          query = """select id, libelle, version from modules where id=%s""" % id_module
     685          return self.dbpool.runQuery(query, (int(id_module),)).addCallbacks(self._install_module,db_client_failed,callbackArgs=[dico_b64])
     686
     687 -    def _install_module(self,data,dico_b64):
     688          if data == []:
     689              return 0, u("""erreur, module non trouvé""")
     690          else:
     691              id_module = data[0][0]
     692              libelle = data[0][1]
     693              version = data[0][2]
     694              if version == 1:
     695                  #creole 1
     696                  dico_path = os.path.abspath(config.ROOT_DIR)+os.sep+'dictionnaires'
     697                  dico_b64 = {'dico-'+str(libelle):dico_b64}
     698              else:
     699                  #creole 2
     700                  dico_path = os.path.abspath(config.ROOT_DIR)+os.sep+'dictionnaires'+os.sep+str(libelle)
     701                  if not os.path.isdir(dico_path):
     702                      # module supplémentaire non géré par eole
     703                      dico_path = os.path.join(os.path.abspath(config.PATH_MODULES),str(id_module),"dicos")
     704              # traitement des dictionnaires définis
     705              for dic_name, data in dico_b64.items():
     706                  dico = os.path.join(dico_path, dic_name)
     707                  try:
     708                      if os.path.isfile(dico):
     709                          # le dictionnaire existe déjà
     710                          os.unlink(dico)
     711                      # recréation du fichier avec les données transmises
     712                      fic_dico = open(dico,'w')
     713                      fic_dico.write(base64.decodestring(data))
     714                      fic_dico.close()
     715                  except:
     716                      traceback.print_exc()
     717                      return 0, u("erreur de mise a jour du dictionnaire du module")
     718
     719          return 1,u("ok")
     720
     721 -    def xmlrpc_exec_script(self, cred_user, serveurs, script_name, params):
     722          """exécution d'un script client sur un serveur/groupe
     723          serveurs: id du serveur ou liste d'id
     724          script_name: nom du script à exécuter
     725          params:paramètres supplémentaires à donner au script
     726          """
     727          if type(serveurs) != list:
     728              serveurs = [serveurs]
     729          erreurs = []
     730          for id_serveur in serveurs:
     731              try:
     732                  id_serveur = int(id_serveur)
     733                  serv = self.parent.s_pool.get(cred_user, id_serveur)
     734              except:
     735                  erreurs.append("Serveur %s : inexistant ou accès refusé" % str(id_serveur))
     736                  continue
     737              try:
     738                  id_uucp = str(serv.get_rne()) + '-' + str(serv.id_s)
     739                  cmd = "zephir_client %s %s" % (script_name, params)
     740                  uucp_pool.add_cmd(id_uucp,cmd.strip())
     741              except UUCPError,e:
     742                  erreurs.append("serveur %s (%s) : Erreur UUCP %s" % (serv.id_s, serv.rne, str(e)))
     743                  continue
     744          if len(erreurs) == len(serveurs):
     745              return 0, "Echec de l'exécution ou action interdite sur tous les serveurs"
     746          return 1, erreurs
     747
     748 -    def xmlrpc_save_files(self,cred_user,id_serveur,checksum):
     749          """sauvegarde des fichiers de configuration d'un serveur"""
     750          try:
     751              id_serveur = int(id_serveur)
     752              serv = self.parent.s_pool.get(cred_user, id_serveur)
     753          except (KeyError, ValueError):
     754              return 0, u("serveur inconnu dans la base zephir")
     755          module = serv.id_mod
     756          variante = serv.id_var
     757          archive='fichiers_zephir'+str(id_serveur)
     758          public_dir = '/var/spool/uucppublic'
     759          temp_dir = public_dir+os.sep+str(id_serveur)
     760          # création d'un répertoire temporaire pour éviter que tout le monde
     761          # écrive dans le même répertoire
     762          if os.path.isdir(temp_dir):
     763              shutil.rmtree(temp_dir)
     764          try:
     765              os.mkdir(temp_dir)
     766          except:
     767              return 0, u("""erreur de creation du repertoire temporaire""")
     768          serveur_dir = serv.get_confdir()
     769          # on vérifie la validité de l'archive
     770          try:
     771              fic_md5 = open(public_dir+os.sep+archive+'.md5','w')
     772              fic_md5.write(checksum)
     773              fic_md5.close()
     774          except:
     775              return 0, u("""erreur d'écriture du fichier de checksum""")
     776          cmd_md5 = """cd %s ; md5sum -c %s.md5 2>&1 > /dev/null""" % (public_dir,archive)
     777          res=os.system(cmd_md5)
     778          if res != 0:
     779              return 0, u("""archive corrompue""")
     780          else:
     781              # l'archive est valide, on la décompresse
     782              cmd_tar = """cd %s ; tar -C %s --same-owner -xhpf %s.tar >/dev/null 2>&1""" % (public_dir,str(id_serveur),archive)
     783              os.system(cmd_tar)
     784              # on met ensuite les fichiers en place
     785              # supression des anciens fichiers ?
     786              directories = ['dicos','fichiers_perso','patchs','fichiers_zephir']
     787              for rep in directories:
     788                  if os.path.exists(os.path.join(temp_dir, 'temp_zephir', rep)):
     789                      try:
     790                          if rep == 'dicos' and os.path.isdir(os.path.join(os.path.abspath(config.PATH_MODULES),str(module),'dicos')):
     791                              # creole2 : on conserve module et variante
     792                              shutil.rmtree(serveur_dir+os.sep+rep+'/local')
     793                          else:
     794                              shutil.rmtree(serveur_dir+os.sep+rep)
     795                      except:
     796                          # le repertoire (ou fichier) n'existe pas encore
     797                          pass
     798              # on déplace les fichiers de l'archive
     799              res = 0
     800              for rep in directories:
     801                  if res == 0:
     802                      if os.path.exists(os.path.join(temp_dir, 'temp_zephir', rep)):
     803                          if os.path.isdir(os.path.join(os.path.abspath(config.PATH_MODULES),str(module),'dicos')) and rep == 'dicos':
     804                              # cas d'eole2 : répertoire de dictionnaires locaux
     805                              res = os.system("mv -f %s %s" % (temp_dir+'/temp_zephir/'+rep+'/local', os.path.join(serveur_dir,rep)))
     806                          else:
     807                              res = os.system("mv -f %s %s" % (temp_dir+'/temp_zephir/'+rep,serveur_dir))
     808                              if res == 0:
     809                                  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')
     810
     811              if res != 0:
     812                  return 0, u("""erreur de mise en place des fichiers""")
     813
     814              if os.path.exists(os.path.join(temp_dir, 'temp_zephir', 'zephir.eol')):
     815                  # mise en place de zephir.eol
     816                  res = os.system("mv -f %s %s" % (temp_dir+'/temp_zephir/zephir.eol',serveur_dir))
     817                  if res != 0:
     818                      return 0, u("""erreur de mise en place de zephir.eol""")
     819                  else:
     820                      # mise à jour de l'état du serveur
     821                      serv.maj_params({'config_ok':1})
     822                      # prise en compte de la configuration dans le cache mémoire
     823                      if serv.dico is not None:
     824                          if config.CREOLE_CACHE:
     825                              serv.dico.mode = None
     826                              serv.load_conf('modif_config')
     827                          else:
     828                              serv.last_mode = None
     829                              serv.get_config('modif_config')
     830
     831              # vérification des md5 de la configuration
     832              new_method = serv.check_min_version(self.parent.maj_checker, 'zephir-client', '2.3-eole54~1')
     833              serv.check_md5conf(new_method)
     834              # vidage du répertoire public
     835              try:
     836                  # on supprime les fichiers temporaires
     837                  os.unlink(public_dir+os.sep+archive+'.tar')
     838                  os.unlink(public_dir+os.sep+archive+'.md5')
     839                  shutil.rmtree(temp_dir)
     840              except:
     841                  return 0, u("""erreur de supression des fichiers temporaires""")
     842              return 1, u('ok')
     843
     844
     845 -    def xmlrpc_install_variante(self,cred_user,id_serveur,checksum,login,passwd_md5):
     846          """installation d'une variante pour un module"""
     847          try:
     848              id_serveur = int(id_serveur)
     849              serv = self.parent.s_pool.get(cred_user, id_serveur)
     850          except (KeyError, ValueError):
     851              return 0, u("serveur inconnu dans la base zephir")
     852          module = serv.id_mod
     853          variante = serv.id_var
     854          query = """select id,module,owner,passmd5 from variantes where id = %s and module = %s"""
     855          params = (int(variante), int(module))
     856          return self.dbpool.runQuery(query, params).addCallbacks(self._install_variante2,db_client_failed,callbackArgs=[cred_user,checksum,login,passwd_md5,serv.get_rne(),id_serveur])
     857
     858
     859 -    def _install_variante2(self,data,cred_user,checksum,login,passwd_md5,rne,id_serveur):
     860          """vérification de l'archive et stockage des fichiers"""
     861          if data == []:
     862              return 0, u("""variante non retrouvée dans la base""")
     863          variante = data[0][0]
     864          module = data[0][1]
     865          owner_var = data[0][2]
     866          passwd_var= data[0][3]
     867          archive='variante'+str(id_serveur)
     868          public_dir = '/var/spool/uucppublic'
     869          temp_dir = public_dir+os.sep+str(id_serveur)
     870          variante_dir = os.path.abspath(config.PATH_ZEPHIR)+os.sep+'modules'+os.sep+str(module)+os.sep+'variantes'+os.sep+str(variante)
     871          # si le mot de passe de la variante n'existe pas (première installation), on le stocke dans la base
     872          # si on est propriétaire de la variante : ok
     873          if cred_user != owner_var:
     874              # si pas de mot de passe : ok
     875              if passwd_var not in [None,'']:
     876                  # sinon on vérifie le mot de passe
     877                  if passwd_md5 != passwd_var:
     878                      return 0, u("""erreur, le mot de passe est invalide""")
     879
     880          # création d'un répertoire temporaire pour éviter que tout le monde
     881          # écrive dans le même répertoire
     882          if os.path.isdir(temp_dir):
     883              shutil.rmtree(temp_dir)
     884          try:
     885              os.mkdir(temp_dir)
     886          except:
     887              return 0, u("""erreur de création du repertoire temporaire""")
     888          # on vérifie la validité de l'archive
     889          try:
     890              fic_md5 = open(public_dir+os.sep+archive+'.md5','w')
     891              fic_md5.write(checksum)
     892              fic_md5.close()
     893          except:
     894              return 0, u("""erreur d'écriture du fichier de checksum""")
     895          cmd_md5 = """cd %s ; md5sum -c %s.md5 2>&1 > /dev/null""" % (public_dir,archive)
     896          res=os.system(cmd_md5)
     897          if res != 0:
     898              return 0, u("""archive corrompue""")
     899          else:
     900              # l'archive est valide, on la décompresse
     901              cmd_tar = """cd %s ; tar -C %s --same-owner -xhpf %s.tar > /dev/null""" % (public_dir,str(id_serveur),archive)
     902              os.system(cmd_tar)
     903              # on met ensuite les fichiers en place
     904              # supression des anciens patchs et dictionnaires locaux
     905              try:
     906                  shutil.rmtree(variante_dir+os.sep+'dicos')
     907                  shutil.rmtree(variante_dir+os.sep+'patchs')
     908                  shutil.rmtree(variante_dir+os.sep+'fichiers_perso')
     909                  shutil.rmtree(variante_dir+os.sep+'fichiers_zephir')
     910              except:
     911                  return 0, u("""erreur de supression de l'ancienne variante""")
     912              # on déplace les fichiers de l'archive
     913              res = os.system("mv %s %s" % (temp_dir+os.sep+'patch/variante',variante_dir+os.sep+'patchs'))
     914              if res == 0:
     915                  res = os.system("mv %s %s" % (temp_dir+os.sep+'dicos/variante',variante_dir+os.sep+'dicos'))
     916              if res == 0:
     917                  res = os.system("mv %s %s" % (temp_dir+os.sep+'fichiers_perso',variante_dir+os.sep+'fichiers_perso'))
     918              if res == 0:
     919                  res = os.system("mv %s %s" % (temp_dir+os.sep+'fichiers_zephir',variante_dir+os.sep+'fichiers_zephir'))
     920              if res != 0:
     921                  return 0, u("""erreur de mise en place de la variante""")
     922              # vidage du répertoire public
     923              try:
     924                  # on supprime les fichiers temporaires
     925                  os.unlink(public_dir+os.sep+archive+'.tar')
     926                  os.unlink(public_dir+os.sep+archive+'.md5')
     927                  shutil.rmtree(temp_dir)
     928              except:
     929                  return 0, u("""erreur de supression des fichiers temporaires""")
     930
     931          if passwd_var in [None,'']:
     932              # stockage des informations d'authentification
     933              query = """update variantes set owner=%s, passmd5=%s where id = %s and module = %s"""
     934              params = (login, passwd_md5, int(variante), int(module))
     935              return self.dbpool.runOperation(query, params).addCallbacks(lambda x : [1,'ok'],lambda x : [0,'erreur de stockage du mot de passe'])
     936          else:
     937              return 1,u('ok')
     938
     939 -    def xmlrpc_log_serveur(self,cred_user,id_serveur,date,type_action,etat,msg):
     940          """ met à jour la table d'état du serveur pour une action précise
     941          (ex: MAJ ou CONFIG) afin de refléter l'état de cohérence actuelle du serveur
     942          """
     943          params = {'last_log':str(date)}
     944          if type_action in ['MAJ','CONFIGURE','RECONFIGURE','SAUVEGARDE','REBOOT','SERVICE_RESTART','UPGRADE','PERSO']:
     945              # on met à jour le champs params du serveur pour refléter un éventuel changement d'état
     946              if int(etat) == -1:
     947                  params['%s_ok' % type_action.lower()] = [2, str(date), msg]
     948              elif int(etat) > 0:
     949                  params['%s_ok' % type_action.lower()] = [0, str(date), msg]
     950              elif int(etat) == 0:
     951                  if type_action == "MAJ":
     952                      # cas spécial, maj lancée : on force query_maj à 0 (plus de paquets non à jour)
     953                      # params['query_maj'] = [0, str(date)]
     954                      pass
     955                  elif type_action == "CONFIGURE":
     956                      # cas de la fin d'envoi de configuration
     957                      # on estime que les données de configuration sont synchronisées (md5)
     958                      # si ce n'est pas le cas, la non concordance sera détectée au prochain envoi de stats
     959                      md5file = os.path.join(os.path.abspath(config.PATH_ZEPHIR),'data','config%s.md5' % id_serveur)
     960                      if os.path.isfile(md5file):
     961                          self.parent.s_pool.edit_serveur(id_serveur,{'md5s':1})
     962                          params['md5s'] = [1,""]
     963                  params['%s_ok' % type_action.lower()] = [1, str(date), msg]
     964          elif type_action == 'LOCK':
     965              if int(etat) == 1:
     966                  params['lock_ok'] = [2, str(date), msg]
     967              else:
     968                  params['lock_ok'] = [1,'']
     969          try:
     970              id_serveur = int(id_serveur)
     971              serv = self.parent.s_pool[id_serveur]
     972              if serv.version == 'creole1':
     973                  if params.has_key('query_maj'):
     974                      params['query_maj'] = [-2,""]
     975          except (KeyError, ValueError):
     976              return 0, u("serveur inconnu dans la base zephir")
     977          else:
     978              # on met à jour la date de dernier contact dans la base
     979              self.parent.s_pool.update_contact(id_serveur)
     980
     981          # on regarde si l'action en question a déjà un état
     982          query = """select id,etat,date,type from last_log_serveur where id_serveur=%s and type=%s"""
     983          sql_params = (int(id_serveur), type_action)
     984          return self.dbpool.runQuery(query, sql_params).addCallbacks(self._log_serveur,db_client_failed,callbackArgs=[id_serveur,type_action,date,int(etat),msg, params, serv])
     985
     986 -    def _log_serveur(self,data,id_serveur,type_action,date,etat,msg,params,serv):
     987          # si l'action existe déjà on la met à jour, sinon on l'insère
     988          if data != []:
     989              # on insère que si la date du nouveau log est > à l'ancien (cas d'anciens logs non remontés)
     990              last_date = data[0][2]
     991              try:
     992                  new_date = datetime.strptime(str(date), "%c")
     993              except:
     994                  try:
     995                      # problème de conversion de date (pb de locale ?)
     996                      # on convertit le jour/mois en français
     997                      new_date = str(date).split()
     998                      new_date[0] = config.days[new_date[0]]
     999                      new_date[1] = config.months[new_date[1]]
    1000                      new_date = " ".join(new_date)
    1001                      new_date = datetime.strptime(str(new_date),"%a %b %d %H:%M:%S %Y")
    1002                  except:
    1003                      log.msg("Serveur %s - erreur de lecture de la date pour le log suivant : %s, %s, %s (%s)" % \
    1004                              (str(id_serveur), type_action, str(etat), msg, date))
    1005                      log.msg("utilisation de la date courante pour ce log")
    1006                      new_date = datetime.utcnow()
    1007              if new_date >= last_date:
    1008                  query = """update last_log_serveur set id_serveur=%s,date=%s,type=%s,message=%s,etat=%s where id=%s"""
    1009                  sql_params = (int(id_serveur), date, type_action, msg, int(etat), int(data[0][0]))
    1010                  # on met à jour le champs params et le cache mémoire
    1011                  #if params.has_key('query_maj'):
    1012                  #    self.parent.s_pool.edit_serveur(id_serveur,{'maj':params['query_maj'][0]})
    1013                  serv.maj_params(params)
    1014              else:
    1015                  # on a reçu un ancien log (reprise d'anciens logs ayant échoué) -> pas de maj de last_log
    1016                  return self._log_serveur2(None,id_serveur,type_action,date,etat,msg)
    1017          else:
    1018              query = """insert into last_log_serveur (id_serveur,date,type,message,etat) values (%s,%s,%s,%s,%s)"""
    1019              sql_params = (int(id_serveur), date, type_action, msg, int(etat))
    1020              # on met à jour le champs params et le cache mémoire
    1021              #if params.has_key('query_maj'):
    1022              #    self.parent.s_pool.edit_serveur(id_serveur,{'maj':params['query_maj'][0]})
    1023              serv.maj_params(params)
    1024          return self.dbpool.runOperation(query, sql_params).addCallbacks(self._log_serveur2,db_client_failed,callbackArgs=[id_serveur,type_action,date,etat,msg])
    1025
    1026 -    def _log_serveur2(self,data,id_serveur,type_action,date,etat,msg):
    1027          query = """insert into log_serveur (id_serveur,date,type,message,etat) values (%s,%s,%s,%s,%s)"""
    1028          sql_params = (int(id_serveur), date, type_action, msg, etat)
    1029          # on effectue la mise à jour de la base
    1030          return self.dbpool.runOperation(query, sql_params).addCallbacks(lambda x : [1,'ok'],db_client_failed)
    1031
    1032 -    def xmlrpc_release_lock_groupe(self,cred_user,liste):
    1033          """prépare la suppression des verrous sur un groupe"""
    1034          erreurs=[]
    1035          for serveur in liste:
    1036              retour = self.xmlrpc_release_lock(cred_user, serveur['id'])
    1037              if retour[0] == 0:
    1038                  erreurs.append(str(serveur['id'])+' : '+retour[1])
    1039          if erreurs != []:
    1040              return 0, u(erreurs)
    1041          else:
    1042              return 1, u('ok')
    1043
    1044 -    def xmlrpc_release_lock(self,cred_user,id_serveur):
    1045          """demande la libération des verrous sur un serveur"""
    1046          try:
    1047              id_serveur = int(id_serveur)
    1048              serv = self.parent.s_pool.get(cred_user,id_serveur)
    1049          except (KeyError, ValueError):
    1050              return 0, u("serveur inconnu dans la base zephir")
    1051          else:
    1052              serv.maj_params({'del_locks':True})
    1053          return 1, 'ok'
    1054
    1055 -    def xmlrpc_unlock(self,cred_user,id_serveur,unlocked=False):
    1056          """indique si les locks doivent être ignorés
    1057          @params unlocked: si True, on enlève l'attibut del_lock de params"""
    1058          try:
    1059              id_serveur = int(id_serveur)
    1060              serv = self.parent.s_pool.get(cred_user,id_serveur)
    1061          except (KeyError, ValueError):
    1062              return 0, u("serveur inconnu dans la base zephir")
    1063          params = serv.get_params()
    1064          if params.has_key('del_locks'):
    1065              if params['del_locks'] == True:
    1066                  if unlocked:
    1067                      # les verrous ont été supprimés, on revient en état normal
    1068                      serv.maj_params({'del_locks':False})
    1069                  # les verrous doivent être bypassés
    1070                  return 1, True
    1071          return 1, False
    1072
    1073 -    def _sendmail(self,adresses,subject,msg):
    1074          """envoi d'un message d'alerte à une liste d'adresses mail
    1075          """
    1076          bad_addr={}
    1077          mail = email.MIMEText.MIMEText(msg)
    1078          mail['Subject'] = Header("[Zephir] %s" % subject,"utf-8")
    1079          mail['From'] = Header(config.MAIL_ACCOUNT, "utf-8")
    1080          mail.set_charset('UTF-8')
    1081          mail_client=smtplib.SMTP()
    1082          orig_timeout = smtplib.socket.getdefaulttimeout()
    1083          try:
    1084              smtplib.socket.setdefaulttimeout(3)
    1085              if config.MAIL_PORT.startswith('port '):
    1086                  mail_client.connect(config.MAIL_ADRESSE,int(config.MAIL_PORT.replace('port ','')))
    1087              else:
    1088                  mail_client.connect(config.MAIL_ADRESSE)
    1089              smtplib.socket.setdefaulttimeout(orig_timeout)
    1090          except:
    1091              smtplib.socket.setdefaulttimeout(orig_timeout)
    1092              return 0, u('erreur de connexion au serveur smtp')
    1093          else:
    1094              try:
    1095                  mail_client.ehlo_or_helo_if_needed()
    1096                  if config.MAIL_PORT.startswith('port '):
    1097                      try:
    1098                          mail_client.starttls()
    1099                      except smtplib.SMTPException, e:
    1100                          return 0, u("Erreur d'envoi du mail d'alerte : le serveur %s ne gère pas les connexions cryptées (TLS)" % config.MAIL_ADRESSE)
    1101                  bad_addr = mail_client.sendmail(config.MAIL_ACCOUNT,adresses,mail.as_string())
    1102              except:
    1103                  return 0, u("erreur d'envoi du mail d'alerte")
    1104          return 1, bad_addr
    1105
    1106 -    def xmlrpc_maj_site(self,cred_user,ip_publique,id_serveur,checksum,new_agents=0):
    1107          if config.USE_THREADS:
    1108              return threads.deferToThread(self._maj_site, cred_user,ip_publique, \
    1109                                           id_serveur,checksum,new_agents)
    1110          else:
    1111              return self._maj_site(cred_user, ip_publique, id_serveur, checksum, new_agents)
    1112
    1113 -    def _maj_site(self,cred_user,ip_publique,id_serveur,checksum,new_agents=0):
    1114          """vérifie l'archive envoyée par le serveur et met le site et les données xml en place
    1115          """
    1116          log.msg ("connexion du serveur %s" % str(id_serveur))
    1117          # on regarde dans les logs si un lock est indiqué
    1118          cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD)
    1119          query="""select type,etat from last_log_serveur where id_serveur=%s and type='LOCK' order by date desc, id desc"""
    1120          cursor=cx.cursor()
    1121          cursor.execute(query, (int(id_serveur),))
    1122          data=cursor.fetchall()
    1123          cursor.close()
    1124          cx.close()
    1125          etat=0
    1126          if data != []:
    1127              etat=int(data[0][1])
    1128          if etat == 1:
    1129              # si il y avait un lock sur uucp, on l'annule
    1130              self.xmlrpc_log_serveur(cred_user,id_serveur,str(time.ctime()),'LOCK','0',"""Reprise de l'activité uucp""")
    1131          # on met à jour la date de dernier contact dans la base
    1132          self.parent.s_pool.update_contact(id_serveur)
    1133          # vérification du md5 de l'archive
    1134          public_dir = '/var/spool/uucppublic'
    1135          archive = 'site%s' % id_serveur
    1136          try:
    1137              fic_md5 = open(public_dir+os.sep+archive+'.md5','w')
    1138              fic_md5.writelines(checksum)
    1139              fic_md5.close()
    1140          except:
    1141              return 0, u("""erreur d'écriture du fichier de checksum""")
    1142          cmd_md5 = """cd %s ; md5sum -c %s.md5 2>&1 > /dev/null""" % (public_dir, archive)
    1143          res=os.system(cmd_md5)
    1144          if res != 0:
    1145              return 0, u("""archive corrompue""")
    1146          else:
    1147              compressed=''
    1148              # l'archive est valide, on la décompresse
    1149              if int(new_agents) == 1:
    1150                  # l'archive est zippée avec les nouveaux agents
    1151                  compressed = 'z'
    1152                  rep_dest = os.path.abspath(config.PATH_ZEPHIR)
    1153                  # on supprime l'ancien répertoire
    1154                  try:
    1155                      shutil.rmtree(rep_dest+os.sep+"data"+os.sep+str(id_serveur))
    1156                  except:
    1157                      pass
    1158              else:
    1159                  rep_dest = os.path.abspath(config.PATH_ZEPHIR)+os.sep+"sites"+os.sep+str(id_serveur)
    1160                  # on supprime l'ancien répertoire
    1161                  if os.path.exists(rep_dest):
    1162                      shutil.rmtree(rep_dest)
    1163                  os.makedirs(rep_dest)
    1164
    1165              cmd_tar = """cd %s ; /bin/tar -C %s -x%sf %s.tar 2> /dev/null""" % (public_dir, rep_dest, compressed, archive)
    1166              res=os.system(cmd_tar)
    1167              if res != 0:
    1168                  return 0, u("erreur de mise en place du site sur zephir")
    1169              serv = self.parent.s_pool[int(id_serveur)]
    1170              if self.parent.maj_checker:
    1171                  serv.check_maj_status(self.parent.maj_checker)
    1172              new_method = serv.check_min_version(self.parent.maj_checker, 'zephir-client', '2.3-eole54~1')
    1173              # vérification du md5 de la configuration
    1174              serv.check_md5conf(new_method)
    1175              serv.update_ip_pub(ip_publique)
    1176              if int(new_agents) == 1 and serv.version == 'creole1':
    1177                  # si serveur eole 1, on convertit le xml en utf-8
    1178                  f_site = file(os.path.join(rep_dest,'data',str(id_serveur),'site.cfg'))
    1179                  data = f_site.read()
    1180                  f_site.close()
    1181                  try:
    1182                      data = unicode(data,'ISO-8859-1').encode(config.charset)
    1183                  except:
    1184                      pass
    1185                  else:
    1186                      f_site = file(os.path.join(rep_dest,'data',str(id_serveur),'site.cfg'),'w')
    1187                      f_site.write(data)
    1188                      f_site.close()
    1189                  for xml_file in glob.glob(os.path.join(rep_dest,'data',str(id_serveur),'*/agent.xml')):
    1190                      try:
    1191                          xml = file(xml_file).read()
    1192                          # conversion du contenu
    1193                          for ori, dst in config.xml_table.items():
    1194                              xml = xml.replace(ori,dst)
    1195                          file(xml_file,'w').write(xml)
    1196                      except:
    1197                          log.msg("erreur lors de la conversion de %s en %s" % (xml_file, config.charset))
    1198              # on met à jour la liste d'agents (en cas de nouvel agent)
    1199              # et on regarde si un des agents a remonté une erreur
    1200              list_errors = []
    1201              try:
    1202                  if self.agent_manager.has_key(str(id_serveur)):
    1203                      # nouvelle API des agents
    1204                      # on force un update du cache pour ce serveur (prise en compte de nouveaux agents sans redémarrer l'application)
    1205                      self.agent_manager[str(id_serveur)].update_structure()
    1206                      stats = self.agent_manager[str(id_serveur)].get_measure()
    1207                      result_ag = self.agent_manager[str(id_serveur)].global_status()
    1208                      if result_ag == 0:
    1209                          # détail des agents en erreur
    1210                          liste_errors = []
    1211                          for ag_name, detail_ag in self.agent_manager[str(id_serveur)].agents_status().items():
    1212                              if detail_ag[1] == 0 and ag_name != 'tcpservices':
    1213                                  list_errors.append(detail_ag[0])
    1214                  else:
    1215                      # anciens agents
    1216                      # mise à jour des données depuis les xml remontés
    1217                      AgentCollecteur(id_serveur)
    1218                      result_ag = ServeurStatus(id_serveur).get_status()
    1219              except:
    1220                  traceback.print_exc()
    1221                  result_ag = 1
    1222
    1223              # on vérifie la cohérence du serveur au niveau des logs zephir
    1224              try:
    1225                  result_zeph = self.parent.getSubHandler('serveurs').xmlrpc_get_status(cred_user,id_serveur)
    1226              except:
    1227                  return 0, u("erreur de récupération de l'état zephir du serveur %s" % id_serveur)
    1228
    1229              d = defer.Deferred()
    1230              d.addCallback(self._alerte,result_zeph[1],result_ag,list_errors)
    1231              d.callback(id_serveur)
    1232
    1233              return 1,u("ok")
    1234
    1235
    1236 -    def _alerte(self,id_serveur,etat_zeph,etat_ag,list_errors):
    1237          """vérification de l'état du serveur et envoi mail si nécessaire
    1238          """
    1239          # on récupére la liste des utilisateurs à contacter
    1240          query="select serveurs.id,serveurs.rne,installateur,serveurs.libelle, \
    1241          modules.libelle,etablissements.libelle,serveurs.etat \
    1242          from serveurs,etablissements,modules \
    1243          where serveurs.id=%s and etablissements.rne=serveurs.rne and modules.id=module_actuel"
    1244          self.dbpool.runQuery(query, (int(id_serveur),)).addCallbacks(self._alerte2,db_client_failed,callbackArgs=[etat_zeph,etat_ag,list_errors])
    1245
    1246 -    def _alerte2(self,data,etat_zeph,etat_ag,list_errors):
    1247          # si erreur zephir ou agent --> mail
    1248          if data == []:
    1249              # pas de données récupérées (serveur inexistant ?)
    1250              pass
    1251          else:
    1252              id_serveur = data[0][0]
    1253              rne = data[0][1]
    1254              libelle = data[0][3]
    1255              module = data[0][4]
    1256              libel_etab = data[0][5]
    1257              etat_precedent = data[0][6]
    1258              if etat_precedent != None:
    1259                  try:
    1260                      etat_precedent = int(etat_precedent)
    1261                  except Exception, e:
    1262                      etat_precedent = 1
    1263              erreur = 0
    1264              msg = """le serveur %s (%s - %s)\n établissement : %s (%s)""" % (libelle, id_serveur, module, rne, libel_etab)
    1265              # vérification de l'état du serveur
    1266              for cle in etat_zeph.keys():
    1267                  etat = etat_zeph[cle]
    1268                  if type(etat) == list:
    1269                      if len(etat) == 3:
    1270                          if etat[0] == 0:
    1271                              if erreur == 0:
    1272                                  msg += """\n(se reporter à la page d'état du serveur dans l'application web)"""
    1273                                  erreur = 1
    1274                              msg +="""\n\nlog du %s : %s""" % (etat[1].encode(config.charset),etat[2].encode(config.charset))
    1275                  if (cle == 'lock_ok') and (etat[0] != 1):
    1276                      msg += """\n\n Fonction Zephir verrouillées, connectez vous sur le serveur pour vérifier son état
    1277                      (commande '/usr/share/zephir/scripts/zephir_client del_lock' pour déverrouiller)"""
    1278
    1279              # on stocke l'etat global des agents dans le champs params du serveur
    1280              serv = self.parent.s_pool[id_serveur]
    1281              serv.maj_params({'agents':etat_ag})
    1282              if etat_ag == 0:
    1283                  erreur = 2
    1284                  # erreur remontée dans le site de surveillance
    1285                  msg += """\n\nerreur remontée par le serveur (cf. https://%s:%s/agents/%s)""" % (config.ADRESSE_ZEPHIR,config.PORT_HTTP,id_serveur)
    1286                  if list_errors != []:
    1287                      msg += """\n\n* %s""" % "\n* ".join(list_errors)
    1288
    1289              # envoi de message si erreur non envoyée précédemment
    1290              # on regarde le dernier état enregistré pour ce serveur
    1291              if erreur != 0:
    1292                  if etat_precedent not in [0,4]:
    1293                      if etat_precedent == 3:
    1294                          serv.set_status(4)
    1295                      else:
    1296                          serv.set_status(0)
    1297                      if serv.no_alert == False:
    1298                          # début d'alerte
    1299                          if etat_precedent == 2:
    1300                              # on vient de reprendre contact et il y a un problème
    1301                              subject = "problème détecté à la reprise de contact: serveur %s (%s)" % (libelle,rne)
    1302                          else:
    1303                              subject = "problème détecté : serveur %s (%s)" % (libelle,rne)
    1304                          msg = "\nproblème détecté sur " + msg
    1305                          self._send_alerte("problème détecté : serveur ",{int(id_serveur):msg})
    1306              else:
    1307                  # pas d'erreur détectée, si l'état était à 2, on ne le change pas
    1308                  # (l'état sera remis à 1 par la fonction de vérification du timeout)
    1309                  if etat_precedent in [0,4]:
    1310                      if etat_precedent == 4:
    1311                          serv.set_status(3)
    1312                      else:
    1313                          serv.set_status(1)
    1314                      if serv.no_alert == False:
    1315                          # fin d'alerte
    1316                          subject = "fin d'alerte : serveur %s (%s)" % (libelle,rne)
    1317                          msg = "\n fin d'alerte pour " + msg
    1318                          self._send_alerte("fin d'alerte : ",{int(id_serveur):msg})
    1319                  # si on n'avait pas d'info : etat ok
    1320                  if etat_precedent == None:
    1321                      serv.set_status(1)
    1322
    1323 -    def _send_alerte(self,subject,msgs):
    1324          """recherche les mails et sms des personnes surveillant un serveur particulier
    1325          """
    1326          if msgs != {}:
    1327              query = """select id,serveurs from groupes_serveurs"""
    1328              self.dbpool.runQuery(query).addCallbacks(self._send_alerte2,db_client_failed,callbackArgs=[subject,msgs])
    1329
    1330 -    def _send_alerte2(self,data,subject,msg):
    1331          # on récupère les groupes
    1332          # et on regarde quels groupes contiennent ce serveur
    1333          groupes=[]
    1334          for id_serveur in msg.keys():
    1335              for groupe in data:
    1336                  if id_serveur in eval(groupe[1]):
    1337                      if groupe[0] not in groupes:
    1338                          groupes.append(groupe[0])
    1339          query = """select groupes,mail,sms,mail_actif,sms_actif from users \
    1340                  where groupes != '' and (mail_actif=1 or sms_actif=1)"""
    1341          self.dbpool.runQuery(query).addCallbacks(self._send_alerte3,db_client_failed,callbackArgs=[groupes,subject,msg])
    1342
    1343 -    def _send_alerte3(self,data,groupes,subject,msg):
    1344          """regarde quels utilisateurs surveillent les groupes
    1345          en question et envoie un mail ou sms si besoin
    1346          """
    1347          # utilisateurs avec les bons groupes
    1348          destinataires = []
    1349          for user in data:
    1350              try:
    1351                  groupes_user=eval(user[0])
    1352              except:
    1353                  groupes_user=[]
    1354              for groupe in groupes_user:
    1355                  # un des groupes contient ce serveur
    1356                  if groupe in groupes:
    1357                      # on regarde si il faut envoyer des mails ou sms
    1358                      if user[3]==1:
    1359                          # on vérifie la syntaxe de l'adresse mail
    1360                          for adresse in user[1].split(','):
    1361                              r=re.match("""^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9]+)*$""",adresse)
    1362                              if r is not None:
    1363                                  # adresse valide : on envoie le mail
    1364                                  if adresse not in destinataires:
    1365                                      destinataires.append(adresse)
    1366          # envoi effectif des messages à tous les utilisateurs concernés
    1367          if destinataires != []:
    1368              self._sendmail(destinataires,subject + str(msg.keys()),"\n".join(msg.values()))
    1369
    1370 -    def xmlrpc_scan_timeouts(self,*args):
    1371          """vérifie toutes les x minutes si des serveurs ont dépassé leur timeout.
    1372          vérification toutes les 5 miuntes par défaut"""
    1373          # requete de récupération des données
    1374          try:
    1375              # premier démarrage de la boucle de vérification des contacts
    1376              if self.start_time is not None:
    1377                  # self.parent.scheduler.start()
    1378                  # on démarre également la vérification des paquets disponibles
    1379                  self.parent.maj_checker = AptChecker()
    1380                  query = "update serveurs set last_contact=%s where last_contact is not null and etat <> 2"
    1381                  self.dbpool.runOperation(query, (self.start_time,)).addCallbacks(lambda x : [1, "OK"],db_client_failed)
    1382                  reactor.callLater(5, self._scan_timeouts)
    1383          except:
    1384              traceback.print_exc()
    1385              return 0, "erreur de démarrage de la boucle de surveillance"
    1386          return 1,""
    1387
    1388 -    def _scan_timeouts(self):
    1389          reactor.callLater(self.scan_delay, self._scan_timeouts)
    1390          if config.LOG_ACTIONS:
    1391              log.msg('Recherche des pertes de contact')
    1392          query = """select serveurs.id,timeout,last_contact,serveurs.libelle, \
    1393          serveurs.rne,etablissements.libelle,modules.libelle,serveurs.etat \
    1394          from serveurs,etablissements,modules where timeout > 0 and last_contact is not null and \
    1395          serveurs.rne=etablissements.rne and module_actuel=modules.id"""
    1396          self.dbpool.runQuery(query).addCallbacks(self._scan_timeouts2,db_client_failed)
    1397
    1398 -    def _scan_timeouts2(self, data):
    1399          """vérifie si le dernier contact est moins ancien que le timeout du serveur.
    1400          """
    1401          # lancement du préchargement des configurations en tâche de fond au premier lancement
    1402          if self.start_time is not None and config.CREOLE_CACHE:
    1403              self.start_time = None
    1404              reactor.callInThread(self.update_creole, [serv[0] for serv in data])
    1405          # vérification des serveurs en timeout
    1406          cmds=uucp_pool._scan_pool()
    1407          d_list = []
    1408          for serveur in data:
    1409              # on lance la boucle de vérification sans attendre le résultat
    1410              if config.USE_THREADS:
    1411                  def_check = threads.deferToThread(self.check_timeout, serveur)
    1412              else:
    1413                  def_check = defer.maybeDeferred(self.check_timeout, serveur)
    1414              d_list.append(def_check)
    1415          d = defer.DeferredList(d_list, consumeErrors=True)
    1416          d.addCallback(self._send_alertes)
    1417
    1418 -    def _send_alertes(self, results):
    1419          erreurs={}
    1420          reprises={}
    1421          bloquages={}
    1422          debloquages={}
    1423          # collecte des résultats pour chaque serveur
    1424          for success, data in results:
    1425              if success:
    1426                  erreurs.update(data[0])
    1427                  reprises.update(data[1])
    1428                  bloquages.update(data[2])
    1429                  debloquages.update(data[3])
    1430              else:
    1431                  log.msg("! Erreur lors de la vérification du timeout d'un serveur : %s" \
    1432                          % str(data.getErrorMessage()))
    1433          self._send_alerte("commandes non lancées : ",bloquages)
    1434          self._send_alerte("commandes débloquées : ",debloquages)
    1435          self._send_alerte("perte de contact : ",erreurs)
    1436          self._send_alerte("reprise du contact : ",reprises)
    1437
    1438 -    def check_timeout(self, serveur):
    1439          """vérifie si un serveur a dépassé le délai de connexion autorisé
    1440          """
    1441          erreurs={}
    1442          reprises={}
    1443          bloquages={}
    1444          debloquages={}
    1445          # calcul du temps écoulé depuis le dernier contact (en secondes)
    1446          serv = self.parent.s_pool[int(serveur[0])]
    1447          params = {'timeout':[-2, ""]}
    1448          last = float(serveur[2])
    1449          delta = float(time.time()) - last
    1450          try:
    1451              etat_actuel = int(serveur[7])
    1452          except:
    1453              etat_actuel = 1
    1454          # on regarde si on a dépassé le timeout
    1455          try:
    1456              timeout = int(serveur[1])
    1457          except:
    1458              pass
    1459          else:
    1460              params['timeout'] = [1, time.ctime(last)]
    1461              # on laisse un délai de 2x le délai de connexion + 4 minutes avant de lever une alerte
    1462              # (on autorise de rater une connexion)
    1463              max_delay = int(timeout) * 2 + 240
    1464              if ( delta > max_delay ) and timeout != 0:
    1465                  params['timeout'][0]=0
    1466                  if etat_actuel != 2:
    1467                      # on prévient les utilisateurs concernés si ce n'est pas déjà fait
    1468                      reactor.callFromThread(log.msg, "timeout du serveur %s" % serveur[0])
    1469                      serv.set_status(2)
    1470                      # construction du message d'erreur
    1471                      if serv.no_alert == False:
    1472                          subject = """perte du contact : serveur(s) %s (%s)""" % (serveur[3],serveur[4])
    1473                          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))
    1474                          # ajout de l'alerte
    1475                          erreurs[serveur[0]]=msg
    1476              else:
    1477                  if etat_actuel == 2:
    1478                      # on était en timeout auparavant
    1479                      serv.set_status(1)
    1480                      if serv.no_alert == False and timeout != 0:
    1481                          subject = """reprise du contact : serveur(s) %s (%s)""" % (serveur[3],serveur[4])
    1482                          msg = """reprise du contact avec le serveur n°%s - %s (%s) de l'établissement %s (%s) : %s""" % \
    1483                          (serveur[0],serveur[3],serveur[6],serveur[4],serveur[5],time.ctime(last))
    1484                          reprises[serveur[0]]=msg
    1485
    1486                  # vérification de la bonne exécution des commandes
    1487                  id_uucp = serveur[4]+"-"+str(serveur[0])
    1488                  old_cmds = uucp_pool.check_timeout(max_delay, id_uucp)
    1489                  if old_cmds != {} and timeout != 0:
    1490                      if etat_actuel not in [3,4]:
    1491                          # mail pour le bloquage des commandes en attente
    1492                          if serv.no_alert == False:
    1493                              msg = """commandes bloquées en attente pour le serveur n°%s - %s (%s) de l'établissement %s (%s)
    1494  Vous pouvez afficher les logs de transfert UUCP sur ce serveur à l'aide de la commande uulog"""
    1495                              bloquages[serveur[0]] = msg % (serveur[0],serveur[3],serveur[6],serveur[4],serveur[5])
    1496                          if etat_actuel == 0:
    1497                              # bloquage + erreur agents
    1498                              serv.set_status(4)
    1499                          else:
    1500                              # bloquage
    1501                              serv.set_status(3)
    1502                  elif etat_actuel in [3,4]:
    1503                      # les commandes sont débloquées
    1504                      if serv.no_alert == False and timeout != 0:
    1505                          msg = """débloquage des commandes (reprise d'activité uucp) pour le serveur n°%s - %s (%s) de l'établissement %s (%s)"""
    1506                          debloquages[serveur[0]] = msg % (serveur[0],serveur[3],serveur[6],serveur[4],serveur[5])
    1507                      if etat_actuel == 4:
    1508                          # erreur agents
    1509                          serv.set_status(0)
    1510                      else:
    1511                          # aucune erreur
    1512                          serv.set_status(1)
    1513
    1514          # mise à jour du champ params du serveur
    1515          serv.maj_params(params)
    1516          return erreurs, reprises, bloquages, debloquages
    1517
    1518 -    def update_creole(self, serveurs):
    1519          # initialisation du premier serveur dans la liste
    1520          log.msg("Début de mise en cache des configurations des serveurs")
    1521          max_serv = len(serveurs)
    1522          for num_serv, serveur in enumerate(serveurs):
    1523              if not reactor.running:
    1524                  # On vérifie d'abord si le réacteur principal est toujours lancé
    1525                  # (l'arrêt idu réacteur n'arrête pas le thread)
    1526                  break
    1527              # lancement du chargement dans un Deffered (on n'attend pas le résultat)
    1528              def_upd = defer.Deferred()
    1529              def_upd.addCallback(self._update_creole, max_serv, num_serv)
    1530              def_upd.callback(serveur)
    1531          log.msg("Fin de mise en cache des configurations")
    1532
    1533 -    def _update_creole(self, serveur, nb_serv, current):
    1534          id_serv = int(serveur)
    1535          try:
    1536              serv = self.parent.s_pool[id_serv]
    1537              # si les dictonnaires du module du serveur est géré par dictpool,
    1538              # on vérifie que tous les liens sont bien créés
    1539              if self.parent.dictpool.check_module(serv.id_mod):
    1540                  self.parent.dictpool.check_dirs(serv)
    1541              if serv.dico is None:
    1542                  serv.get_config('modif_config')
    1543              if divmod(current, 50)[1] == 0 and current != 0:
    1544                  # affichage d'un message tous les 50 serveur et en fin de chargement
    1545                  log.msg("Mise en cache des configurations : %d/%d effectué" % (current, nb_serv))
    1546          except Exception, e:
    1547              log.msg("Erreur de lecture de la configuration du serveur %s (%s)" % (str(id_serv), str(e)))
    1548
    1549 -    def xmlrpc_get_actions(self,cred_user,id_serveur):
    1550          """retourne la liste des actions uucp en attente"""
    1551          # on vérifie l'existence du serveur dans la base
    1552          try:
    1553              id_serveur = int(id_serveur)
    1554              serv = self.parent.s_pool.get(cred_user, id_serveur)
    1555          except (KeyError, ValueError):
    1556              return 0, u("serveur inconnu dans la base zephir")
    1557          else:
    1558              id_uucp = str(serv.get_rne()) + '-' + str(id_serveur)
    1559              # construction de la commande
    1560              try:
    1561                  cmds=uucp_pool.list_cmd(id_uucp)[id_uucp]
    1562              except:
    1563                  cmds={}
    1564              try:
    1565                  files=uucp_pool.list_files(id_uucp)[id_uucp]
    1566              except:
    1567                  files={}
    1568              return 1,u([cmds,files])
    1569
    1570 -    def xmlrpc_check_queue(self,cred_user,id_serveur):
    1571          """indique à un serveur si il doit ou non effectuer des actions
    1572          """
    1573          # on vérifie l'existence du serveur dans la base
    1574          try:
    1575              id_serveur = int(id_serveur)
    1576              serv = self.parent.s_pool.get(cred_user, id_serveur)
    1577          except (KeyError, ValueError):
    1578              return 0, u("serveur inconnu dans la base zephir")
    1579          else:
    1580              id_uucp = str(serv.get_rne()) + '-' + str(id_serveur)
    1581              # on commence par mettre à jour le pool uucp
    1582              cmds=uucp_pool._scan_pool()
    1583              if len(uucp_pool.pool[id_uucp]) > 0:
    1584                  return 1, True
    1585              else:
    1586                  return 1, False
    1587
    1588 -    def xmlrpc_purge_actions(self,cred_user,serveurs,id_tache=None):
    1589          """annule toutes les actions en attente sur un/plusieurs serveur(s)"""
    1590          # on vérifie l'existence du serveur dans la base
    1591          try:
    1592              for id_serveur in serveurs:
    1593                  id_serveur = int(id_serveur)
    1594                  assert self.parent.s_pool.has_key(id_serveur)
    1595          except (KeyError, ValueError):
    1596              return 0, u("serveur inconnu dans la base zephir")
    1597          else:
    1598              for id_serveur in serveurs:
    1599                  rne = self.parent.s_pool.get(cred_user,int(id_serveur)).get_rne()
    1600                  id_uucp = str(rne) + '-' + str(id_serveur)
    1601                  # on regarde si un transfert est lié à cette action (configure)
    1602                  if id_tache is None:
    1603                      try:
    1604                          uucp_pool.flush([id_uucp])
    1605                      except UUCPError, e:
    1606                          return 0, u("erreur de purge des commandes : %" % str(e))
    1607                  else:
    1608                      try:
    1609                          uucp_pool.remove_cmd(id_uucp,int(id_tache))
    1610                      except UUCPError, e:
    1611                          return 0, u("Erreur de supression de la commande uucp : %" %str(e))
    1612                      except KeyError:
    1613                          pass
    1614
    1615          return 1,"OK"
    1616