zephir.backend.serveurs_rpc

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

# Source Code for Module zephir.backend.serveurs_rpc

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