ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/CRAB/python/crab.py
Revision: 1.35
Committed: Tue Nov 8 13:25:22 2005 UTC (19 years, 5 months ago) by spiga
Content type: text/x-python
Branch: MAIN
CVS Tags: CRAB_1_0_2, CRAB_0_2_2
Changes since 1.34: +1 -1 lines
Log Message:
PostMortem with boss

File Contents

# User Rev Content
1 slacapra 1.27 #!/usr/bin/env python2.2
2 nsmirnov 1.1 from crab_help import *
3     from crab_util import *
4     from crab_exceptions import *
5     from crab_logger import Logger
6     from WorkSpace import WorkSpace
7     from JobDB import JobDB
8 nsmirnov 1.3 from JobList import JobList
9 nsmirnov 1.1 from Creator import Creator
10     from Submitter import Submitter
11 slacapra 1.8 from Checker import Checker
12 slacapra 1.9 from PostMortem import PostMortem
13     from Status import Status
14 spiga 1.16 from StatusBoss import StatusBoss
15 nsmirnov 1.1 import common
16 spiga 1.13 import Statistic
17 nsmirnov 1.1
18     import sys, os, time, string
19    
20     ###########################################################################
21     class Crab:
22 nsmirnov 1.3 def __init__(self, opts):
23 nsmirnov 1.1
24     # The order of main_actions is important !
25 slacapra 1.28 self.main_actions = [ '-create', '-submit' ]
26 slacapra 1.8 self.aux_actions = [ '-list', '-kill', '-status', '-getoutput',
27 slacapra 1.28 '-resubmit' , '-cancelAndResubmit', '-testJdl', '-postMortem', '-clean']
28 nsmirnov 1.1
29     # Dictionary of actions, e.g. '-create' -> object of class Creator
30     self.actions = {}
31    
32     # Configuration file
33     self.cfg_fname = None
34     # Dictionary with configuration parameters
35     self.cfg_params = {}
36    
37     # Current working directory
38     self.cwd = os.getcwd()+'/'
39     # Current time in format 'yymmdd_hhmmss'
40     self.current_time = time.strftime('%y%m%d_%H%M%S',
41     time.localtime(time.time()))
42    
43 nsmirnov 1.3 # Session name (?) Do we need this ?
44 nsmirnov 1.1 self.name = '0'
45    
46     # Job type
47     self.job_type_name = None
48    
49     # Continuation flag
50     self.flag_continue = 0
51    
52     # quiet mode, i.e. no output on screen
53     self.flag_quiet = 0
54     # produce more output
55     self.debug_level = 0
56    
57 nsmirnov 1.3 # Scheduler name, e.g. 'edg', 'lsf'
58 fanzago 1.14 self.scheduler_name = ''
59 nsmirnov 1.1
60 nsmirnov 1.3 self.initialize_(opts)
61 nsmirnov 1.1
62     return
63    
64 nsmirnov 1.7 def version():
65 nsmirnov 1.1 return common.prog_version_str
66    
67 nsmirnov 1.7 version = staticmethod(version)
68    
69 nsmirnov 1.3 def initialize_(self, opts):
70 nsmirnov 1.1
71     # Process the '-continue' option first because
72     # in the case of continuation the CRAB configuration
73     # parameters are loaded from already existing Working Space.
74 nsmirnov 1.3 self.processContinueOption_(opts)
75 nsmirnov 1.1
76     # Process ini-file first, then command line options
77     # because they override ini-file settings.
78    
79 nsmirnov 1.3 self.processIniFile_(opts)
80 nsmirnov 1.1
81 nsmirnov 1.3 if self.flag_continue: opts = self.loadConfiguration_(opts)
82 nsmirnov 1.1
83 nsmirnov 1.3 self.processOptions_(opts)
84 nsmirnov 1.1
85     if not self.flag_continue:
86 nsmirnov 1.3 self.createWorkingSpace_()
87 slacapra 1.9 optsToBeSaved={}
88     for it in opts.keys():
89     if (it in self.main_actions) or (it in self.aux_actions) or (it == '-debug'):
90     pass
91     else:
92     optsToBeSaved[it]=opts[it]
93     common.work_space.saveConfiguration(optsToBeSaved, self.cfg_fname)
94 nsmirnov 1.1 pass
95    
96     # At this point all configuration options have been read.
97    
98     args = string.join(sys.argv,' ')
99 slacapra 1.11
100 nsmirnov 1.3 self.updateHistory_(args)
101 slacapra 1.11
102 nsmirnov 1.3 self.createLogger_(args)
103 slacapra 1.11
104 nsmirnov 1.1 common.jobDB = JobDB()
105 slacapra 1.11
106 nsmirnov 1.3 if self.flag_continue:
107 slacapra 1.12 try:
108     common.jobDB.load()
109     common.logger.debug(6, str(common.jobDB))
110     except DBException,e:
111     pass
112 nsmirnov 1.3 pass
113 slacapra 1.11
114 nsmirnov 1.3 self.createScheduler_()
115 slacapra 1.11
116 nsmirnov 1.3 if common.logger.debugLevel() >= 6:
117     common.logger.debug(6, 'Used properties:')
118     keys = self.cfg_params.keys()
119     keys.sort()
120     for k in keys:
121     if self.cfg_params[k]:
122     common.logger.debug(6, ' '+k+' : '+self.cfg_params[k])
123     pass
124     else:
125     common.logger.debug(6, ' '+k+' : ')
126     pass
127     pass
128     common.logger.debug(6, 'End of used properties.\n')
129     pass
130     self.initializeActions_(opts)
131 nsmirnov 1.1 return
132    
133 nsmirnov 1.3 def processContinueOption_(self,opts):
134 nsmirnov 1.1
135     continue_dir = None
136 nsmirnov 1.4
137     # Look for the '-continue' option.
138    
139 nsmirnov 1.1 for opt in opts.keys():
140     if ( opt in ('-continue','-c') ):
141     self.flag_continue = 1
142     val = opts[opt]
143     if val:
144     if val[0] == '/': continue_dir = val # abs path
145     else: continue_dir = self.cwd + val # rel path
146     pass
147 nsmirnov 1.4 break
148     pass
149    
150     # Look for actions which has sense only with '-continue'
151    
152     if not self.flag_continue:
153     for opt in opts.keys():
154 slacapra 1.6 if ( opt in (self.aux_actions) ):
155 nsmirnov 1.4 self.flag_continue = 1
156     break
157 nsmirnov 1.1 pass
158     pass
159 slacapra 1.6 submit_flag=0
160     create_flag=0
161     for opt in opts.keys():
162     if opt == "-submit": submit_flag=1
163     if opt == "-create": create_flag=1
164     pass
165     if (submit_flag and not create_flag):
166 nsmirnov 1.7 msg = "'-submit' must be used with either '-create' or '-continue'."
167     raise CrabException(msg)
168 slacapra 1.6 pass
169 nsmirnov 1.1
170     if not self.flag_continue: return
171    
172     if not continue_dir:
173     prefix = common.prog_name + '_' + self.name + '_'
174     continue_dir = findLastWorkDir(prefix)
175     pass
176    
177     if not continue_dir:
178     raise CrabException('Cannot find last working directory.')
179    
180     if not os.path.exists(continue_dir):
181     msg = 'Cannot continue because the working directory <'
182     msg += continue_dir
183     msg += '> does not exist.'
184     raise CrabException(msg)
185    
186     # Instantiate WorkSpace
187     common.work_space = WorkSpace(continue_dir)
188    
189     return
190    
191 nsmirnov 1.3 def processIniFile_(self, opts):
192 nsmirnov 1.1 """
193     Processes a configuration INI-file.
194     """
195    
196     # Extract cfg-file name from the cmd-line options.
197    
198     for opt in opts.keys():
199     if ( opt == '-cfg' ):
200     if self.flag_continue:
201     raise CrabException('-continue and -cfg cannot coexist.')
202     if opts[opt] : self.cfg_fname = opts[opt]
203     else : usage()
204     pass
205    
206     elif ( opt == '-name' ):
207     self.name = opts[opt]
208     pass
209    
210     pass
211    
212     # Set default cfg-fname
213    
214     if self.cfg_fname == None:
215     if self.flag_continue:
216     self.cfg_fname = common.work_space.cfgFileName()
217     else:
218     self.cfg_fname = common.prog_name+'.cfg'
219     pass
220     pass
221    
222     # Load cfg-file
223    
224     if string.lower(self.cfg_fname) != 'none':
225     if os.path.exists(self.cfg_fname):
226     self.cfg_params = loadConfig(self.cfg_fname)
227     pass
228     else:
229     msg = 'cfg-file '+self.cfg_fname+' not found.'
230     raise CrabException(msg)
231     pass
232     pass
233    
234     # process the [CRAB] section
235    
236     lhp = len('CRAB.')
237     for k in self.cfg_params.keys():
238     if len(k) >= lhp and k[:lhp] == 'CRAB.':
239     opt = '-'+k[lhp:]
240     if len(opt) >= 3 and opt[:3] == '-__': continue
241     if opt not in opts.keys():
242     opts[opt] = self.cfg_params[k]
243     pass
244     pass
245     pass
246    
247     return
248    
249 nsmirnov 1.3 def processOptions_(self, opts):
250 nsmirnov 1.1 """
251     Processes the command-line options.
252     """
253    
254     for opt in opts.keys():
255     val = opts[opt]
256    
257 nsmirnov 1.3 # Skip actions, they are processed later in initializeActions_()
258     if opt in self.main_actions:
259     self.cfg_params['CRAB.'+opt[1:]] = val
260     continue
261     if opt in self.aux_actions:
262     self.cfg_params['CRAB.'+opt[1:]] = val
263     continue
264 nsmirnov 1.1
265    
266     elif ( opt == '-cfg' ):
267     pass
268    
269     elif ( opt in ('-continue', '-c') ):
270 nsmirnov 1.4 # Already processed in processContinueOption_()
271 nsmirnov 1.1 pass
272    
273     elif ( opt == '-jobtype' ):
274     if val : self.job_type_name = string.upper(val)
275     else : usage()
276     pass
277    
278     elif ( opt == '-Q' ):
279     self.flag_quiet = 1
280     pass
281    
282     elif ( opt == '-debug' ):
283 slacapra 1.6 if val: self.debug_level = int(val)
284     else: self.debug_level = 1
285 nsmirnov 1.1 pass
286    
287     elif ( opt == '-scheduler' ):
288     if val: self.scheduler_name = val
289     else:
290     print common.prog_name+". No value for '-scheduler'."
291     usage()
292     pass
293     pass
294 slacapra 1.22
295 fanzago 1.18 elif ( opt in ('-use_boss', '-useboss') ):
296     if ( val == '1' ):
297     self.scheduler_name = 'boss'
298     pass
299     elif ( val == '0' ):
300     pass
301     else:
302     print common.prog_name+'. Bad flag for -use_boss option:',\
303     val,'Possible values are 0(=No) or 1(=Yes)'
304     usage()
305     pass
306 fanzago 1.14 pass
307    
308 nsmirnov 1.3 elif string.find(opt,'.') == -1:
309     print common.prog_name+'. Unrecognized option '+opt
310     usage()
311     pass
312 nsmirnov 1.1
313 nsmirnov 1.3 # Override config parameters from INI-file with cmd-line params
314     if string.find(opt,'.') == -1 :
315     self.cfg_params['CRAB.'+opt[1:]] = val
316 nsmirnov 1.1 pass
317 nsmirnov 1.3 else:
318 nsmirnov 1.1 # Command line parameters in the form -SECTION.ENTRY=VALUE
319     self.cfg_params[opt[1:]] = val
320     pass
321     pass
322     return
323    
324 slacapra 1.8 def parseRange_(self, aRange):
325 nsmirnov 1.4 """
326 slacapra 1.8 Takes as the input a string with a range defined in any of the following
327     way, including combination, and return a tuple with the ints defined
328     according to following table. A consistency check is done.
329     NB: the first job is "1", not "0".
330     'all' -> [1,2,..., NJobs]
331     '' -> [1,2,..., NJobs]
332     'n1' -> [n1]
333     'n1-n2' -> [n1, n1+1, n1+2, ..., n2-1, n2]
334     'n1,n2' -> [n1, n2]
335     'n1,n2-n3' -> [n1, n2, n2+1, n2+2, ..., n3-1, n3]
336     """
337     result = []
338    
339 slacapra 1.9 common.logger.debug(5,"parseRange_ "+str(aRange))
340     if aRange=='all' or aRange==None or aRange=='':
341 slacapra 1.8 result=range(0,common.jobDB.nJobs())
342     return result
343 slacapra 1.9 elif aRange=='0':
344     return result
345 slacapra 1.8
346     subRanges = string.split(aRange, ',')
347     for subRange in subRanges:
348     result = result+self.parseSimpleRange_(subRange)
349    
350     if self.checkUniqueness_(result):
351     return result
352     else:
353 slacapra 1.33 common.logger.message("Error "+result)
354 slacapra 1.8 return []
355    
356     def checkUniqueness_(self, list):
357     """
358 slacapra 1.9 check if a list contains only unique elements
359 slacapra 1.8 """
360    
361     uniqueList = []
362     # use a list comprehension statement (takes a while to understand)
363    
364     [uniqueList.append(it) for it in list if not uniqueList.count(it)]
365    
366     return (len(list)==len(uniqueList))
367    
368     def parseSimpleRange_(self, aRange):
369     """
370     Takes as the input a string with two integers separated by
371     the minus sign and returns the tuple with these numbers:
372     'n1-n2' -> [n1, n1+1, n1+2, ..., n2-1, n2]
373     'n1' -> [n1]
374     """
375     (start, end) = (None, None)
376    
377     result = []
378     minus = string.find(aRange, '-')
379     if ( minus < 0 ):
380     if isInt(aRange) and int(aRange)>0:
381     result.append(int(aRange)-1)
382     else:
383 slacapra 1.9 common.logger.message("parseSimpleRange_ ERROR "+aRange)
384 nsmirnov 1.4 pass
385     else:
386 slacapra 1.8 (start, end) = string.split(aRange, '-')
387     if isInt(start) and isInt(end) and int(start)>0 and int(start)<int(end):
388     result=range(int(start)-1, int(end))
389     else:
390 slacapra 1.33 common.logger.message("parseSimpleRange_ ERROR "+start+end)
391 slacapra 1.8
392     return result
393 nsmirnov 1.4
394 nsmirnov 1.3 def initializeActions_(self, opts):
395 nsmirnov 1.1 """
396     For each user action instantiate a corresponding
397     object and put it in the action dictionary.
398     """
399     for opt in opts.keys():
400 spiga 1.32 self.flag_useboss = 0
401 spiga 1.16 if ( opt == '-use_boss'):
402 slacapra 1.25 val = opts[opt]
403     if ( val == '1' ):
404     self.flag_useboss = 1
405     common.logger.message('Using BOSS')
406     pass
407     else:
408     self.flag_useboss = 0
409     pass
410 spiga 1.15
411     for opt in opts.keys():
412    
413 nsmirnov 1.1 val = opts[opt]
414 spiga 1.15
415    
416     if ( opt == '-create' ):
417 slacapra 1.22 ncjobs = 0
418 nsmirnov 1.1 if val:
419     if ( isInt(val) ):
420     ncjobs = int(val)
421     elif ( val == 'all'):
422     ncjobs = val
423     else:
424 nsmirnov 1.5 msg = 'Bad creation bunch size <'+str(val)+'>\n'
425     msg += ' Must be an integer or "all"'
426 slacapra 1.8 msg += ' Generic range is not allowed"'
427 nsmirnov 1.5 raise CrabException(msg)
428 nsmirnov 1.1 pass
429     else: ncjobs = 'all'
430    
431     if ncjobs != 0:
432 nsmirnov 1.3 # Instantiate Creator object
433 nsmirnov 1.1 creator = Creator(self.job_type_name,
434     self.cfg_params,
435     ncjobs)
436     self.actions[opt] = creator
437 nsmirnov 1.3
438     # Initialize the JobDB object if needed
439 nsmirnov 1.1 if not self.flag_continue:
440     common.jobDB.create(creator.nJobs())
441     pass
442 nsmirnov 1.3
443     # Create and initialize JobList
444    
445     common.job_list = JobList(common.jobDB.nJobs(),
446     creator.jobType())
447    
448     common.job_list.setScriptNames(self.job_type_name+'.sh')
449     common.job_list.setJDLNames(self.job_type_name+'.jdl')
450 slacapra 1.12 common.job_list.setCfgNames(self.job_type_name+'.orcarc')
451 slacapra 1.9
452     creator.writeJobsSpecsToDB()
453 nsmirnov 1.1 pass
454 nsmirnov 1.3 pass
455 nsmirnov 1.1
456     elif ( opt == '-submit' ):
457 slacapra 1.23
458     # total jobs
459     # get the first not already submitted
460 slacapra 1.24 common.logger.debug(5,'Total jobs '+str(common.jobDB.nJobs()))
461     lastSubmittedJob=0
462     for nj in range(common.jobDB.nJobs()):
463     if (common.jobDB.status(nj)=='S'):
464     lastSubmittedJob +=1
465 slacapra 1.30 else: break
466 slacapra 1.24 # count job from 1
467 slacapra 1.30 totalJobsSubmittable = common.jobDB.nJobs()-lastSubmittedJob
468 slacapra 1.24 common.logger.debug(5,'lastSubmittedJob '+str(lastSubmittedJob))
469     common.logger.debug(5,'totalJobsSubmittable '+str(totalJobsSubmittable))
470 slacapra 1.23
471 slacapra 1.24 nsjobs = lastSubmittedJob+totalJobsSubmittable
472 slacapra 1.23 # get user request
473 slacapra 1.22 if val:
474     if ( isInt(val) ):
475 slacapra 1.24 tmp = int(val)
476     if (tmp >= totalJobsSubmittable):
477     common.logger.message('asking to submit '+str(tmp)+' jobs, but only '+str(totalJobsSubmittable)+' left: submitting those')
478     pass
479     else:
480     nsjobs=lastSubmittedJob+int(val)
481 slacapra 1.23 elif (val=='all'):
482     pass
483 slacapra 1.22 else:
484     msg = 'Bad submission option <'+str(val)+'>\n'
485     msg += ' Must be an integer or "all"'
486     msg += ' Generic range is not allowed"'
487     raise CrabException(msg)
488     pass
489 slacapra 1.24 common.logger.debug(5,'nsjobs '+str(nsjobs))
490 slacapra 1.23
491     # submit N from last submitted job
492 slacapra 1.24 nj_list = range(lastSubmittedJob, nsjobs)
493     common.logger.debug(5,'nj_list '+str(nj_list))
494 nsmirnov 1.5
495     if len(nj_list) != 0:
496 nsmirnov 1.3 # Instantiate Submitter object
497 nsmirnov 1.5 self.actions[opt] = Submitter(self.cfg_params, nj_list)
498 nsmirnov 1.3
499     # Create and initialize JobList
500     if len(common.job_list) == 0 :
501     common.job_list = JobList(common.jobDB.nJobs(),
502     None)
503     common.job_list.setJDLNames(self.job_type_name+'.jdl')
504     pass
505 nsmirnov 1.1 pass
506 slacapra 1.30 pass
507 nsmirnov 1.1
508 nsmirnov 1.4 elif ( opt == '-list' ):
509 slacapra 1.8 jobs = self.parseRange_(val)
510    
511     common.jobDB.dump(jobs)
512 nsmirnov 1.4 pass
513    
514     elif ( opt == '-status' ):
515 slacapra 1.8 jobs = self.parseRange_(val)
516    
517 slacapra 1.9 if len(jobs) != 0:
518 spiga 1.16 if ( self.flag_useboss == 1 ):
519     self.actions[opt] = StatusBoss(self.cfg_params, jobs)
520 spiga 1.15 else:
521     self.actions[opt] = Status(self.cfg_params, jobs)
522     pass
523 nsmirnov 1.1 pass
524     pass
525 slacapra 1.22
526 nsmirnov 1.4 elif ( opt == '-kill' ):
527 slacapra 1.8
528 spiga 1.31 if ( self.flag_useboss == 1 ):
529     if val:
530     if val =='all':
531     jobs = common.scheduler.listBoss()
532     else:
533     jobs = self.parseRange_(val)
534     common.scheduler.cancel(jobs)
535     else:
536     common.logger.message("Warning: with '-kill' you _MUST_ specify a job range or 'all'")
537     else:
538     if val:
539     jobs = self.parseRange_(val)
540    
541     for nj in jobs:
542     st = common.jobDB.status(nj)
543     if st == 'S':
544     jid = common.jobDB.jobId(nj)
545     common.logger.message("Killing job # "+`(nj+1)`)
546     common.scheduler.cancel(jid)
547     common.jobDB.setStatus(nj, 'K')
548     pass
549 slacapra 1.9 pass
550 spiga 1.31
551     common.jobDB.save()
552 nsmirnov 1.4 pass
553 spiga 1.31 else:
554     common.logger.message("Warning: with '-kill' you _MUST_ specify a job range or 'all'")
555 nsmirnov 1.1
556 slacapra 1.8 elif ( opt == '-getoutput' ):
557    
558 spiga 1.20 if ( self.flag_useboss == 1 ):
559     if val=='all' or val==None or val=='':
560 spiga 1.21 jobs = common.scheduler.listBoss()
561 spiga 1.20 else:
562     jobs = self.parseRange_(val)
563    
564     common.scheduler.getOutput(jobs)
565     else:
566     jobs = self.parseRange_(val)
567 spiga 1.13
568 slacapra 1.22 ## also this: create a ActorClass (GetOutput)
569 spiga 1.20 jobs_done = []
570     for nj in jobs:
571     st = common.jobDB.status(nj)
572     if st == 'D':
573 slacapra 1.12 jobs_done.append(nj)
574 spiga 1.20 pass
575     elif st == 'S':
576     jid = common.jobDB.jobId(nj)
577     currStatus = common.scheduler.queryStatus(jid)
578     if currStatus=="Done":
579     jobs_done.append(nj)
580     else:
581     msg = 'Job # '+`(nj+1)`+' submitted but still status '+currStatus+' not possible to get output'
582     common.logger.message(msg)
583     pass
584 slacapra 1.9 else:
585 spiga 1.20 # common.logger.message('Jobs #'+`(nj+1)`+' has status '+st+' not possible to get output')
586     pass
587 slacapra 1.12 pass
588    
589 spiga 1.20 for nj in jobs_done:
590 spiga 1.15 jid = common.jobDB.jobId(nj)
591     dir = common.scheduler.getOutput(jid)
592     common.jobDB.setStatus(nj, 'Y')
593 slacapra 1.12
594     # Rename the directory with results to smth readable
595     new_dir = common.work_space.resDir()
596 spiga 1.20 try:
597     files = os.listdir(dir)
598     for file in files:
599     os.rename(dir+'/'+file, new_dir+'/'+file)
600     os.rmdir(dir)
601     except OSError, e:
602     msg = 'rename files from '+dir+' to '+new_dir+' error: '
603     msg += str(e)
604     common.logger.message(msg)
605     # ignore error
606 slacapra 1.12 pass
607 spiga 1.20 pass
608 slacapra 1.22 ###
609    
610 spiga 1.13 resFlag = 0
611     exCode = common.scheduler.getExitStatus(jid)
612 spiga 1.34 Statistic.Monitor('retrieved',resFlag,jid,exCode)
613 slacapra 1.12
614     msg = 'Results of Job # '+`(nj+1)`+' are in '+new_dir
615     common.logger.message(msg)
616 nsmirnov 1.4 pass
617    
618     common.jobDB.save()
619     pass
620    
621     elif ( opt == '-resubmit' ):
622 slacapra 1.11 if val:
623     jobs = self.parseRange_(val)
624 slacapra 1.8
625 slacapra 1.11 # create a list of jobs to be resubmitted.
626 slacapra 1.8
627 slacapra 1.22 ### as before, create a Resubmittter Class
628 slacapra 1.11 nj_list = []
629     for nj in jobs:
630     st = common.jobDB.status(nj)
631 slacapra 1.8
632 slacapra 1.11 if st in ['K','A']:
633     nj_list.append(nj)
634     elif st == 'Y':
635     # here I would like to move the old output to a new place
636     # I would need the name of the output files.
637     # these infos are in the jobType class, which is not accessible from here!
638     outSandbox = common.jobDB.outputSandbox(nj)
639    
640     resDir = common.work_space.resDir()
641     resDirSave = resDir + self.current_time
642     os.mkdir(resDirSave)
643    
644     for file in outSandbox:
645     if os.path.exists(resDir+'/'+file):
646     os.rename(resDir+'/'+file, resDirSave+'/'+file)
647     common.logger.message('Output file '+file+' moved to '+resDirSave)
648     pass
649     nj_list.append(nj)
650 spiga 1.13 st = common.jobDB.setStatus(nj,'RC')
651 slacapra 1.11 elif st == 'D':
652     ## Done but not yet retrieved
653     ## retrieve job, then go to previous ('Y') case
654     ## TODO
655     pass
656     else:
657     common.logger.message('Job #'+str(nj+1)+' has status '+crabJobStatusToString(st)+' must be "killed" before resubmission')
658 slacapra 1.9 pass
659 slacapra 1.8
660 slacapra 1.11 if len(nj_list) != 0:
661     # Instantiate Submitter object
662     self.actions[opt] = Submitter(self.cfg_params, nj_list)
663    
664     # Create and initialize JobList
665    
666     if len(common.job_list) == 0 :
667     common.job_list = JobList(common.jobDB.nJobs(),
668     None)
669     common.job_list.setJDLNames(self.job_type_name+'.jdl')
670     pass
671 slacapra 1.8 pass
672     pass
673 slacapra 1.11 else:
674     common.logger.message("Warning: with '-resubmit' you _MUST_ specify a job range or 'all'")
675     common.logger.message("WARNING: _all_ job specified in the rage will be resubmitted!!!")
676     pass
677 slacapra 1.8 pass
678    
679     elif ( opt == '-cancelAndResubmit' ):
680     jobs = self.parseRange_(val)
681 nsmirnov 1.5
682 nsmirnov 1.7 # Cancel submitted jobs.
683 nsmirnov 1.5
684 slacapra 1.8 nj_list = []
685     for nj in jobs:
686 nsmirnov 1.5 st = common.jobDB.status(nj)
687     if st == 'S':
688     jid = common.jobDB.jobId(nj)
689     common.scheduler.cancel(jid)
690     st = 'K'
691     common.jobDB.setStatus(nj, st)
692     pass
693 nsmirnov 1.7 pass
694 nsmirnov 1.5
695 slacapra 1.8 if st != 'X': nj_list.append(nj)
696     pass
697 nsmirnov 1.5
698     if len(nj_list) != 0:
699     # Instantiate Submitter object
700     self.actions[opt] = Submitter(self.cfg_params, nj_list)
701    
702     # Create and initialize JobList
703    
704     if len(common.job_list) == 0 :
705     common.job_list = JobList(common.jobDB.nJobs(),
706     None)
707     common.job_list.setJDLNames(self.job_type_name+'.jdl')
708     pass
709     pass
710 nsmirnov 1.4 pass
711    
712 slacapra 1.28 elif ( opt == '-testJdl' ):
713 slacapra 1.8 jobs = self.parseRange_(val)
714     nj_list = []
715     for nj in jobs:
716     st = common.jobDB.status(nj)
717 slacapra 1.12 if st == 'C': nj_list.append(nj)
718 slacapra 1.8 pass
719    
720     if len(nj_list) != 0:
721     # Instantiate Submitter object
722     self.actions[opt] = Checker(self.cfg_params, nj_list)
723    
724     # Create and initialize JobList
725    
726     if len(common.job_list) == 0 :
727     common.job_list = JobList(common.jobDB.nJobs(), None)
728     common.job_list.setJDLNames(self.job_type_name+'.jdl')
729     pass
730     pass
731    
732 slacapra 1.9 elif ( opt == '-postMortem' ):
733     jobs = self.parseRange_(val)
734     nj_list = []
735     for nj in jobs:
736     st = common.jobDB.status(nj)
737 fanzago 1.17 if st not in ['X', 'C']: nj_list.append(nj)
738 slacapra 1.9 pass
739    
740     if len(nj_list) != 0:
741     # Instantiate Submitter object
742 spiga 1.35 self.actions[opt] = PostMortem(self.cfg_params, nj_list,self.flag_useboss)
743 slacapra 1.9
744     # Create and initialize JobList
745    
746     if len(common.job_list) == 0 :
747     common.job_list = JobList(common.jobDB.nJobs(), None)
748     common.job_list.setJDLNames(self.job_type_name+'.jdl')
749     pass
750     pass
751 slacapra 1.33 else:
752     common.logger.message("No jobs to analyze")
753 slacapra 1.9
754     elif ( opt == '-clean' ):
755     if val != None:
756     raise CrabException("No range allowed for '-clean'")
757    
758     submittedJobs=0
759 slacapra 1.11 doneJobs=0
760 slacapra 1.12 try:
761     for nj in range(0,common.jobDB.nJobs()):
762     st = common.jobDB.status(nj)
763     if st == 'S':
764     submittedJobs = submittedJobs+1
765     if st == 'D':
766     doneJobs = doneJobs+1
767     pass
768     pass
769     except DBException:
770     common.logger.debug(5,'DB not found, so delete all')
771 nsmirnov 1.1 pass
772 slacapra 1.9
773 slacapra 1.11 if submittedJobs or doneJobs:
774     msg = "There are still "
775     if submittedJobs:
776     msg= msg+str(submittedJobs)+" jobs submitted. Kill them '-kill' before '-clean'"
777     if (submittedJobs and doneJobs):
778     msg = msg + "and \nalso"
779     if doneJobs:
780     msg= msg+str(doneJobs)+" jobs Done. Get their outputs '-getoutput' before '-clean'"
781     raise CrabException(msg)
782 slacapra 1.9
783     msg = 'directory '+common.work_space.topDir()+' removed'
784     common.work_space.delete()
785     common.logger.message(msg)
786    
787 nsmirnov 1.1 pass
788 slacapra 1.9
789 nsmirnov 1.1 pass
790     return
791    
792 nsmirnov 1.3 def createWorkingSpace_(self):
793 slacapra 1.9 new_dir = ''
794    
795     try:
796     new_dir = self.cfg_params['USER.ui_working_dir']
797     except KeyError:
798     new_dir = common.prog_name + '_' + self.name + '_' + self.current_time
799     new_dir = self.cwd + new_dir
800     pass
801    
802 nsmirnov 1.1 common.work_space = WorkSpace(new_dir)
803     common.work_space.create()
804     return
805    
806 nsmirnov 1.3 def loadConfiguration_(self, opts):
807 nsmirnov 1.1
808     save_opts = common.work_space.loadSavedOptions()
809    
810     # Override saved options with new command-line options
811    
812     for k in opts.keys():
813     save_opts[k] = opts[k]
814     pass
815    
816     # Return updated options
817     return save_opts
818    
819 nsmirnov 1.3 def createLogger_(self, args):
820 nsmirnov 1.1
821     log = Logger()
822     log.quiet(self.flag_quiet)
823     log.setDebugLevel(self.debug_level)
824     log.write(args+'\n')
825 nsmirnov 1.3 log.message(self.headerString_())
826 nsmirnov 1.1 log.flush()
827     common.logger = log
828     return
829    
830 nsmirnov 1.3 def updateHistory_(self, args):
831 nsmirnov 1.1 history_fname = common.prog_name+'.history'
832     history_file = open(history_fname, 'a')
833     history_file.write(self.current_time+': '+args+'\n')
834     history_file.close()
835     return
836    
837 nsmirnov 1.3 def headerString_(self):
838 nsmirnov 1.1 """
839     Creates a string describing program options either given in
840     the command line or their default values.
841     """
842     header = common.prog_name + ' (version ' + common.prog_version_str + \
843     ') running on ' + \
844     time.ctime(time.time())+'\n\n' + \
845     common.prog_name+'. Working options:\n'
846     header = header +\
847     ' scheduler ' + self.scheduler_name + '\n'+\
848     ' job type ' + self.job_type_name + '\n'+\
849     ' working directory ' + common.work_space.topDir()\
850     + '\n'
851     return header
852    
853 nsmirnov 1.3 def createScheduler_(self):
854 nsmirnov 1.1 """
855     Creates a scheduler object instantiated by its name.
856     """
857     klass_name = 'Scheduler' + string.capitalize(self.scheduler_name)
858     file_name = klass_name
859     try:
860     klass = importName(file_name, klass_name)
861     except KeyError:
862     msg = 'No `class '+klass_name+'` found in file `'+file_name+'.py`'
863     raise CrabException(msg)
864     except ImportError, e:
865     msg = 'Cannot create scheduler '+self.scheduler_name
866     msg += ' (file: '+file_name+', class '+klass_name+'):\n'
867     msg += str(e)
868     raise CrabException(msg)
869    
870     common.scheduler = klass()
871     common.scheduler.configure(self.cfg_params)
872     return
873    
874     def run(self):
875     """
876     For each
877     """
878    
879     for act in self.main_actions:
880     if act in self.actions.keys(): self.actions[act].run()
881     pass
882    
883     for act in self.aux_actions:
884     if act in self.actions.keys(): self.actions[act].run()
885     pass
886     return
887    
888     ###########################################################################
889     def processHelpOptions(opts):
890    
891 slacapra 1.11 if len(opts):
892     for opt in opts.keys():
893     if opt in ('-v', '-version', '--version') :
894     print Crab.version()
895     return 1
896     if opt in ('-h','-help','--help') :
897     if opts[opt] : help(opts[opt])
898     else: help()
899     return 1
900     else:
901     usage()
902 nsmirnov 1.1
903     return 0
904    
905     ###########################################################################
906     if __name__ == '__main__':
907    
908 fanzago 1.18
909 fanzago 1.19 # # Initial settings for Python modules. Avoid appending manually lib paths.
910     # try:
911     # path=os.environ['EDG_WL_LOCATION']
912     # except:
913     # print "Error: Please set the EDG_WL_LOCATION environment variable pointing to the userinterface installation path"
914     # sys.exit(1)
915     #
916     # libPath=os.path.join(path, "lib")
917     # sys.path.append(libPath)
918     # libPath=os.path.join(path, "lib", "python")
919     # sys.path.append(libPath)
920 fanzago 1.18
921    
922 nsmirnov 1.1 # Parse command-line options and create a dictionary with
923     # key-value pairs.
924    
925     options = parseOptions(sys.argv[1:])
926    
927     # Process "help" options, such as '-help', '-version'
928    
929 slacapra 1.11 if processHelpOptions(options) : sys.exit(0)
930 nsmirnov 1.1
931     # Create, initialize, and run a Crab object
932    
933     try:
934 nsmirnov 1.3 crab = Crab(options)
935 nsmirnov 1.1 crab.run()
936     except CrabException, e:
937     print '\n' + common.prog_name + ': ' + str(e) + '\n'
938     if common.logger:
939     common.logger.write('ERROR: '+str(e)+'\n')
940     pass
941     pass
942    
943     pass