ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/CRAB/python/crab.py
Revision: 1.32
Committed: Thu Nov 3 14:23:33 2005 UTC (19 years, 6 months ago) by spiga
Content type: text/x-python
Branch: MAIN
CVS Tags: CRAB_1_0_1, CRAB_1_0_0_rc1
Changes since 1.31: +1 -0 lines
Log Message:
patch

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     print "Error ", result
354     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     print "ERROR ", start, end
391    
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 slacapra 1.22 ## This should not be here.
567 spiga 1.20 jobs = self.parseRange_(val)
568     fileCODE1 = open(common.work_space.logDir()+"/.code","r")
569     array = fileCODE1.read().split('::')
570     self.ID1 = array[0]
571     self.NJC = array[1]
572     self.dataset = array[2]
573     self.owner = array[3]
574     fileCODE1.close()
575 slacapra 1.22 ###
576 spiga 1.13
577 slacapra 1.22 ## also this: create a ActorClass (GetOutput)
578 spiga 1.20 jobs_done = []
579     for nj in jobs:
580     st = common.jobDB.status(nj)
581     if st == 'D':
582 slacapra 1.12 jobs_done.append(nj)
583 spiga 1.20 pass
584     elif st == 'S':
585     jid = common.jobDB.jobId(nj)
586     currStatus = common.scheduler.queryStatus(jid)
587     if currStatus=="Done":
588     jobs_done.append(nj)
589     else:
590     msg = 'Job # '+`(nj+1)`+' submitted but still status '+currStatus+' not possible to get output'
591     common.logger.message(msg)
592     pass
593 slacapra 1.9 else:
594 spiga 1.20 # common.logger.message('Jobs #'+`(nj+1)`+' has status '+st+' not possible to get output')
595     pass
596 slacapra 1.12 pass
597    
598 spiga 1.20 for nj in jobs_done:
599 spiga 1.15 jid = common.jobDB.jobId(nj)
600     dir = common.scheduler.getOutput(jid)
601     common.jobDB.setStatus(nj, 'Y')
602 slacapra 1.12
603     # Rename the directory with results to smth readable
604     new_dir = common.work_space.resDir()
605 spiga 1.20 try:
606     files = os.listdir(dir)
607     for file in files:
608     os.rename(dir+'/'+file, new_dir+'/'+file)
609     os.rmdir(dir)
610     except OSError, e:
611     msg = 'rename files from '+dir+' to '+new_dir+' error: '
612     msg += str(e)
613     common.logger.message(msg)
614     # ignore error
615 slacapra 1.12 pass
616 spiga 1.20 pass
617 slacapra 1.22 ###
618    
619     ## again, this should not be here but in getoutput class
620 spiga 1.13 destination = common.scheduler.queryDest(jid).split(":")[0]
621     ID3 = jid.split("/")[3]
622     broker = jid.split("/")[2].split(":")[0]
623     resFlag = 0
624     exCode = common.scheduler.getExitStatus(jid)
625     Statistic.notify('retrieved',resFlag,exCode,self.dataset,self.owner,destination,broker,ID3,self.ID1,self.NJC)
626 slacapra 1.22 ###
627 slacapra 1.12
628     msg = 'Results of Job # '+`(nj+1)`+' are in '+new_dir
629     common.logger.message(msg)
630 nsmirnov 1.4 pass
631    
632     common.jobDB.save()
633     pass
634    
635     elif ( opt == '-resubmit' ):
636 slacapra 1.11 if val:
637     jobs = self.parseRange_(val)
638 slacapra 1.8
639 slacapra 1.11 # create a list of jobs to be resubmitted.
640 slacapra 1.8
641 slacapra 1.22 ### as before, create a Resubmittter Class
642 slacapra 1.11 nj_list = []
643     for nj in jobs:
644     st = common.jobDB.status(nj)
645 slacapra 1.8
646 slacapra 1.11 if st in ['K','A']:
647     nj_list.append(nj)
648     elif st == 'Y':
649     # here I would like to move the old output to a new place
650     # I would need the name of the output files.
651     # these infos are in the jobType class, which is not accessible from here!
652     outSandbox = common.jobDB.outputSandbox(nj)
653    
654     resDir = common.work_space.resDir()
655     resDirSave = resDir + self.current_time
656     os.mkdir(resDirSave)
657    
658     for file in outSandbox:
659     if os.path.exists(resDir+'/'+file):
660     os.rename(resDir+'/'+file, resDirSave+'/'+file)
661     common.logger.message('Output file '+file+' moved to '+resDirSave)
662     pass
663     nj_list.append(nj)
664 spiga 1.13 st = common.jobDB.setStatus(nj,'RC')
665 slacapra 1.11 elif st == 'D':
666     ## Done but not yet retrieved
667     ## retrieve job, then go to previous ('Y') case
668     ## TODO
669     pass
670     else:
671     common.logger.message('Job #'+str(nj+1)+' has status '+crabJobStatusToString(st)+' must be "killed" before resubmission')
672 slacapra 1.9 pass
673 slacapra 1.8
674 slacapra 1.11 if len(nj_list) != 0:
675     # Instantiate Submitter object
676     self.actions[opt] = Submitter(self.cfg_params, nj_list)
677    
678     # Create and initialize JobList
679    
680     if len(common.job_list) == 0 :
681     common.job_list = JobList(common.jobDB.nJobs(),
682     None)
683     common.job_list.setJDLNames(self.job_type_name+'.jdl')
684     pass
685 slacapra 1.8 pass
686     pass
687 slacapra 1.11 else:
688     common.logger.message("Warning: with '-resubmit' you _MUST_ specify a job range or 'all'")
689     common.logger.message("WARNING: _all_ job specified in the rage will be resubmitted!!!")
690     pass
691 slacapra 1.8 pass
692    
693     elif ( opt == '-cancelAndResubmit' ):
694     jobs = self.parseRange_(val)
695 nsmirnov 1.5
696 nsmirnov 1.7 # Cancel submitted jobs.
697 nsmirnov 1.5
698 slacapra 1.8 nj_list = []
699     for nj in jobs:
700 nsmirnov 1.5 st = common.jobDB.status(nj)
701     if st == 'S':
702     jid = common.jobDB.jobId(nj)
703     common.scheduler.cancel(jid)
704     st = 'K'
705     common.jobDB.setStatus(nj, st)
706     pass
707 nsmirnov 1.7 pass
708 nsmirnov 1.5
709 slacapra 1.8 if st != 'X': nj_list.append(nj)
710     pass
711 nsmirnov 1.5
712     if len(nj_list) != 0:
713     # Instantiate Submitter object
714     self.actions[opt] = Submitter(self.cfg_params, nj_list)
715    
716     # Create and initialize JobList
717    
718     if len(common.job_list) == 0 :
719     common.job_list = JobList(common.jobDB.nJobs(),
720     None)
721     common.job_list.setJDLNames(self.job_type_name+'.jdl')
722     pass
723     pass
724 nsmirnov 1.4 pass
725    
726 slacapra 1.28 elif ( opt == '-testJdl' ):
727 slacapra 1.8 jobs = self.parseRange_(val)
728     nj_list = []
729     for nj in jobs:
730     st = common.jobDB.status(nj)
731 slacapra 1.12 if st == 'C': nj_list.append(nj)
732 slacapra 1.8 pass
733    
734     if len(nj_list) != 0:
735     # Instantiate Submitter object
736     self.actions[opt] = Checker(self.cfg_params, nj_list)
737    
738     # Create and initialize JobList
739    
740     if len(common.job_list) == 0 :
741     common.job_list = JobList(common.jobDB.nJobs(), None)
742     common.job_list.setJDLNames(self.job_type_name+'.jdl')
743     pass
744     pass
745    
746 slacapra 1.9 elif ( opt == '-postMortem' ):
747     jobs = self.parseRange_(val)
748     nj_list = []
749     for nj in jobs:
750     st = common.jobDB.status(nj)
751 fanzago 1.17 if st not in ['X', 'C']: nj_list.append(nj)
752 slacapra 1.9 pass
753    
754     if len(nj_list) != 0:
755     # Instantiate Submitter object
756     self.actions[opt] = PostMortem(self.cfg_params, nj_list)
757    
758     # Create and initialize JobList
759    
760     if len(common.job_list) == 0 :
761     common.job_list = JobList(common.jobDB.nJobs(), None)
762     common.job_list.setJDLNames(self.job_type_name+'.jdl')
763     pass
764     pass
765    
766     elif ( opt == '-clean' ):
767     if val != None:
768     raise CrabException("No range allowed for '-clean'")
769    
770     submittedJobs=0
771 slacapra 1.11 doneJobs=0
772 slacapra 1.12 try:
773     for nj in range(0,common.jobDB.nJobs()):
774     st = common.jobDB.status(nj)
775     if st == 'S':
776     submittedJobs = submittedJobs+1
777     if st == 'D':
778     doneJobs = doneJobs+1
779     pass
780     pass
781     except DBException:
782     common.logger.debug(5,'DB not found, so delete all')
783 nsmirnov 1.1 pass
784 slacapra 1.9
785 slacapra 1.11 if submittedJobs or doneJobs:
786     msg = "There are still "
787     if submittedJobs:
788     msg= msg+str(submittedJobs)+" jobs submitted. Kill them '-kill' before '-clean'"
789     if (submittedJobs and doneJobs):
790     msg = msg + "and \nalso"
791     if doneJobs:
792     msg= msg+str(doneJobs)+" jobs Done. Get their outputs '-getoutput' before '-clean'"
793     raise CrabException(msg)
794 slacapra 1.9
795     msg = 'directory '+common.work_space.topDir()+' removed'
796     common.work_space.delete()
797     common.logger.message(msg)
798    
799 nsmirnov 1.1 pass
800 slacapra 1.9
801 nsmirnov 1.1 pass
802     return
803    
804 nsmirnov 1.3 def createWorkingSpace_(self):
805 slacapra 1.9 new_dir = ''
806    
807     try:
808     new_dir = self.cfg_params['USER.ui_working_dir']
809     except KeyError:
810     new_dir = common.prog_name + '_' + self.name + '_' + self.current_time
811     new_dir = self.cwd + new_dir
812     pass
813    
814 nsmirnov 1.1 common.work_space = WorkSpace(new_dir)
815     common.work_space.create()
816     return
817    
818 nsmirnov 1.3 def loadConfiguration_(self, opts):
819 nsmirnov 1.1
820     save_opts = common.work_space.loadSavedOptions()
821    
822     # Override saved options with new command-line options
823    
824     for k in opts.keys():
825     save_opts[k] = opts[k]
826     pass
827    
828     # Return updated options
829     return save_opts
830    
831 nsmirnov 1.3 def createLogger_(self, args):
832 nsmirnov 1.1
833     log = Logger()
834     log.quiet(self.flag_quiet)
835     log.setDebugLevel(self.debug_level)
836     log.write(args+'\n')
837 nsmirnov 1.3 log.message(self.headerString_())
838 nsmirnov 1.1 log.flush()
839     common.logger = log
840     return
841    
842 nsmirnov 1.3 def updateHistory_(self, args):
843 nsmirnov 1.1 history_fname = common.prog_name+'.history'
844     history_file = open(history_fname, 'a')
845     history_file.write(self.current_time+': '+args+'\n')
846     history_file.close()
847     return
848    
849 nsmirnov 1.3 def headerString_(self):
850 nsmirnov 1.1 """
851     Creates a string describing program options either given in
852     the command line or their default values.
853     """
854     header = common.prog_name + ' (version ' + common.prog_version_str + \
855     ') running on ' + \
856     time.ctime(time.time())+'\n\n' + \
857     common.prog_name+'. Working options:\n'
858     header = header +\
859     ' scheduler ' + self.scheduler_name + '\n'+\
860     ' job type ' + self.job_type_name + '\n'+\
861     ' working directory ' + common.work_space.topDir()\
862     + '\n'
863     return header
864    
865 nsmirnov 1.3 def createScheduler_(self):
866 nsmirnov 1.1 """
867     Creates a scheduler object instantiated by its name.
868     """
869     klass_name = 'Scheduler' + string.capitalize(self.scheduler_name)
870     file_name = klass_name
871     try:
872     klass = importName(file_name, klass_name)
873     except KeyError:
874     msg = 'No `class '+klass_name+'` found in file `'+file_name+'.py`'
875     raise CrabException(msg)
876     except ImportError, e:
877     msg = 'Cannot create scheduler '+self.scheduler_name
878     msg += ' (file: '+file_name+', class '+klass_name+'):\n'
879     msg += str(e)
880     raise CrabException(msg)
881    
882     common.scheduler = klass()
883     common.scheduler.configure(self.cfg_params)
884     return
885    
886     def run(self):
887     """
888     For each
889     """
890    
891     for act in self.main_actions:
892     if act in self.actions.keys(): self.actions[act].run()
893     pass
894    
895     for act in self.aux_actions:
896     if act in self.actions.keys(): self.actions[act].run()
897     pass
898     return
899    
900     ###########################################################################
901     def processHelpOptions(opts):
902    
903 slacapra 1.11 if len(opts):
904     for opt in opts.keys():
905     if opt in ('-v', '-version', '--version') :
906     print Crab.version()
907     return 1
908     if opt in ('-h','-help','--help') :
909     if opts[opt] : help(opts[opt])
910     else: help()
911     return 1
912     else:
913     usage()
914 nsmirnov 1.1
915     return 0
916    
917     ###########################################################################
918     if __name__ == '__main__':
919    
920 fanzago 1.18
921 fanzago 1.19 # # Initial settings for Python modules. Avoid appending manually lib paths.
922     # try:
923     # path=os.environ['EDG_WL_LOCATION']
924     # except:
925     # print "Error: Please set the EDG_WL_LOCATION environment variable pointing to the userinterface installation path"
926     # sys.exit(1)
927     #
928     # libPath=os.path.join(path, "lib")
929     # sys.path.append(libPath)
930     # libPath=os.path.join(path, "lib", "python")
931     # sys.path.append(libPath)
932 fanzago 1.18
933    
934 nsmirnov 1.1 # Parse command-line options and create a dictionary with
935     # key-value pairs.
936    
937     options = parseOptions(sys.argv[1:])
938    
939     # Process "help" options, such as '-help', '-version'
940    
941 slacapra 1.11 if processHelpOptions(options) : sys.exit(0)
942 nsmirnov 1.1
943     # Create, initialize, and run a Crab object
944    
945     try:
946 nsmirnov 1.3 crab = Crab(options)
947 nsmirnov 1.1 crab.run()
948     except CrabException, e:
949     print '\n' + common.prog_name + ': ' + str(e) + '\n'
950     if common.logger:
951     common.logger.write('ERROR: '+str(e)+'\n')
952     pass
953     pass
954    
955     pass