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

Source Code for Module zephir.backend.uucp_utils

  1  #! /usr/bin/env python 
  2  # -*- coding: UTF-8 -*- 
  3  ########################################################################### 
  4  # Eole NG - 2007   
  5  # Copyright Pole de Competence Eole  (Ministere Education - Academie Dijon) 
  6  # Licence CeCill  cf /root/LicenceEole.txt 
  7  # eole@ac-dijon.fr  
  8  #   
  9  # uucp_utils.py 
 10  #   
 11  # fonctions utilitaires pour la gestion d'uucp 
 12  #        
 13  ########################################################################### 
 14   
 15  import os,time,shutil,tempfile 
 16   
 17  UUCP_DIR = "/var/spool/uucp" 
 18  CMD_UUX = "/usr/bin/uux2" 
 19  CMD_UUCP = "/usr/bin/uucp2" 
 20  LOG_FILE = "/tmp/rapport.zephir" 
 21  LOCK = "/var/spool/uucp/lock" 
 22  IGNORE_LIST = ['.ssh','.Status','.Temp','.Received'] 
 23   
 24  COMMANDS = {"zephir_client save_files":"Sauvegarde de configuration", 
 25              "zephir_client maj_auto":"Mise à jour", 
 26              "zephir_client maj_client":"Mise à jour de zephir-client", 
 27              "zephir_client configure":"Envoi de configuration", 
 28              "zephir_client reboot":"Redémarrage du serveur", 
 29              "zephir_client service_restart":"Redémarrage du service", 
 30              "zephir_client reconfigure":"Reconfiguration"} 
 31   
 32  UUCPError = 'UUCPError' 
 33       
 34   
 35  NUMBERS = ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"] 
 36   
 37  # fonction de conversion  
