ATLAS Offline Software
Loading...
Searching...
No Matches
taskman.py
Go to the documentation of this file.
1#!/usr/bin/env python
2
3# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
4
5
6"""
7taskman is a command line utility to run TaskManager functions.
8"""
9__author__ = 'Juerg Beringer'
10__version__ = 'taskman.py atlas/athena'
11__usage__ = '''%prog [options] taskdbconn command [args ...]
12
13Commands are:
14
15init Create a new database
16checkdb Check (and fix) sqlite database
17checkdup Check task database for duplicate entries
18debug Interactive debugging (EXPERTS ONLY!)
19dump [DSNAME TASKNAME] Dump all or selected tasks in database
20show DSNAME [TASKNAME] Show list of tasks
21update Update information of ongoing tasks
22update DSNAME TASKNAME Update information of selected tasks
23rebuild [DSNAME TASKNAME] Rebuild missing or selected database entries from job files
24import [DSNAME TASKNAME] DBCONN Import all or selected tasks from database DBCONN (duplicates not checked)
25setstatus DSNAME TASKNAME STATUS Set status of selected tasks to STATUS
26setfield DSNAME TASKNAME FIELDNAME VALUE Set database field to value (experts only!)
27delete DSNAME TASKNAME Delete entry for selected task(s) (task files are NOT removed)
28deleteResults DSNAME TASKNAME Delete postprocessing results for selected set of tasks
29deleteTask DSNAME TASKNAME Delete task files and corresponding TaskManager entry
30 for a single task (will prompt for confirmation unless
31 option --batch is used)
32'''
33
34import sys, os, stat
35import pprint
37from InDetBeamSpotExample.Utils import getRunFromName
38
39import subprocess
40
41
42from optparse import OptionParser
43parser = OptionParser(usage=__usage__, version=__version__)
44#parser.add_option('-x', '--xxx', dest='xx', default='myvalue', help='sample option')
45parser.add_option('-b', '--batch', dest='batch', action='store_true', default=False, help='batch mode - never ask for confirmation')
46parser.add_option('-v', '--verbose', dest='verbose', action='store_true', default=False, help='enable more verbose output for some commands')
47parser.add_option('-n', '--nowildcards', dest='nowildcards', action='store_true', default=False, help='do not add wildcards when looking up dataset and task names')
48parser.add_option('-d', '--dbconn', dest='dbconn', default='', help='task manager database connection string (default: check TASKDB, otherwise use sqlite_file:taskdata.db)')
49parser.add_option('', '--proddir', dest='proddir', default='.', help='production directory (default: "."')
50parser.add_option('-p', '--pretty', dest='pretty', action='store_true', default=None, help='try to nicely format output (default: auto)')
51parser.add_option('', '--no-pretty', dest='pretty', action='store_false', help='do not attempt to format output')
52parser.add_option('', '--runtaskname', dest='runtaskname', default='CB_BEAMSPOT', help='task name')
53(options,args) = parser.parse_args()
54
55if len(args) < 1:
56 parser.error('wrong number of command line arguments')
57cmd = args[0]
58cmdargs = args[1:]
59
60proddir = options.proddir
61if not os.path.exists(proddir):
62 sys.exit('ERROR: Job directory %s does not exist or is unreadable' % proddir)
63
64def getTaskManager(dbconn=None):
65 ''' Open task manager '''
66 dbconn = dbconn or options.dbconn
67 try:
68 return TaskManager(dbconn)
69 except:
70 print ('ERROR: Unable to access task manager database %s' % dbconn)
71 sys.exit(1)
72
73#
74# Initialize a new task database
75#
76if cmd == 'init':
77 if cmdargs: parser.error('Command init does not take arguments')
78 try:
79 dbtype, dbname = TaskManager.parseConnectionInfo(options.dbconn)
80 except ValueError as e:
81 sys.exit('ERROR: {}'.format(e))
82 print ('Will initialise schema for database: {}:{}'.format(dbtype, dbname))
83
84 print()
85 print ('Checking for existing database ...')
86 try:
87 with TaskManager(options.dbconn): pass
88 except ValueError as e:
89 print ('Test connection failed: {}'.format(e))
90 else:
91 print ('Test connection succeeded: the database already exists!')
92
93 if not options.batch:
94 a = raw_input('\nRECREATING TASK DATABASE SCHEMA - ANY EXISTING DATA WILL BE ERASED!\n\nARE YOU REALLY ABSOLUTELY SURE [n] ? ')
95 if a != 'y': sys.exit('ERROR: Rebuilding aborted by user')
96 print()
97 with TaskManager(options.dbconn, createDatabase=True): pass
98 sys.exit(0)
99
100
101#
102# Check integrity of sqlite database and vacuum, if necessary
103#
104if cmd == 'checkdb':
105 if cmdargs: parser.error('Command checkdb does not take arguments')
106 try:
107 dbtype, dbfile = TaskManager.parseConnectionInfo(options.dbconn)
108 except ValueError:
109 sys.exit("ERROR: Illegal or empty/default database connection string - must provide explicity SQLite file reference")
110 if dbtype != 'sqlite_file':
111 sys.exit('ERROR: checkdb is only supported for SQLite databases')
112 if not os.path.exists(dbfile):
113 sys.exit('ERROR: SQLite file %s does not exist' % dbfile)
114
115 (status, output) = subprocess.getstatusoutput("sqlite3 %s 'pragma integrity_check;'" % dbfile)
116 if status != 0:
117 sys.exit('ERROR: Error executing sqlite3 command')
118 if output != 'ok':
119 print ('ERROR: SQLite database file has errors:')
120 print (output)
121 print()
122
123 if not options.batch:
124 a = raw_input('Do you want to try VACUUM [n] ? ')
125 if a != 'y':
126 sys.exit('\nERROR: VACUUM not executed - please fix database file manually')
127 (status, output) = subprocess.getstatusoutput("sqlite3 %s 'vacuum;'" % dbfile)
128 print (output)
129 if status != 0:
130 sys.exit('ERROR: VACUUM failed')
131
132 (status, output) = subprocess.getstatusoutput("sqlite3 %s 'pragma integrity_check;'" % dbfile)
133 if status != 0 or output != 'ok':
134 print (output)
135 sys.exit('ERROR: Integrity check still failed - please check')
136 print ('INFO: SQLite file now passes integrity test (content may still have errors)')
137 sys.exit(2)
138
139 print ('INFO: SQLite file {} ok'.format(dbfile))
140 sys.exit(0)
141
142
143#
144# Check database for duplicate entries and remove duplicates, if necessary
145#
146if cmd == 'checkdup':
147 if cmdargs: parser.error('Command checkdup does not take arguments')
148 #q = ['select dsname,taskname,count(*) from tasks group by dsname,taskname']
149 nDuplicates = 0
150 with getTaskManager() as taskman:
151 for t in taskman.taskIter('dsname,taskname,count(*)', ['group by dsname,taskname']):
152 if t[2] > 1:
153 nDuplicates += 1
154 print ('Duplicate task: {} / {}'.format(t[0], t[1]))
155 for d in taskman.taskIterDict(qual=[
156 'where DSNAME =', DbParam(t[0]),
157 'and TASKNAME =', DbParam(t[1]),
158 'order by taskid']):
159 print (' TASKID =', d['TASKID'])
160 print (nDuplicates, 'duplicates found')
161 sys.exit(0)
162
163
164#
165# Dump contents of task database
166#
167if cmd == 'dump':
168 if not cmdargs:
169 with getTaskManager() as taskman:
170 print (taskman.getNTasks(),'task(s) found:\n')
171 if options.pretty:
172 for t in taskman.taskIterDict():
173 print ('\n\nTask {} / {}:\n'.format(
174 t['DSNAME'],
175 t['TASKNAME']))
176 print (pprint.pformat(t))
177 else:
178 for t in taskman.taskIter():
179 print (t)
180 sys.exit(0)
181
182 elif len(cmdargs) == 2:
183 dsname = cmdargs[0]
184 taskname = cmdargs[1]
185
186 with getTaskManager() as taskman:
187 try:
188 taskList = getFullTaskNames(taskman, dsname, taskname,
189 addWildCards=not options.nowildcards)
190 except TaskManagerCheckError as e:
191 sys.exit(e)
192 for t in taskList:
193 taskEntry = taskman.getTaskDict(t[0], t[1])
194 if options.pretty is None or options.pretty:
195 print ('\n\nTask {} / {}:\n'.format(
196 taskEntry['DSNAME'],
197 taskEntry['TASKNAME']))
198 print (pprint.pformat(taskEntry))
199 else:
200 print (taskEntry)
201 sys.exit(0)
202
203 else: parser.error('Command dump takes either 0 or 2 arguments')
204
205
206#
207# Show list of tasks
208#
209if cmd=='show' and (len(args)==2 or len(args)==3):
210 dsname = args[1]
211 taskname = args[2] if len(args)>2 else ''
212 try:
213 with getTaskManager() as taskman:
214 taskList = getFullTaskNames(taskman,dsname,taskname,addWildCards=not options.nowildcards)
215 print()
216 print (" %-50s %s" % ('DATASET NAME','TASK NAME'))
217 print (" %s" % (75*'-'))
218 for t in taskList:
219 print (" %-50s %s" % (t[0],t[1]) )
220 print ('\n%i task(s) found\n' % len(taskList))
221 sys.exit(0)
222 except TaskManagerCheckError as e:
223 print (e)
224 sys.exit(1)
225
226
227#
228# Update task database entries based on task files on disk
229#
230if cmd=='update' and len(args)==1:
231 if cmdargs: parser.error('Command update does not take any arguments')
232
233 with getTaskManager() as taskman:
234 for t in taskman.taskIterDict('DSNAME,TASKNAME', [
235 'where STATUS < {:d} and ONDISK < {:d}'.format(
236 TaskManager.StatusCodes['POSTPROCESSING'],
237 TaskManager.OnDiskCodes['ARCHIVED'])]):
238 a = TaskAnalyzer(proddir, t['DSNAME'], t['TASKNAME'])
239 if a.analyzeFiles():
240 print ('Updating task {}/{}'.format(t['DSNAME'], t['TASKNAME']))
241 a.updateStatus(taskman)
242 else:
243 taskman.setDiskStatus(t['DSNAME'], t['TASKNAME'],
244 TaskManager.OnDiskCodes['DELETED'])
245 sys.exit(0)
246
247if cmd=='update' and len(args)==3:
248 with getTaskManager() as taskman:
249 try:
250 taskList = getFullTaskNames(taskman,args[1],args[2],confirmWithUser=not options.batch,addWildCards=not options.nowildcards)
251 except TaskManagerCheckError as e:
252 print (e)
253 sys.exit(1)
254 for t in taskList:
255 a = TaskAnalyzer(proddir,t[0],t[1])
256 if a.analyzeFiles():
257 print ('Updating task %s/%s' % (t[0],t[0]))
258 a.updateStatus(taskman)
259 else:
260 taskman.setDiskStatus(t[0],t[0],TaskManager.OnDiskCodes['DELETED'])
261 sys.exit(0)
262
263
264#
265# Rebuild task database entries based on task files on disk
266#
267if cmd == 'rebuild':
268 if len(cmdargs) == 2:
269 dsname = cmdargs[0]
270 taskname = cmdargs[1]
271 taskpath = os.path.join(proddir, dsname, taskname)
272 elif not cmdargs:
273 taskpath = os.path.join(proddir, '*', '*')
274 else:
275 parser.error('Command rebuild takes 0 or 2 arguments')
276
277 print ('Will reconstruct database from directory: {}'.format(taskpath))
278 print()
279
280 with getTaskManager() as taskman:
281 dirs = []
282 if not options.batch:
283 print ('Rebuilding the following tasks:')
284 print()
285 print ( ' DB {:50} {}'.format('DATASET NAME','TASK NAME'))
286 print (' {}'.format(85 * '-'))
287 for p in glob.glob(taskpath):
288 if not os.path.isdir(p): continue
289 (dsName, taskName) = p.split('/')[-2:]
290 nDefined = taskman.getNTasks([
291 'where DSNAME=', DbParam(dsName),
292 'and TASKNAME=', DbParam(taskName)])
293 dirs.append((dsName, taskName, nDefined))
294
295 if nDefined == 0:
296 print (' {:50} {}'.format(dsName, taskName))
297 elif options.verbose:
298 print (' * {:50} {}'.format(dsName, taskName))
299
300 a = raw_input('\nARE YOU SURE [n] ? ')
301 if a != 'y':
302 sys.exit('ERROR: Rebuilding aborted by user')
303 print()
304
305 for (dsName, taskName, nDefined) in dirs:
306 if nDefined == 0:
307 print ('Adding missing entry for task {}/{}'.format(dsName, taskName))
308 configFile = glob.glob(os.path.join(proddir, dsName, taskName, '*', '*.config.py'))
309 if configFile:
310 mtime = os.stat(configFile[0])[stat.ST_MTIME]
311 config = {}
312 exec(compile(open(configFile[0]).read()), config)
313 try:
314 template = config['jobConfig']['joboptionpath']
315 except KeyError:
316 template = 'UNKNOWN'
317 try:
318 release = config['jobConfig']['release']
319 except KeyError:
320 release = 'UNKNOWN'
321 try:
322 taskpostprocsteps = config['jobConfig']['taskpostprocsteps']
323 except KeyError:
324 taskpostprocsteps = ''
325 try:
326 comment = config['jobConfig']['comment'] + ' (rebuilt from config file)'
327 except KeyError:
328 comment = 'rebuilt from config file'
329 taskman.addTask(dsName, taskName, template, release, 0, taskpostprocsteps,
330 createdTime=mtime,
331 createdUser='UNKNOWN',
332 createdHost='UNKNOWN',
333 comment=comment)
334 else:
335 print ('WARNING: no config file found, unable to determine task creation time and configuration details')
336 # Should we still add such a task - most likely this is a directory of files, e.g. some AOD or ESD files
337 taskman.addTask(dsName, taskName, 'UNKNOWN', 'UNKNOWN', 0,
338 comment='rebuilt, no config file found')
339 a = TaskAnalyzer(proddir, dsName, taskName)
340 a.analyzeFiles()
341 a.updateStatus(taskman)
342 elif nDefined == 1:
343 print ('Entry exists already for task {}/{} - SKIPPED'.format(dsName, taskName))
344 elif nDefined > 1:
345 print ('ERROR: {:d} conflicting task entries for task {}/{} - SKIPPED'.format(nDefined, dsName, taskName))
346 sys.exit(0)
347
348
349#
350# Import tasks from another task database
351#
352if cmd == 'import':
353 if len(cmdargs) == 1:
354 fromDbconn = cmdargs[0]
355 qual = []
356 elif len(cmdargs) == 3:
357 dsname = cmdargs[0]
358 taskname = cmdargs[1]
359 fromDbconn = cmdargs[2]
360
361 # Convert a minimal shell glob syntax into an SQL query:
362 import string
363 wildcards = string.maketrans('*?', '%_')
364 qual = []
365 if '*' in dsname or '?' in dsname:
366 qual.append("where DSNAME like '{}'".format(dsname.translate(wildcards)))
367 else:
368 qual.extend(['where DSNAME =', DbParam(dsname)])
369 if '*' in taskname or '?' in taskname:
370 qual.append("and TASKNAME like '{}'".format(taskname.translate(wildcards)))
371 else:
372 qual.extend(['and TASKNAME =', DbParam(taskname)])
373 else:
374 parser.error('Command import takes 1 or 3 arguments')
375
376 try:
377 destDbtype, destDbname = TaskManager.parseConnectionInfo(options.dbconn)
378 fromDbtype, fromDbname = TaskManager.parseConnectionInfo(fromDbconn)
379 except ValueError as e:
380 sys.exit('ERROR: Bad database connection string {}'.format(e))
381 print()
382 print ('Import from: {}:{}'.format(fromDbtype, fromDbname))
383 print ('Import into: {}:{}'.format(destDbtype, destDbname))
384 print()
385
386 with getTaskManager() as taskman:
387 with getTaskManager(fromDbconn) as fromman:
388 nImported = 0
389 qual.append('order by RUNNR desc')
390 for t in fromman.taskIterDict(qual=qual):
391 print ('Importing ', t['DSNAME'], '/' , t['TASKNAME'], '...')
392 if not 'RUNNR' in t.keys():
393 # Fill run number from DSNAME
394 t['RUNNR'] = getRunFromName(t['DSNAME'], None, True)
395 if not t.get('RESULTLINKS'):
396 # Rebuild old result files and links
397 links = ''
398 files = t.get('RESULTFILES','')
399 if files==None:
400 files = ''
401 dsname = t['DSNAME']
402 taskname = t['TASKNAME']
403 summaryFiles = glob.glob('%s/%s/*beamspot.gif' % (dsname,taskname))
404 if len(summaryFiles)>0:
405 for r in summaryFiles:
406 f = r.split('/')[-1]
407 pdf = f[:-3]+'pdf'
408 if not f in files.split():
409 files = ' '.join([files,f])
410 if not pdf in files.split():
411 files = ' '.join([files,pdf])
412 links += ' <a href="../files?u=%s/%s/%s">summary</a>' %(dsname,taskname,f)
413 links += ' (<a href="/jobfiles/%s/%s/%s">pdf</a>)' %(dsname,taskname,pdf)
414 monitoringFiles = glob.glob('%s/%s/*beamspotmon.gif' % (dsname,taskname))
415 if len(monitoringFiles)>0:
416 for r in monitoringFiles:
417 f = r.split('/')[-1]
418 pdf = f[:-3]+'pdf'
419 if not f in files.split():
420 files = ' '.join([files,f])
421 if not pdf in files.split():
422 files = ' '.join([files,pdf])
423 links += ' <a href="../files?u=%s/%s/%s">monitoring</a>' %(dsname,taskname,f)
424 links += ' (<a href="/jobfiles/%s/%s/%s">pdf</a>)' %(dsname,taskname,pdf)
425 t['RESULTFILES'] = files
426 t['RESULTLINKS'] = links
427
428 fieldNameString = ''
429 params = []
430 for fieldName in t.keys():
431 newFieldName = fieldName
432 if fieldName == 'TASKID':
433 continue # Skip old primary key
434 elif fieldName == 'COMMENT':
435 newFieldName = 'TASKCOMMENT'
436 if params:
437 fieldNameString += ','
438 params.append(',')
439 fieldNameString += newFieldName
440 params.append(DbParam(t[fieldName]))
441 q = [ 'insert into TASKS (%s) values (' % fieldNameString ]
442 q.extend(params)
443 q.append(')')
444 taskman.execute(q, True)
445 nImported += 1
446 print()
447 print ('{:d} tasks imported'.format(nImported))
448 sys.exit(0)
449
450
451#
452# Set task status
453#
454if cmd == 'setstatus':
455 if len(cmdargs) != 3: parser.error('Command setstatus takes 3 arguments')
456 dsname = cmdargs[0]
457 taskname = cmdargs[1]
458 statusName = cmdargs[2].upper()
459
460 status = TaskManager.StatusCodes.get(statusName)
461 if status:
462 print ('Setting task status to {} (code {:d})'.format(statusName,status))
463 else:
464 sys.exit('ERROR: Illegal status code name {}'.format(statusName))
465 print()
466
467 with getTaskManager() as taskman:
468 try:
469 taskList = getFullTaskNames(taskman, dsname, taskname,
470 confirmWithUser=not options.batch,
471 addWildCards=not options.nowildcards)
472 except TaskManagerCheckError as e:
473 sys.exit(e)
474
475 n = 0
476 for t in taskList:
477 n += taskman.setValue(t[0], t[1], 'STATUS', status)
478 print ('%i task status entries updated\n' % (n))
479 sys.exit(0)
480
481
482#
483# Set database field
484#
485if cmd == 'setfield':
486 if len(cmdargs) != 4: parser.error('Command setfield takes 4 arguments')
487 dsname = cmdargs[0]
488 taskname = cmdargs[1]
489 fieldName = cmdargs[2].upper()
490 fieldValue = cmdargs[3]
491
492 print ('Setting field %s to: %s' % (fieldName,fieldValue))
493 print()
494 with getTaskManager() as taskman:
495 try:
496 [(dsname,task)] = getFullTaskNames(taskman, dsname, taskname,
497 requireSingleTask=True,
498 confirmWithUser=not options.batch,
499 addWildCards=not options.nowildcards)
500 except TaskManagerCheckError as e:
501 sys.exit(e)
502 n = taskman.setValue(dsname,task,fieldName,fieldValue)
503 print ('{:d} task status entries updated'.format(n))
504 sys.exit(0)
505
506
507#
508# Delete task entry
509#
510if cmd=='delete' and len(args)==3:
511 with getTaskManager() as taskman:
512 try:
513 taskList = getFullTaskNames(taskman,args[1],args[2],confirmWithUser=not options.batch,addWildCards=not options.nowildcards)
514 except TaskManagerCheckError as e:
515 print (e)
516 sys.exit(1)
517 n = 0
518 for t in taskList:
519 n += taskman.deleteTask(t[0],t[1])
520 print ('\n%i task entries deleted\n' % (n))
521 sys.exit(0)
522
523# List results for selected sets of tasks
524#
525if cmd=='listResults' and len(args)==3:
526 with getTaskManager() as taskman:
527 try:
528 taskList = getFullTaskNames(taskman,args[1],args[2],confirmWithUser=not options.batch,addWildCards=not options.nowildcards)
529 except TaskManagerCheckError as e:
530 print (e)
531 sys.exit(1)
532 for t in taskList:
533 print ('Listing results for task %s/%s ...' % (t[0],t[1]) )
534 print (taskman.getTaskValue(t[0],t[1],'RESULTFILES'))
535 print (taskman.getTaskValue(t[0],t[1],'RESULTLINKS'))
536 sys.exit(0)
537
538
539#
540# Clear results for selected sets of tasks
541# TODO: remove associated files as well (?)
542#
543if cmd=='deleteResults' and len(args)==3:
544 with getTaskManager() as taskman:
545 try:
546 taskList = getFullTaskNames(taskman,args[1],args[2],confirmWithUser=not options.batch,addWildCards=not options.nowildcards)
547 except TaskManagerCheckError as e:
548 print (e)
549 sys.exit(1)
550 for t in taskList:
551 print ('Deleting results for task %s/%s ...' % (t[0],t[1]) )
552 taskman.setValue(t[0],t[1],'RESULTFILES','')
553 taskman.setValue(t[0],t[1],'RESULTLINKS','')
554 sys.exit(0)
555
556
557#
558# Delete task (files and associated TaskManager entry)
559#
560if cmd=='deleteTask' and len(args)==3:
561 with getTaskManager() as taskman:
562 try:
563 [(dsname,task)] = getFullTaskNames(taskman,args[1],args[2],confirmWithUser=not options.batch,requireSingleTask=True,addWildCards=not options.nowildcards)
564 except TaskManagerCheckError as e:
565 print (e)
566 sys.exit(1)
567 dir = '/'.join([proddir,dsname,task])
568 print()
569 if os.path.exists(dir):
570 os.system('du -hs %s' % dir)
571 else:
572 print ('No task files found (no directory %s)' % dir)
573 if not options.batch:
574 a = input('\nDeleteing task entry and all files - ARE YOU SURE [n] ? ')
575 if a!='y':
576 print ("ERROR: Deletion aborted by user.")
577 sys.exit(1)
578 n = taskman.deleteTask(dsname,task)
579 print ('\n%i task entry deleted.' % (n))
580 print ('Deleting ',dir,' ...')
581 os.system('rm -rf %s' % dir)
582 sys.exit(0)
583
584if cmd=='deleteTask' and len(args)==2:
585 dsname = args[1]
586 taskname = ''
587 with getTaskManager() as taskman:
588 try:
589 taskList = getFullTaskNames(taskman,dsname,taskname,addWildCards=not options.nowildcards)
590 except TaskManagerCheckError as e:
591 print (e)
592 sys.exit(1)
593 print()
594 # print (" %-50s %s" % ('DATASET NAME','TASK NAME'))
595 # print (" %s" % (75*'-'))
596 # for t in taskList:
597 # print (" %-50s %s" % (t[0],t[1]) )
598 print ('\n%i task(s) found\n' % len(taskList))
599 n = 0
600 for t in taskList:
601 taskname = t[1]
602 print (" %-50s %s" % (dsname,taskname) )
603 dir = '/'.join([proddir,dsname,taskname])
604 print()
605 if os.path.exists(dir):
606 os.system('du -hs %s' % dir)
607 else:
608 print ('No task files found (no directory %s)' % dir)
609 if not options.batch:
610 a = input('\nDeleteing task entry and all files - ARE YOU SURE [n] ? ')
611 if a!='y':
612 print ("ERROR: Deletion aborted by user.")
613 sys.exit(1)
614 n += taskman.deleteTask(dsname,taskname)
615 print ('Deleting ',dir,' ...')
616 os.system('rm -rf %s' % dir)
617 print ('\n%i tasks deleted.' % (n))
618 sys.exit(0)
619
620if cmd=='notifyFailed' and len(args)<3:
621 if len(args)==2:
622 earliestUpdateTime = time.time()-float(args[1])
623 else:
624 earliestUpdateTime = 0
625
626 taskList = []
627 with getTaskManager() as taskman:
628 for t in taskman.taskIterDict('*',["where TASKNAME like '%%%s%%'" % options.runtaskname,
629 "and UPDATED >= ", DbParam(earliestUpdateTime),
630 "and (STATUS = %i or STATUS = %i)" %(TaskManager.StatusCodes['FAILED'], TaskManager.StatusCodes['POSTPROCFAILED']),
631 "order by RUNNR desc"]):
632
633 # Change status to string version
634 t['STATUS'] = [k for k, v in TaskManager.StatusCodes.items() if v == t['STATUS']][0]
635 taskList.append(t)
636
637 if taskList:
638
639 dsWidth = len(max([t['DSNAME'] for t in taskList],key=len))
640 taskWidth = len(max([t['TASKNAME'] for t in taskList],key=len))
641 statusWidth = len(max([t['STATUS'] for t in taskList],key=len))
642
643 bodyFormat = '%%(DSNAME)%ss %%(TASKNAME)%ss %%(STATUS)%ss' %(dsWidth, taskWidth, statusWidth)
644
645 mailBody = 'The following %s tasks have reported failures' % len(taskList)
646 if len(args)==2:
647 hours = round(float(args[1])/3600.)
648 mailBody += ' in the last %s hours' % hours
649 mailBody += ':\n\n'
650 mailBody += '\n'.join([bodyFormat % t for t in taskList])
651 stat = os.system('source /afs/cern.ch/user/a/atlidbs/cron/mailwrapper; mailwrapper "[atlidbs] %s tasks report failures" "%s"' %(len(taskList), mailBody)) >> 8
652
653 if stat:
654 print ('\nERROR: Unable to send mail\n')
655
656 sys.exit(0)
657
658#
659# Debugging (for experts only!)
660#
661# This must be the last command. If we end up here, it's either debugging
662# or an illegal command.
663#
664if cmd=='debug' and len(args)==1:
665 taskman = getTaskManager()
666 taskman.debug = True
667 os.environ['PYTHONINSPECT'] = '1'
668 print()
669 print ('Entering python shell. taskman is the TaskManager object. Be careful!')
670 print()
671else:
672 print ('ERROR: Illegal command or number of arguments')
673 sys.exit(1)
int upper(int c)
void print(char *figname, TCanvas *c1)
#define max(a, b)
Definition cfImp.cxx:41
getTaskManager(dbconn=None)
Definition taskman.py:64
IovVectorMap_t read(const Folder &theFolder, const SelectionCriterion &choice, const unsigned int limit=10)