1
2
3
4
5
6
7
8
9
10
11
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','.bash_history','dead.letter']
23
24
25
26
27
28
29 COMMANDS = {"zephir_client save_files": ("Sauvegarde complète", True, False),
30 "zephir_client save_files 0": ("Sauvegarde (complète)", True, False),
31 "zephir_client save_files 1": ("Sauvegarde (configuration)", True, False),
32 "zephir_client save_files 2": ("Sauvegarde (configuration/patchs/dicos)", True, False),
33 "zephir_client save_files 3": ("Sauvegarde (fichiers divers)", True, False),
34 "zephir_client maj_auto": ("Mise à jour", True, False),
35 "zephir_client maj_auto E": ("Mise à jour complète", True, False),
36 "zephir_client maj_client": ("Mise à jour de zephir-client", True, False),
37 "zephir_client download_upgrade": ("Préchargement des paquets (Upgrade-Auto)", True, False),
38 "zephir_client configure": ("Envoi de configuration", False, False),
39 "zephir_client reboot": ("Redémarrage du serveur", True, False),
40 "zephir_client service_restart": ("Redémarrage du service", True, False),
41 "zephir_client reconfigure": ("Reconfiguration", True, False),
42 "zephir_client update_key regen_certs": ("Renouvellement des clés d'enregistrement et certificats ssl", False, False),
43 "zephir_client update_key": ("Renouvellement des clés d'enregistrement", False, False),
44 "zephir_client update_replication": ("Regénération de la configuration de réplication LDAP", False, False),
45 "zephir_client change_ip": ("Préparation au changement d'adresse de zephir", False, False),
46 "zephir_client purge_ip": ("Annulation du changement d'adresse de zephir", True, False),
47 "zephir_client import_aaf": ("Prise en compte des fichiers d'import AAF", False, True),
48 }
49
51
52 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','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']
53
54
56 result=0
57 digits = range(len(chaine))
58
59 digits.reverse()
60 for i in range(len(chaine)):
61
62 digit = NUMBERS.index(chaine[digits[i]])
63
64 result = result + digit * len(NUMBERS).__pow__(i)
65 return result
66
68
69 timeout = 0
70 while os.path.isfile(LOCK):
71
72 timeout += 1
73
74 if timeout > 10:
75
76 raise UUCPError("Problème d'accès concurrent, fichier %s présent" % LOCK)
77 time.sleep(0.5)
78
79 lock=file(LOCK,"w")
80 lock.close()
81
83
84 if os.path.isfile(LOCK):
85 os.unlink(LOCK)
86
88 """wrapper d'uucp pour permettre la gestion des files dans zephir"""
89
91 """initialisation de l'objet"""
92 self.peers_ori=peers
93 self.pool={}
94 self._scan_pool()
95
97 """crée la liste d'attente en mémoire"""
98
99
100 if peer is not None:
101 peers = [peer]
102 else:
103 if self.peers_ori is None:
104 peers = os.listdir(UUCP_DIR)
105 for peer in IGNORE_LIST:
106 if peer in peers:
107 peers.remove(peer)
108 else:
109 peers = self.peers_ori
110
111 for peer in peers:
112
113 peer_dir = os.path.abspath(os.path.join(UUCP_DIR, peer))
114
115 lst={}
116 if os.path.isdir(os.path.join(peer_dir, "C.")):
117 for fic in os.listdir(os.path.join(peer_dir, "C.")):
118
119 date_creat = os.stat(os.path.join(peer_dir, "C.", fic)).st_ctime
120 f=file(os.path.join(peer_dir, "C.", fic))
121 l=f.read().strip().split('\n')[0]
122 f.close()
123
124
125
126
127 args=l.split()[1]
128 script=l.split()[5]
129 seq_number=convert_num(script[-4:])
130
131 type_cmd = "transfert"
132 orig_cmd = ""
133 if args.startswith("D.X"):
134 type_cmd = "execute"
135
136 f=file(os.path.join(peer_dir, "D.X", script))
137 l=f.read().strip().split('\n')
138 f.close()
139 for line in l:
140 line = line.strip()
141 if line[:2] == "C ":
142 args = line[2:]
143 orig_cmd = line[2:]
144
145 cmds = COMMANDS.keys()
146 cmds.sort(reverse=True)
147 for cmd in cmds:
148 if line[2:].startswith(cmd):
149 args = line[2:].replace(cmd, COMMANDS[cmd][0])
150 break
151
152 lst[seq_number]=(type_cmd,args,script,fic,date_creat,orig_cmd)
153
154 self.pool[peer]=lst
155
156
158 """met en place une commande distante"""
159 peer_dir = os.path.abspath(os.path.join(UUCP_DIR, peer))
160 get_lock()
161
162 self._scan_pool(peer)
163 used_grades = []
164 if peer in self.pool:
165 cmd_files = [uucmd[3] for uucmd in self.pool[peer].values()]
166 for uucmd in cmd_files:
167 cmd_grade = convert_num(uucmd[2])
168 if cmd_grade not in used_grades:
169 used_grades.append(cmd_grade)
170 if used_grades != []:
171 new_grade = max(used_grades) + 1
172 else:
173
174 new_grade = 24
175
176 if new_grade >= len(NUMBERS):
177 new_grade = NUMBERS[-1]
178 else:
179 new_grade = NUMBERS[new_grade]
180 old_calls = []
181 if commande in COMMANDS and COMMANDS[commande][1] == False:
182
183 for old_cmd in self.list_cmd(peer)[peer]:
184
185 if self.pool[peer][old_cmd[0]][5] == commande:
186 old_calls.append((old_cmd[0], COMMANDS[commande][2]))
187
188 cmd = "%s -g %s -r '%s!%s >%s!%s'" % (CMD_UUX, new_grade, peer, commande, peer, LOG_FILE)
189 try:
190
191 res=os.system(cmd)
192
193 if res == 0:
194
195 tempbuf=tempfile.mktemp()
196 os.system("/bin/ls -t %s > %s" % (os.path.join(peer_dir, "C./"), tempbuf))
197 output=file(tempbuf)
198 res2=output.read()
199 output.close()
200 os.unlink(tempbuf)
201
202 filename = res2.split()[0]
203
204 f=file(os.path.join(peer_dir, "C.", filename))
205 l=f.read().strip().split('\n')[0]
206 f.close()
207 script = l.split()[5]
208
209 seq_num=convert_num(script[-4:])
210 if not self.pool.has_key(peer):
211 self.pool[peer]={}
212 date_creat = os.stat(os.path.join(peer_dir, "C.", filename)).st_ctime
213 self.pool[peer][seq_num]=("execute", commande, script, filename, date_creat, commande)
214
215 free_lock()
216
217 if old_calls != []:
218 for call_id, keep_transfert in old_calls:
219 self.remove_cmd(peer, call_id, keep_transfert)
220 return seq_num
221 else:
222 free_lock()
223 raise Exception("uux2 a retourné une erreur")
224 except Exception,e:
225 free_lock()
226
227 raise UUCPError("""erreur lors de la préparation de l'exécution de %s : %s""" % (commande, str(e)))
228
229 - def add_file(self,peer,fichier,destination="~"):
230 """prépare l'envoi d'un fichier"""
231 peer_dir = os.path.abspath(os.path.join(UUCP_DIR, peer))
232
233 old_trans = []
234 for transfert in self.list_files(peer)[peer]:
235 if transfert[1] == fichier:
236 old_trans.append(transfert[0])
237
238 cmd = "%s -r %s %s\\!%s" % (CMD_UUCP,fichier,peer,destination)
239 get_lock()
240 try:
241
242 res=os.system(cmd)
243
244 if res == 0:
245
246 tempbuf=tempfile.mktemp()
247 os.system("/bin/ls -t %s > %s" % (os.path.join(peer_dir, "C./"), tempbuf))
248 output=file(tempbuf)
249 res2=output.read()
250 output.close()
251 os.unlink(tempbuf)
252
253 filename = res2.split()[0]
254
255 f=file(os.path.join(peer_dir, "C.", filename))
256 l=f.read().strip().split('\n')[0]
257 f.close()
258 script = l.split()[5]
259
260 seq_num=convert_num(script[-4:])
261 if not self.pool.has_key(peer):
262 self.pool[peer]={}
263 date_creat = os.stat(os.path.join(peer_dir, "C.", filename)).st_ctime
264 self.pool[peer][seq_num] = ("transfert",fichier,script,filename,time.time(),date_creat,fichier)
265
266 free_lock()
267
268 if old_trans != []:
269 for trans_id in old_trans:
270 self.remove_cmd(peer, trans_id)
271 return 0
272 else:
273 free_lock()
274 raise UUCPError("""echec à l'exécution de uucp""")
275 except Exception,e:
276 free_lock()
277 raise UUCPError("""erreur lors de la préparation du transfert de %s : %s""" % (fichier,e))
278
280 """fonction interne qui liste les actions d'un type particulier"""
281 cmds = {}
282
283 for peer in peers:
284 cmds[peer] = []
285 if not self.pool.has_key(peer):
286 continue
287
288 numeros = self.pool[peer].keys()
289 numeros.sort()
290 for n in numeros:
291 action = self.pool[peer][n]
292
293 if action[0] == type_cmd:
294
295 cmds[peer].append((n, action[1]))
296 return cmds
297
299 """vérifie si il existe des commandes plus anciennes
300 que max_time pour un serveur donné (ou tous)
301 @param max_time: age maximum en seconde accepté pour une commande
302 retourne un dictionnaire {serveur:liste des ids de commande trop anciens}"""
303 dic_res = {}
304 if peer is not None:
305 peers=[peer]
306 else:
307 self._scan_pool()
308 peers=self.pool.keys()
309 for serveur in peers:
310 timeouts = []
311 if self.pool.has_key(serveur):
312 for seq_num, data in self.pool[serveur].items():
313 test_time = time.localtime(float(data[-2] + max_time))
314
315 if test_time < time.localtime():
316
317 timeouts.append((seq_num, time.ctime(data[-2])))
318 if timeouts != []:
319 dic_res[serveur] = timeouts
320 return dic_res
321
323 """renvoie la liste des commandes en attente"""
324 if peer is not None:
325 self._scan_pool(peer)
326 peers=[peer]
327 else:
328 self._scan_pool()
329 peers=self.pool.keys()
330 return self._create_liste("execute",peers)
331
333 """renvoie la liste des transferts en attente"""
334 if peer is not None:
335 self._scan_pool(peer)
336 peers=[peer]
337 else:
338 self._scan_pool()
339 peers=self.pool.keys()
340 return self._create_liste("transfert",peers)
341
342 - def remove_cmd(self, peer, num_cmd, keep_transfert=False):
343 """supprime une commande ou un transfert"""
344 num_cmd = int(num_cmd)
345 type_cmd,fichier,script,filename,date_creat,fichier_orig = self.pool[peer][num_cmd]
346 peer_dir = os.path.abspath(os.path.join(UUCP_DIR, peer))
347 get_lock()
348
349 try:
350 if os.path.isfile(os.path.join(peer_dir, 'C.', filename)):
351 os.unlink(os.path.join(peer_dir, 'C.', filename))
352 if type_cmd == "transfert":
353
354 if os.path.isfile(os.path.join(peer_dir, 'D.', script)):
355 os.unlink(os.path.join(peer_dir, 'D.', script))
356 else:
357
358 if os.path.isfile(os.path.join(peer_dir, 'D.X', script)):
359 os.unlink(os.path.join(peer_dir, 'D.X', script))
360
361 free_lock()
362 except:
363
364 free_lock()
365 raise UUCPError("erreur lors de la suppression des fichiers")
366
367 del(self.pool[peer][num_cmd])
368
369 if fichier_orig in COMMANDS and COMMANDS[fichier_orig][1] == False and not keep_transfert:
370 previous_cmd = self.pool[peer].get(num_cmd-1,[''])
371 if previous_cmd[0] == "transfert":
372 self.remove_cmd(peer, num_cmd-1)
373 return 0
374
375 - def flush(self,peers=None):
376 """supprime toute la file d'attente"""
377 if peers is None:
378 for i in os.listdir(UUCP_DIR):
379 if i not in IGNORE_LIST:
380 try:
381
382 if os.path.isdir(os.path.join(UUCP_DIR, i)):
383 shutil.rmtree(os.path.join(UUCP_DIR, i))
384 self.pool[i]={}
385 except:
386 raise UUCPError("""erreur de suppression de la file d'attente de %s""" % i)
387 else:
388 try:
389 for peer in peers:
390 if os.path.isdir(os.path.join(UUCP_DIR, peer)):
391 shutil.rmtree(os.path.join(UUCP_DIR, peer))
392 self.pool[peer]={}
393 except:
394 raise UUCPError("""erreur de supression de la file d'attente""")
395 return 0
396
397 uucp_pool = UUCP()
398
399 if __name__ == '__main__':
400 peers = ["0210056X-1","0210056X-2","0210056X-3","0210056X-4","0210056X-5"]
401 uucp=UUCP(peers)
402 peer = ""
403 while not peer in peers:
404 peer = raw_input("\nvoir la file d'attente de : ")
405 print "\ncommandes :\n"
406 for cmd in uucp.list_cmd(peer)[peer]:
407 print " "+str(cmd)
408
409 print "\ntransferts :\n"
410 for cmd in uucp.list_files(peer)[peer]:
411 print " "+str(cmd)
412 print '\n'
413