38 -def convert_num(chaine):
39 result=0 40 digits = range(len(chaine)) 41 # on parcourt la chaine en partant de la fin 42 digits.reverse() 43 for i in range(len(chaine)): 44 # valeur du digit en cours 45 digit = NUMBERS.index(chaine[digits[i]]) 46 # valeur * longueur_base^position 47 result = result + digit * len(NUMBERS).__pow__(i) 48 return result
49
50 -class UUCP:
51 """wrapper d'uucp pour permettre la gestion des files dans zephir""" 52
53 - def __init__(self,peers=None):
54 """initialisation de l'objet""" 55 self.peers_ori=peers 56 self.pool={} 57 self._scan_pool()
58
59 - def _scan_pool(self):
60 """crée la liste d'attente en mémoire""" 61 # on crée la liste des commandes et transferts actuels 62 # si pas de noms de machines spécifiées, on recherche dans tous les systèmes 63 if self.peers_ori is None: 64 peers = os.listdir(UUCP_DIR) 65 for peer in IGNORE_LIST: 66 if peer in peers: 67 peers.remove(peer) 68 else: 69 peers = self.peers_ori 70 # parcours de /var/spool/uucp 71 for peer in peers: 72 # répertoire uucp de ce correspondant 73 peer_dir = os.path.abspath(UUCP_DIR+os.sep+peer) 74 # liste des actions en attente 75 lst={} 76 if os.path.isdir(peer_dir+"/C."): 77 for fic in os.listdir(peer_dir+"/C."): 78 # on récupère la date de création de la commande (timestamp) 79 date_creat = os.stat(peer_dir+"/C./"+fic)[-1] 80 f=file(peer_dir+"/C./"+fic) 81 l=f.read().strip().split('\n')[0] 82 f.close() 83 # séparation des paramètres 84 # ex de lignes: 85 # S /var/lib/zephir/conf/0210056X/4/config-zephir.tar ~ root -Cd D.0008 0644 86 # S D.X0007 X.zephirN0007 root -C D.X0007 0666 87 args=l.split()[1] 88 script=l.split()[5] 89 seq_number=convert_num(script[-4:]) 90 # si on a une commande 91 type_cmd = "transfert" 92 if args.startswith("D.X"): 93 type_cmd = "execute" 94 # on regarde laquelle dans le fichier correspondat 95 f=file(peer_dir+"/D.X/"+script) 96 l=f.read().strip().split('\n') 97 f.close() 98 for line in l: 99 line = line.strip() 100 if line[:2] == "C ": 101 args = line[2:] 102 # on regarde si c'est une commande connue 103 for command, label in COMMANDS.items(): 104 if line[2:].startswith(command): 105 args = line[2:].replace(command, label) 106 break 107 108 lst[seq_number]=(type_cmd,args,script,fic,date_creat) 109 110 self.pool[peer]=lst
111 112
113 - def add_cmd(self,peer,commande):
114 """met en place une commande distante""" 115 peer_dir = os.path.abspath(UUCP_DIR+os.sep+peer) 116 # construction de l'appel à uux 117 cmd = "%s -r '%s!%s >%s!%s'" % (CMD_UUX,peer,commande,peer,LOG_FILE) 118 # on regarde si on a le droit d'écrire 119 timeout = 0 120 while os.path.isfile(LOCK): 121 # si non on attend la libération des ressources 122 timeout += 1 123 # si plus de 5 secondes d'attente, il y a surement un problème 124 if timeout > 10: 125 # print "Problème d'accès concurrent, fichier %s présent" % LOCK 126 raise UUCPError, "Problème d'accès concurrent, fichier %s présent" % LOCK 127 time.sleep(0.5) 128 # on bloque les autres appels à cette fonction en cas de 129 # demandes simultanées 130 lock=file(LOCK,"w") 131 lock.close() 132 try: 133 # appel systeme 134 res=os.system(cmd) 135 # on ajoute la commande à la liste des commandes de ce peer 136 if res == 0: 137 # recherche du fichier correspondant (dernier fichier créé dans "C.") 138 tempbuf=tempfile.mktemp() 139 os.system("/bin/ls -t %s" % peer_dir+"/C./ > %s" % tempbuf) 140 output=file(tempbuf) 141 res2=output.read() 142 output.close() 143 os.unlink(tempbuf) 144 # on récupère le nom du fichier le plus récent 145 filename = res2.split()[0] 146 # nom du script correspondant 147 f=file(peer_dir+"/C./"+filename) 148 l=f.read().strip().split('\n')[0] 149 f.close() 150 script = l.split()[5] 151 # on déduit le n° dans la file à partir du nom de script 152 seq_num=convert_num(script[-4:]) 153 if not self.pool.has_key(peer): 154 self.pool[peer]={} 155 self.pool[peer][seq_num]=("execute",commande,script,filename) 156 # on libère la ressource 157 os.unlink(LOCK) 158 return seq_num 159 else: 160 os.unlink(LOCK) 161 raise Exception("uux2 a retourné une erreur") 162 except Exception,e: 163 os.unlink(LOCK) 164 # print """erreur lors de la préparation de l'exécution de %s : %s""" % (commande,e) 165 raise UUCPError, """erreur lors de la préparation de l'exécution de %s : %s""" % (commande,str(e))
166
167 - def add_file(self,peer,fichier,destination="~"):
168 """prépare l'envoi d'un fichier""" 169 peer_dir = os.path.abspath(UUCP_DIR+os.sep+peer) 170 # construction de l'appel à uucp 171 cmd = "%s -r %s %s\\!%s" % (CMD_UUCP,fichier,peer,destination) 172 # on regarde si on a le droit d'écrire 173 timeout = 0 174 while os.path.isfile(LOCK): 175 # si non on attend la libération des ressources 176 timeout += 1 177 # si plus de 5 secondes d'attente, il y a surement un problème 178 if timeout > 10: 179 # print "Problème d'accès concurrent, fichier %s présent" % LOCK 180 raise UUCPError, "Problème d'accès concurrent, fichier %s présent" % LOCK 181 time.sleep(0.5) 182 # on bloque les autres appels à cette fonction en cas de 183 # demandes simultanées 184 lock=file(LOCK,"w") 185 lock.close() 186 try: 187 # appel systeme 188 res=os.system(cmd) 189 # on ajoute le transfert à la liste des transferts de ce peer 190 if res == 0: 191 # recherche du fichier correspondant 192 tempbuf=tempfile.mktemp() 193 os.system("/bin/ls -t %s" % peer_dir+"/C./ > %s" % tempbuf) 194 output=file(tempbuf) 195 res2=output.read() 196 output.close() 197 os.unlink(tempbuf) 198 # on récupère le nom du fichier le plus récent 199 filename = res2.split()[0] 200 # nom du script correspondant 201 f=file(peer_dir+"/C./"+filename) 202 l=f.read().strip().split('\n')[0] 203 f.close() 204 script = l.split()[5] 205 # on déduit le n° dans la file à partir du nom de script 206 seq_num=convert_num(script[-4:]) 207 if not self.pool.has_key(peer): 208 self.pool[peer]={} 209 self.pool[peer][seq_num]=("transfert",fichier,script,filename) 210 # on libère la ressource 211 os.unlink(LOCK) 212 return 0 213 else: 214 os.unlink(LOCK) 215 raise UUCPError, """echec à l'exécution de uucp""" 216 except Exception,e: 217 os.unlink(LOCK) 218 raise UUCPError, """erreur lors de la préparation du transfert de %s : %s""" % (fichier,e)
219
220 - def _create_liste(self,type_cmd,peers):
221 """fonction interne qui liste les actions d'un type particulier""" 222 cmds = {} 223 # pour chaque peer 224 for peer in peers: 225 cmds[peer] = [] 226 if not self.pool.has_key(peer): 227 continue 228 # on parcourt la liste des actions en attente 229 numeros = self.pool[peer].keys() 230 numeros.sort() 231 for n in numeros: 232 action=self.pool[peer][n] 233 # si c'est une commande distante 234 if action[0] == type_cmd: 235 # on l'ajoute à la liste 236 cmds[peer].append((n,action[1])) 237 return cmds
238
239 - def check_timeout(self,max_time,peer=None):
240 """vérifie si il existe des commandes plus anciennes 241 que max_time pour un serveur donné (ou tous) 242 @param max_time: age maximum en seconde accepté pour une commande 243 retourne un dictionnaire {serveur:liste des ids de commande trop anciens}""" 244 dic_res = {} 245 if peer is not None: 246 peers=[peer] 247 else: 248 self._scan_pool() 249 peers=self.pool.keys() 250 for serveur in peers: 251 timeouts = [] 252 if self.pool.has_key(serveur): 253 for seq_num, data in self.pool[serveur].items(): 254 test_time = time.localtime(float(data[-1] + max_time)) 255 # si timeout (date de création + délai > date actuelle) 256 if test_time < time.localtime(): 257 # on renvoie le n° de commande et sa date de création 258 timeouts.append((seq_num, time.ctime(data[-1]))) 259 if timeouts != []: 260 dic_res[serveur] = timeouts 261 return dic_res
262 263 264
265 - def list_cmd(self,peer=None):
266 """renvoie la liste des commandes en attente""" 267 if peer is not None: 268 peers=[peer] 269 else: 270 self._scan_pool() 271 peers=self.pool.keys() 272 return self._create_liste("execute",peers)
273
274 - def list_files(self,peer=None):
275 """renvoie la liste des transferts en attente""" 276 if peer is not None: 277 peers=[peer] 278 else: 279 self._scan_pool() 280 peers=self.pool.keys() 281 return self._create_liste("transfert",peers)
282
283 - def remove_cmd(self,peer,num_cmd):
284 """supprime une commande ou un transfert""" 285 type_cmd,fichier,script,filename,date_creat = self.pool[peer][int(num_cmd)] 286 peer_dir = os.path.abspath(UUCP_DIR+os.sep+peer) 287 # on regarde si on a le droit d'écrire 288 timeout = 0 289 while os.path.isfile(LOCK): 290 # si non on attend la libération des ressources 291 timeout += 1 292 # si plus de 5 secondes d'attente, il y a surement un problème 293 if timeout > 10: 294 # print "Problème d'accès concurrent, fichier %s présent" % LOCK 295 raise UUCPError, "Problème d'accès concurrent, fichier %s présent" % LOCK 296 time.sleep(0.5) 297 # on bloque les autres appels à cette fonction en cas de 298 # demandes simultanées 299 lock=file(LOCK,"w") 300 lock.close() 301 # supression du fichier correspondant dans C. 302 try: 303 os.unlink(peer_dir+'/C./'+filename) 304 if type_cmd == "transfert": 305 # supression de la copie du fichier dans D. 306 os.unlink(peer_dir+'/D./'+script) 307 else: 308 # supression du script correspondant dans D.X 309 os.unlink(peer_dir+'/D.X/'+script) 310 # on libère la ressource 311 os.unlink(LOCK) 312 except: 313 # print "erreur lors de la suppression des fichiers" 314 os.unlink(LOCK) 315 raise UUCPError, "erreur lors de la suppression des fichiers" 316 317 del(self.pool[peer][int(num_cmd)]) 318 return 0
319 320
321 - def flush(self,peers=None):
322 """supprime toute la file d'attente""" 323 if peers is None: 324 for i in os.listdir(UUCP_DIR): 325 if i not in IGNORE_LIST: 326 try: 327 # on supprime le répertoire d'échange 328 if os.path.isdir(UUCP_DIR+os.sep+i): 329 shutil.rmtree(UUCP_DIR+os.sep+i) 330 self.pool[i]={} 331 except: 332 raise UUCPError, """erreur de suppression de la file d'attente de %s""" % i 333 else: 334 try: 335 for peer in peers: 336 if os.path.isdir(UUCP_DIR+os.sep+peer): 337 shutil.rmtree(UUCP_DIR+os.sep+peer) 338 self.pool[peer]={} 339 except: 340 raise UUCPError, """erreur de supression de la file d'attente""" 341 return 0
342 343 uucp_pool = UUCP() 344 345 if __name__ == '__main__': 346 peers = ["0210056X-1","0210056X-2","0210056X-3","0210056X-4","0210056X-5"] 347 uucp=UUCP(peers) 348 peer = "" 349 while not peer in peers: 350 peer = raw_input("\nvoir la file d'attente de : ") 351 print "\ncommandes :\n" 352 for cmd in uucp.list_cmd(peer)[peer]: 353 print " "+str(cmd) 354 355 print "\ntransferts :\n" 356 for cmd in uucp.list_files(peer)[peer]: 357 print " "+str(cmd) 358 print '\n' 359