33import os
44import glob
55import signal
6- import tarfile
76import tempfile
87from pathlib import Path
98from collections import deque
109
1110from pbench .common .exceptions import (
1211 BadDate ,
1312 UnsupportedTarballFormat ,
14- SosreportHostname ,
1513 BadMDLogFormat ,
1614 TemplateError ,
1715)
@@ -37,6 +35,23 @@ class SigTermException(Exception):
3735 pass
3836
3937
38+ class ErrorCode :
39+ def __init__ (self , name , value , tarball_error , message ):
40+ self .name = name
41+ self .value = value
42+ self .success = value == 0
43+ self .tarball_error = tarball_error
44+ self .message = message
45+
46+
47+ class Errors :
48+ def __init__ (self , * codes ):
49+ self .errors = {code .name : code for code in codes }
50+
51+ def __getitem__ (self , key ):
52+ return self .errors [key ]
53+
54+
4055def _count_lines (fname ):
4156 """Simple method to count the lines of a file.
4257 """
@@ -49,7 +64,38 @@ def _count_lines(fname):
4964
5065
5166class Index :
52- """class used to collect tarballs and index them"""
67+ """ class used to collect tarballs and index them
68+
69+ Status codes used by es_index and the error below are defined to
70+ maintain compatibility with the previous code base when pbench-index
71+ was a bash script.
72+ """
73+
74+ error_code = Errors (
75+ ErrorCode ("OK" , 0 , None , "Successful completion" ),
76+ ErrorCode ("OP_ERROR" , 1 , False , "Operational error while indexing" ),
77+ ErrorCode ("CFG_ERROR" , 2 , False , "Configuration file not specified" ),
78+ ErrorCode ("BAD_CFG" , 3 , False , "Bad configuration file" ),
79+ ErrorCode (
80+ "TB_META_ABSENT" , 4 , True , "Tar ball does not contain a metadata.log file" ,
81+ ),
82+ ErrorCode ("BAD_DATE" , 5 , True , "Bad start run date value encountered" ),
83+ ErrorCode ("FILE_NOT_FOUND_ERROR" , 6 , True , "File Not Found error" ),
84+ ErrorCode ("BAD_METADATA" , 7 , True , "Bad metadata.log file encountered" ),
85+ ErrorCode (
86+ "MAPPING_ERROR" ,
87+ 8 ,
88+ False ,
89+ "Error reading a mapping file for Elasticsearch templates" ,
90+ ),
91+ ErrorCode (
92+ "TEMPLATE_CREATION_ERROR" ,
93+ 9 ,
94+ False ,
95+ "Error creating one of the Elasticsearch templates" ,
96+ ),
97+ ErrorCode ("GENERIC_ERROR" , 12 , False , "Unexpected error encountered" ),
98+ )
5399
54100 def __init__ (self , name , options , idxctx , incoming , archive , qdir ):
55101
@@ -80,6 +126,7 @@ def collect_tb(self):
80126 # find -L $ARCHIVE/*/$linksrc -name '*.tar.xz' -printf "%s\t%p\n" 2>/dev/null | sort -n > $list
81127 tarballs = []
82128 idxctx = self .idxctx
129+ error_code = self .error_code
83130 try :
84131 tb_glob = os .path .join (self .archive , "*" , self .linksrc , "*.tar.xz" )
85132 for tb in glob .iglob (tb_glob ):
@@ -119,26 +166,45 @@ def collect_tb(self):
119166 raise
120167 except Exception :
121168 idxctx .logger .exception (
122- "Unexpected error encountered generating list"
123- " of tar balls to process"
169+ "{} generating list of tar balls to process" ,
170+ error_code [ "GENERIC_ERROR" ]. message ,
124171 )
125172 # tuple to return the status and return value
126- return (12 , [])
173+ return (error_code [ "GENERIC_ERROR" ]. value , [])
127174 else :
128175 if not tarballs :
129176 idxctx .logger .info ("No tar balls found that need processing" )
130- return (0 , [])
131177
132- return (0 , tarballs )
178+ return (error_code ["OK" ].value , sorted (tarballs ))
179+
180+ def emit_error (self , logger_method , error , exception ):
181+ """Helper method to write a log message in a standard format from an error code
182+
183+ Args
184+ logger_method -- Reference to a method of a Python logger object,
185+ like idxctx.logger.warning
186+ error -- An error code name from the Errors collection, like "OK"
187+ exception -- the original exception leading to the error
188+
189+ Returns
190+ Relevant error_code object
191+
192+ Although all log messages will appear to have originated from this method,
193+ the origin can easily be identified from the error code value, and this
194+ interface provides simplicity and consistency.
195+ """
196+ ec = self .error_code [error ]
197+ logger_method ("{}: {}" , ec .message , exception )
198+ return ec
133199
134200 def process_tb (self , tarballs ):
135201 """Process Tarballs For Indexing and creates report
136202
137203 "tarballs" - List of tarball, it is the second value of
138204 the tuple returned by collect_tb() """
139-
140- # We always process the smallest tar balls first.
205+ res = 0
141206 idxctx = self .idxctx
207+ error_code = self .error_code
142208
143209 tb_deque = deque (sorted (tarballs ))
144210
@@ -152,8 +218,7 @@ def process_tb(self, tarballs):
152218 idxctx .logger .debug ("update_templates [start]" )
153219 idxctx .templates .update_templates (idxctx .es )
154220 except TemplateError as e :
155- idxctx .logger .error ("update_templates [end], error {}" , repr (e ))
156- res = 9
221+ res = self .emit_error (idxctx .logger .error , "TEMPLATE_CREATION_ERROR" , e )
157222 except SigTermException :
158223 # Re-raise a SIGTERM to avoid it being lumped in with general
159224 # exception handling below.
@@ -162,14 +227,14 @@ def process_tb(self, tarballs):
162227 idxctx .logger .exception (
163228 "update_templates [end]: Unexpected template" " processing error"
164229 )
165- res = 12
230+ res = error_code [ "GENERIC_ERROR" ]
166231 else :
167232 idxctx .logger .debug ("update_templates [end]" )
168- res = 0
233+ res = error_code [ "OK" ]
169234
170- if res != 0 :
235+ if not res . success :
171236 # Exit early if we encounter any errors.
172- return res
237+ return res . value
173238
174239 report = Report (
175240 idxctx .config ,
@@ -192,7 +257,7 @@ def process_tb(self, tarballs):
192257 raise
193258 except Exception :
194259 idxctx .logger .error ("Failed to post initial report status" )
195- return 12
260+ return error_code [ "GENERIC_ERROR" ]. value
196261 else :
197262 idxctx .set_tracking_id (tracking_id )
198263
@@ -289,37 +354,30 @@ def sighup_handler(*args):
289354 # Turn off the SIGINT handler when not indexing.
290355 signal .signal (signal .SIGINT , signal .SIG_IGN )
291356 except UnsupportedTarballFormat as e :
292- idxctx .logger .warning ("Unsupported tar ball format: {}" , e )
293- tb_res = 4
357+ tb_res = self .emit_error (
358+ idxctx .logger .warning , "TB_META_ABSENT" , e
359+ )
294360 except BadDate as e :
295- idxctx .logger .warning ("Bad Date: {!r}" , e )
296- tb_res = 5
361+ tb_res = self .emit_error (
362+ idxctx .logger .warning , "BAD_DATE" , e
363+ )
297364 except FileNotFoundError as e :
298- idxctx .logger .warning ("No such file: {}" , e )
299- tb_res = 6
300- except BadMDLogFormat as e :
301- idxctx .logger .warning (
302- "The metadata.log file is curdled in" " tar ball: {}" , e
365+ tb_res = self .emit_error (
366+ idxctx .logger .warning , "FILE_NOT_FOUND_ERROR" , e
303367 )
304- tb_res = 7
305- except SosreportHostname as e :
306- idxctx .logger .warning ("Bad hostname in sosreport: {}" , e )
307- tb_res = 10
308- except tarfile .TarError as e :
309- idxctx .logger .error (
310- "Can't unpack tar ball into {}: {}" ,
311- ptb .extracted_root ,
312- e ,
368+ except BadMDLogFormat as e :
369+ tb_res = self .emit_error (
370+ idxctx .logger .warning , "BAD_METADATA" , e
313371 )
314- tb_res = 11
315372 except SigTermException :
316373 idxctx .logger .exception (
317374 "Indexing interrupted by SIGTERM, terminating"
318375 )
319376 break
320377 except Exception as e :
321- idxctx .logger .exception ("Other indexing error: {}" , e )
322- tb_res = 12
378+ tb_res = self .emit_error (
379+ idxctx .logger .exception , "GENERIC_ERROR" , e
380+ )
323381 else :
324382 beg , end , successes , duplicates , failures , retries = es_res
325383 idxctx .logger .info (
@@ -334,7 +392,7 @@ def sighup_handler(*args):
334392 failures ,
335393 retries ,
336394 )
337- tb_res = 1 if failures > 0 else 0
395+ tb_res = error_code [ "OP_ERROR" if failures > 0 else "OK" ]
338396 try :
339397 ie_len = ie_filepath .stat ().st_size
340398 except FileNotFoundError :
@@ -378,7 +436,7 @@ def sighup_handler(*args):
378436 # `linkerrdest` for later retry.
379437 controller_path = linksrc_dir .parent
380438
381- if tb_res == 0 :
439+ if tb_res is error_code [ "OK" ] :
382440 idxctx .logger .info (
383441 "{}: {}/{}: success" ,
384442 idxctx .TS ,
@@ -391,7 +449,7 @@ def sighup_handler(*args):
391449 rename_tb_link (
392450 tb , Path (controller_path , self .linkdest ), idxctx .logger
393451 )
394- elif tb_res == 1 :
452+ elif tb_res is error_code [ "OP_ERROR" ] :
395453 idxctx .logger .warning (
396454 "{}: index failures encountered on {}" , idxctx .TS , tb
397455 )
@@ -402,25 +460,28 @@ def sighup_handler(*args):
402460 Path (controller_path , f"{ self .linkerrdest } .1" ),
403461 idxctx .logger ,
404462 )
405- elif tb_res in (2 , 3 ):
463+ elif tb_res in (error_code [ "CFG_ERROR" ], error_code [ "BAD_CFG" ] ):
406464 assert False , (
407465 f"Logic Bomb! Unexpected tar ball handling "
408- f"result status { tb_res :d} for tar ball { tb } "
466+ f"result status { tb_res . value :d} for tar ball { tb } "
409467 )
410- elif tb_res >= 4 and tb_res <= 11 :
468+ elif tb_res . tarball_error :
411469 # # Quietly skip these errors
412470 with skipped .open (mode = "a" ) as fp :
413471 print (tb , file = fp )
414472 rename_tb_link (
415473 tb ,
416- Path (controller_path , f"{ self .linkerrdest } .{ tb_res :d} " ),
474+ Path (
475+ controller_path ,
476+ f"{ self .linkerrdest } .{ tb_res .value :d} " ,
477+ ),
417478 idxctx .logger ,
418479 )
419480 else :
420481 idxctx .logger .error (
421482 "{}: index error {:d} encountered on {}" ,
422483 idxctx .TS ,
423- tb_res ,
484+ tb_res . value ,
424485 tb ,
425486 )
426487 with erred .open (mode = "a" ) as fp :
@@ -471,11 +532,11 @@ def sighup_handler(*args):
471532 # exception handling below.
472533 raise
473534 except Exception :
474- idxctx .logger .exception ("Unexpected setup error" )
475- res = 12
535+ idxctx .logger .exception (error_code [ "GENERIC_ERROR" ]. message )
536+ res = error_code [ "GENERIC_ERROR" ]
476537 else :
477538 # No exceptions while processing tar ball, success.
478- res = 0
539+ res = error_code [ "OK" ]
479540 finally :
480541 if idxctx :
481542 idxctx .dump_opctx ()
@@ -541,4 +602,4 @@ def sighup_handler(*args):
541602 except Exception :
542603 pass
543604
544- return res
605+ return res . value
0 commit comments