ATLAS Offline Software
DQWebDisplayMod.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
4 # -*- coding: utf-8 -*-
5 
6 import os, shutil
7 import time
8 from time import sleep
9 from DataQualityUtils.dqu_subprocess import apply as _local_apply
10 
11 
12 CWD = os.getcwd()
13 
14 import sys
15 import ROOT
16 
19 from ROOT import gSystem
20 
21 from DataQualityUtils.handimod import handiWithComparisons
22 from DataQualityUtils.handimod import makeCSSFile
23 from DataQualityUtils.SingleAppInstance import SingleAppInstance
24 from DataQualityUtils.hancoolmod import hancool
25 from DataQualityUtils.DQHistogramMergeMod import DQHistogramMerge
26 import DataQualityUtils.HanMetadata
27 
28 gSystem.Load("libdqm_core")
29 gSystem.Load("libDataQualityInterfaces")
30 from ROOT import dqutils
31 
32 os.chdir(CWD)
33 
34 
35 VERSION = '$Id: DQWebDisplay.py 529090 2012-12-05 22:32:03Z ponyisi $'
36 FROMEMAIL = 'atlasdqm@cern.ch'
37 
38 # return code
39 LOCK_ERROR = 5
40 
41 
42 
43 os.environ['TDAQ_ERS_NO_SIGNAL_HANDLERS'] = '1'
44 
45 
46 class LockAcquisitionException(Exception):
47  def __init__(self, msg):
48  super(LockAcquisitionException,self).__init__(msg)
49 
50 def DQWebDisplay( inputFilePath, runAccumulating, c ):
51 
52  print("")
53  print("SVN version:")
54  print(VERSION)
55 
56  # we use the multiprocessing module to isolate code that possibly
57  # has memory leaks, so they don't build up over time
58 
59  if isinstance(c.server, str):
60  if c.server == '':
61  c.server = []
62  else:
63  c.server = [c.server]
64 
65  if c.server != [] or c.webHandoffDir != "" or c.lockFile == '':
66  print("")
67  print("Lockfile is disabled")
68  print("")
69  instance = None
70  else:
71  while True:
72  try:
73  instance = SingleAppInstance( c.htmlDir + "/" + c.lockFile, True )
74  islocked = instance.acquire()
75  except SingleAppInstance.FileLockAcquisitionError as e:
76  print('=========================================================================')
77  print('Cannot acquire lock on', c.htmlDir)
78  print('This usually means either')
79  print(' -> the directory does not exist,')
80  print(' -> you do not have the required permissions, or')
81  print(' -> the directory is out of space.')
82  print('If you ran into this error while trying to test the web display, please')
83  print('read the instructions at:')
84  print('https://twiki.cern.ch/twiki/bin/view/Atlas/DQOperationalRecipes#Obtain_SVN_and_disk_write_permis')
85  print()
86  print('Explicit error:', e)
87  print('=========================================================================')
88  sys.exit(1)
89  if islocked:
90  break
91  print("Another instance is running; waiting 60 seconds...")
92  sleep(60)
93 
94 
98 
99  #javaScriptLoc = c.htmlWeb + "/" + javaScript
100  #HjavaScriptLoc = c.htmlWeb + "/" + HjavaScript
101  allDirsScriptLoc = c.htmlWeb #+ "/" + allDirsScript
102  runlistLoc = c.htmlWeb + "/" + c.runlist
103 
104  compare = True # Create the compare button
105  #history = True # Create the history button
106  browserMenu = True # Use the menu interface
107 
108  if ( c.hanResultsDir.rfind("/")!=(len(c.hanResultsDir)-1) ):
109  c.hanResultsDir+="/"
110 
111  if ( c.htmlDir.rfind("/")!=(len(c.htmlDir)-1) ):
112  c.htmlDir+="/"
113 
114  inputFileName = inputFilePath
115  i = inputFilePath.rfind("/")
116  if( i != -1 ):
117  inputFileName = inputFilePath[i+1:]
118 
119  runid = 99999999
120  shortStream = "NoStream"
121  amitag = None
122  procpass = int(sys.argv[3])
123 
124  if c.config == "RTT":
125  shortStream = time.strftime("%A")
126  else:
127  fields = inputFileName.split(".")
128  if len(fields) >= 3:
129  runid = int(fields[1])
130  shortStream = fields[2]
131  if len(fields) >= 6:
132  amitag = fields[5]
133 
134  if runAccumulating:
135  print("")
136  print("Searching for existing histogram cache to merge with input histograms...")
137  try:
138  inputFilePath = _local_apply(mergeAndCache, ( inputFilePath, runid, shortStream, c.histogramCache ) )
139  except LockAcquisitionException:
140  sys.exit(LOCK_ERROR)
141  shortStream = "tmp_" + shortStream
142  elif c.histogramCache != "":
143  cacheFile, version = findCacheFile( inputFilePath, runid, shortStream, c.histogramCache )
144  if cacheFile != "":
145  print("")
146  print("Removing cached histograms used during accumulation mode")
147  try:
148  while cacheFile != '':
149  fullCachePath = c.histogramCache + "/" + cacheFile
150  os.unlink( fullCachePath )
151  cacheFile, version = findCacheFile( inputFilePath, runid, shortStream, c.histogramCache )
152  except OSError:
153  pass
154 
155  stream = shortStream
156  if len(sys.argv) >= 5:
157  stream = repr(procpass) + "/" + shortStream
158 
159  outputHanResultsDir = c.hanResultsDir + stream + '/run_' + repr(runid)
160  outputHtmlDir = c.htmlDir + stream + "/"
161 
162  if c.server != [] or c.webHandoffDir != "" or c.eosResultsDir:
163  print("Writing all output to \'./\'; will copy at the end to ", end='')
164  if c.webHandoffDir != "":
165  print("a handoff directory:", c.webHandoffDir)
166  else:
167  print("the web server(s):", ', '.join(c.server))
168  print("")
169  outputHanResultsDir = "./han_results/" + stream + '/run_' + repr(runid)
170  outputHtmlDir = "./www/" + stream + "/"
171 
172  makeOutputDirectory( outputHanResultsDir )
173  makeOutputDirectory( outputHtmlDir )
174 
175  total=_local_apply(getHanResults, ( inputFilePath, outputHanResultsDir, inputFilePath, c.hcfg, c.hcfg_min10, c.hcfg_min30 ))
176  fileList=total.rsplit('\n')
177  if amitag is not None:
178  addAmiTags(fileList, amitag)
179 
180  number=len(fileList)
181  if (len(fileList[number-1])<1): # last line is empty
182  number-=1
183 
184  # find run number to create index.html in run-dir
185  runfile=fileList[0].rsplit()
186  if (len(runfile) == 0):
187  print("ERROR: TFile has no \"run_*\" directories. The input monitoring file is not organized for production use,")
188  print("probably because AthenaMonitoring is not configured properly. Exiting.\n")
189  sys.exit(1)
190 
191  xferFileList = []
192  for allLines in fileList:
193  splitLine = allLines.rsplit()
194  if len(splitLine) >= 1:
195  xferFileList.append( splitLine[0] + "\n" )
196 
197  # invoke hancool if appropriate
198  runNumber = runfile[1]
199  rN=runNumber.lstrip("run_")
200  if not runAccumulating:
201  print("Getting COOL authentications")
202 # if c.auth:
203 # os.environ['CORAL_AUTH_PATH'] = c.auth
204 # else:
205 # home = os.environ.get('HOME')
206 # os.environ['CORAL_AUTH_PATH'] = home+"/private"
207 
208  # write monitor comparison results to cool
209  # MB : 29.05.2008
210  if 'COOLUPLOADS' in os.environ:
211  uploadAllowed = (os.environ['COOLUPLOADS'] == '1')
212  else:
213  uploadAllowed = True
214 
215  if not uploadAllowed:
216  print('hancool run and upload to DB switched off by request')
217 
218  if (uploadAllowed and c.dbConnection):
219  print("")
220  print("Now calling hancool ...")
221  #stream = os.path.basename(outputHanResultsDir)
222  if '_' in stream: stream = stream.split('_',1)[-1]
223  if amitag is not None and 'x' in amitag and stream.startswith('express'): # this is ESn processing
224  dbTagName = c.dbTagNameESn
225  isESn = True
226  else:
227  dbTagName = c.dbTagName
228  isESn = False
229  if '%' in dbTagName:
230  # this is a little fragile
231  uploadTag = dbTagName % { 'stream': stream,
232  'amitag': amitag,
233  'procpass': procpass }
234  doUpload = True
235  else:
236  uploadTag = dbTagName
237  doUpload = ('-%s-' % stream in uploadTag)
238 
239  if (doUpload):
240  print('isESn?', isESn)
241  _local_apply(hancool, (int(rN),outputHanResultsDir,c.dbConnection,isESn))
242 
243 
244  if c.server != []:
245  failures = 0
246  for server in c.server:
247  print("Transfering han files to server: ", server)
248  success = transferFilesToServer( xferFileList[:], "./han_results/", c.hanResultsDir, server )
249  if success:
250  print("Done.")
251  print("")
252  else:
253  failures += 1
254  print("FAILED!", end='')
255  if c.emailWarnings:
256  email('The transfer of han files\n\n' +
257  ''.join(xferFileList) +
258  '\nto server ' + server +
259  ' failed. This may indicate that this server is down.\n'
260  'Please investigate as soon as possible!',
261  'WARNING! File transfer from Tier-0 failed',
262  FROMEMAIL,
263  'hn-atlas-data-quality-operations@cern.ch'
264  )
265  print("Email sent...")
266  else:
267  print("")
268  print("")
269  if failures == len(c.server):
270  print("SERIOUS PROBLEM: file transfers failed to ALL defined servers")
271  print("These are:", ', '.join(c.server))
272  print("Will die so as to alert Tier-0 shifter")
273  raise IOError('tarfile ssh transfer failed')
274  if c.eosResultsDir != "":
275  print("Transfering han files to EOS")
276  failures = 0
277  eos_attempts = 3
278  while failures < (eos_attempts+1) :
279  success_EOS = transferFilesToEOS( xferFileList[:], "./han_results/", c.eosResultsDir )
280  if success_EOS:
281  break
282  failures += 1
283  sleep(5**failures)
284  if success_EOS:
285  print("Done.")
286  print("")
287  else:
288  print("FAILED!",)
289  raise IOError("Transfer to /eos failed after {} attempts".format(failures))
290  if c.emailWarnings:
291  email('The transfer of han files\n\n' +
292  ''.join(xferFileList) +
293  '\nto EOS failed.\n'
294  'Please investigate as soon as possible!',
295  'WARNING! File transfer from Tier-0 failed',
296  FROMEMAIL,
297  'hn-atlas-data-quality-operations@cern.ch'
298  )
299  print("Email sent...")
300  else:
301  print("")
302 
303 
304  if c.doHandi:
305  rundir=outputHtmlDir+runNumber+"/"
306  makeOutputDirectory( rundir )
307 
308 
309  now = time.localtime()
310  lastUpdate = "Last Update: "+time.strftime('%Y-%m-%d %H:%M %Z', now)
311 
312 
313  g=open(outputHtmlDir+runNumber +'/index.html','w')
314  g.write('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n')
315  g.write('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n')
316  g.write('<head>\n')
317  g.write('<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />\n')
318  g.write('<title>run ' +rN+ ' ' + stream + '</title>\n')
319  g.write('<link rel="stylesheet" href="AutomChecks.css" type="text/css" />\n')
320  g.write('</head>\n')
321  g.write('<body>\n')
322  g.write('<font class="DQGroup">[<a href="#" onclick="history.go(-1);return false;">Back</a>]</font>\n')
323  g.write('<h1>Run '+rN+', ' + stream + '</h1>\n\n')
324 
325  makeCSSFile( rundir, "", "" )
326 
327  if number >0:
328  min10List = []
329  min30List = []
330  for x in range(0,number):
331  sp=fileList[x].rsplit()
332  if (len(sp)==2): # the run file
333  print("Running handi on " + sp[0] + ":")
334  print('handi("Run '+rN+ ', '+ stream + '",' + sp[0] + ','+rundir+'/run)')
335  _local_apply(handiWithComparisons, ( ('Run '+rN+', ' + stream), sp[0], (rundir+"/run"), runlistLoc, compare, browserMenu, allDirsScriptLoc) )
336  print("")
337  else:# a minutes file
338  if sp[1].find("lowStat")!=-1: # low statistics interval
339  print("Running handi on " + sp[0] + ":")
340  print('handi("Run '+rN+ ', '+sp[1]+', ' + stream + '",' + sp[0] + ','+rundir+sp[3]+')')
341  _local_apply(handiWithComparisons, ( ('Run '+rN+ ', '+sp[1]+', ' + stream), sp[0], (rundir+sp[3]), runlistLoc, compare, browserMenu, allDirsScriptLoc) )
342  print("")
343  mN = sp[1].removeprefix("lowStat_")
344  min10List.append( (sp[3], mN) )
345  elif sp[1].find("medStat")!=-1: # medium statistics interval
346  print("Running handi on " + sp[0] + ":")
347  print('handi("Run '+rN+ ', '+sp[1]+', ' + stream + '",' + sp[0] + ','+rundir+sp[3]+')')
348  _local_apply(handiWithComparisons, (('Run '+rN+ ', '+sp[1]+', ' + stream), sp[0], (rundir+sp[3]), runlistLoc, compare, browserMenu, allDirsScriptLoc))
349  print("")
350  mN = sp[1].removeprefix("medStat_")
351  min30List.append( (sp[3], mN) )
352 
353  #min10List.sort(key=lambda x: int(x[1]))
354  #min30List.sort(key=lambda x: int(x[1]))
355 
356  g.write('<table>\n')
357 
358  if len(min10List) == 0 and len(min30List) == 0:
359  g.write('<tr>\n')
360  g.write(' <td width=120>\n')
361  g.write(' <a href="run/index.html">Entire Run</a>\n')
362  g.write(' </td>\n')
363  g.write('</tr>\n')
364  elif len(min10List) == 0 or len(min30List) == 0:
365  minList = []
366  blockName = ""
367  if len(min10List) == 0:
368  minList = min30List
369  blockName = "medium stat interval"
370  else:
371  minList = min10List
372  blockName = "low stat interval"
373  g.write('<tr>\n')
374  g.write(' <td rowspan='+ str(len(minList)) +' valign="top" width=120>\n')
375  g.write(' <a href="run/index.html">Entire Run</a>\n')
376  g.write(' </td>\n')
377  margin = ""
378  minList.sort()
379  for page, nMin in minList:
380  g.write(margin)
381  g.write(' <td width=200>\n')
382  if nMin.find('merged_')!=-1:
383  g.write(' <a href="' + page + '/index.html">' + nMin + '</a>\n')
384  else:
385  g.write(' <a href="' + page + '/index.html">' + blockName + ' ' + nMin + '</a>\n')
386  g.write(' </td>\n')
387  margin = '</tr>\n<tr>\n'
388  g.write('</tr>\n')
389  else:
390  g.write('<tr>\n')
391  g.write(' <td rowspan='+ str(len(min10List)) +' valign="top" width=120>\n')
392  g.write(' <a href="run/index.html">Entire Run</a>\n')
393  g.write(' </td>\n')
394  margin = ""
395  count = 0
396  min10List.sort()
397  for page10, nMin10 in min10List:
398  g.write(margin)
399  nMin30 = 0
400  if count % 3 == 0:
401  iMin30 = (count // 3)
402  page30, nMin30 = min30List[iMin30]
403  g.write(' <td rowspan=3 valign="top" width=200>\n')
404  g.write(' <a href="' + page30 + '/index.html">medium stat interval ' + nMin30 + '</a>\n')
405  g.write(' </td>\n')
406  g.write(' <td width=200>\n')
407  g.write(' <a href="' + page10 + '/index.html">low stat interval ' + nMin10 + '</a>\n')
408  g.write(' </td>\n')
409  count = count + 1
410  margin = '</tr>\n<tr>\n'
411  g.write('</tr>\n')
412 
413  g.write('</table>\n')
414 
415 
416  g.write('<br/>\n<font class=\"Note\">'+lastUpdate+'</font><br />\n')
417  g.write('</body>\n</html>')
418  g.close()
419 
420  if c.webHandoffDir != "":
421  print('Transfering web files to handoff directory')
422  transferDirectoryToHandoffDir( rundir, './www/', c.webHandoffDir, c )
423  elif c.server != []:
424  failures = 0
425  for server in c.server:
426  print("Transfering web files to server: ", server)
427  success = transferDirectoryToServer( rundir, "./www/", c.htmlDir, server )
428  if success:
429  print("Done.")
430  print("")
431  else:
432  failures += 1
433  if c.emailWarnings:
434  email('The transfer of web files\n'
435  + c.htmlDir +
436  '\nto server' + server +
437  'failed. This may indicate that this server is down.\n'
438  'Please investigate as soon as possible!',
439  'WARNING! File transfer from Tier-0 failed',
440  FROMEMAIL,
441  'hn-atlas-data-quality-operations@cern.ch'
442  )
443  print("FAILED!")
444  print("")
445  if failures == len(c.server):
446  print("SERIOUS PROBLEM: web files transfer failed to ALL defined servers")
447  print("These are:", ', '.join(c.server))
448  print("Will die so as to alert Tier-0 shifter")
449  raise IOError('Directory ssh transfer failed')
450 
451 
452  #markCompleteTransfer( rundir, './www/', c.htmlDir, c )
453 
454  if c.webHandoffDir == '':
455  print("Generating index files...")
456  for server in c.server:
457  generateDQIndexFiles( server, c.htmlDir, c.config, c.indexFile, c.runlist, c.htmlWeb )
458 
459  if runAccumulating:
460  os.unlink(inputFilePath)
461 
462  if instance is not None:
463  instance.release()
464  return fileList
465 
466 
467 def makeOutputDirectory( dirname ):
468  if( not os.access(dirname,os.F_OK) ):
469  try:
470  os.umask(0o002)
471  os.makedirs(dirname)
472  except os.error:
473  print('Cannot create directory "' + dirname + '"; exiting.')
474  sys.exit(-1)
475 
476 
477 def getHanResults(inputFilePath, *args):
478  of = dqutils.MonitoringFile(inputFilePath)
479  rv = of.getHanResults(*args)
480  return rv
481 
482 def mergeAndCache( inputFilePath, run, stream, cache ):
483  if cache == "":
484  print("Cannot use cache: No cache directory defined")
485  print("")
486  return inputFilePath
487 
488  MAX_LOCK_TRIES = 3
489 
490  islocked = False
491  for i in range(MAX_LOCK_TRIES):
492  try:
493  lockfilename = os.path.join(cache, 'lock_%s_%s' % (run, stream))
494  instance = SingleAppInstance( lockfilename, True )
495  islocked = instance.acquire()
496  except SingleAppInstance.FileLockAcquisitionError as e:
497  print('Unable to start to acquire cache directory lock! Bailing')
498  raise e
499  if islocked:
500  break
501  else:
502  print('Unable to acquire cache directory lock; waiting 60 seconds; try', (i+1))
503  sleep(60)
504 
505  if not islocked:
506  raise LockAcquisitionException(' '.join(['Tried', repr(MAX_LOCK_TRIES), 'times to acquire cache lock; exiting now']))
507 
508  cacheFile, version = findCacheFile( inputFilePath, run, stream, cache )
509  fullCachePath = ""
510  if cacheFile != "":
511  print("Found cached histograms: ")
512  print(" dir: ", cache)
513  print(" file: ", cacheFile)
514  fullCachePath = cache + "/" + cacheFile
515  else:
516  print("Did not find cached histograms: ")
517  print(" dir: ", cache)
518 
519  inputFileName = inputFilePath
520  i = inputFilePath.rfind("/")
521  if( i != -1 ):
522  inputFileName = inputFilePath[i+1:]
523  updatedFile = inputFileName + ".CACHE_" + str(version+1)
524  print("Creating updated cache: ")
525  print(" file: ", updatedFile)
526  fullUpdatedFile = cache + "/" + updatedFile
527  print("")
528 
529  if fullCachePath != '':
530  print('Copying previous cache to local directory ...', end='')
531  shutil.copy(fullCachePath, cacheFile)
532  print('done\n')
533 
534  mergeListName = "cache_merge.list"
535  f = open( mergeListName, 'w' )
536  txtstr = ""
537  txtstr += "%s\n" % cacheFile
538  txtstr += "%s\n" % inputFilePath
539  f.write(txtstr)
540  f.close()
541 
542  print("Running DQHistogramMerge...")
543  DQHistogramMerge( mergeListName, updatedFile, False )
544  print("Finished DQHistogramMerge.")
545  print("")
546 
547  if fullCachePath != '':
548  print('Deleting local copy of old cache ...', end='')
549  os.unlink(cacheFile)
550  print('done\n')
551 
552  print('Copying new cache to cache directory ...', end='')
553  shutil.copy(updatedFile, fullUpdatedFile)
554  print('done\n')
555 
556  # make copy so we can process further without interference
557  # from other jobs
558  #localFullUpdatedFile = fullUpdatedFile + '-local'
559  #print('Copying to new file', localFullUpdatedFile, '...', end='')
560  #shutil.copy(updatedFile, localFullUpdatedFile)
561  #print('done')
562 
563  os.unlink( mergeListName )
564  if fullCachePath != "":
565  os.unlink( fullCachePath )
566 
567  instance.release()
568 
569  print('Now running histogram postprocessing ...')
570  from DataQualityUtils import DQPostProcessMod
571  DQPostProcessMod.DQPostProcess( updatedFile, isIncremental=True )
572 
573  return updatedFile
574 
575 def verifyHasRunKey(inputFile, run):
576  f = ROOT.TFile(inputFile, 'READ')
577  if f.IsOpen():
578  if f.Get('run_%s' % run):
579  f.Close()
580  return True
581  f.Close()
582  print('WARNING: cache file %s appears to be corrupted' % inputFile)
583  return False
584 
585 def findCacheFile( inputFilePath, run, stream, cache ):
586  fileDict = { }
587  for root, dirs, files in os.walk(cache):
588  removeDir = []
589  for name in dirs:
590  removeDir.append(name)
591  for fileName in files:
592  if fileName.find(str(run)) == -1:
593  continue
594  if fileName.find(stream) == -1:
595  continue
596  vi = fileName.rfind(".CACHE_")
597  if vi != -1:
598  try:
599  v = int(fileName[vi+7:])
600  fileDict[v] = fileName
601  except Exception:
602  pass
603  for name in removeDir:
604  dirs.remove(name)
605  for v in reversed(sorted([key for key in fileDict.keys() if verifyHasRunKey(cache+'/'+fileDict[key], run)])):
606  return fileDict[v], v
607 
608  return "", 0
609 
610 
611 def transferDirectoryToHandoffDir( dirName, localDir, targetDir, config ):
612  import time, shutil, glob
613  import six.moves.configparser as configparser
614  targetfname = repr(int(time.time())) + '-' + repr(os.getpid()) \
615  + '-' + os.uname()[1] + '.tgz'
616  targetfile = os.path.join(targetDir, targetfname)
617 
618  print('Creating tarball', targetfname, '...')
619  parser = configparser.ConfigParser()
620  parser.set('DEFAULT', 'target', config.htmlDir)
621  parser.add_section('execute')
622  parser.set('execute', 'command', config.htmlDir + '/generateDQIndexFiles.py')
623  parser.set('execute', 'options', '"%s" "%s" "%s" "%s" "%s"' % (config.htmlDir, config.config, config.indexFile, config.runlist, config.htmlWeb))
624  dnames = glob.glob('%s/*/*/*' % localDir)
625  if len(dnames) != 1:
626  print('Unexpected glob result')
627  else:
628  parser.add_section('webdisplay')
629  parser.set('webdisplay', 'id', dnames[0][len(localDir):])
630  manifest = open(localDir + '/MANIFEST', 'w')
631  parser.write(manifest); manifest.close()
632 
633  #loctf = tarfile.open(targetfname, 'w:gz')
634 
638  print('About to execute', end='')
639  cmd = 'cd %s ; tar czf %s MANIFEST %s ; mv %s ..' % (localDir, targetfname, dirName.replace(localDir, ''), targetfname)
640  print(cmd)
641  rv = os.system(cmd)
642  if rv != 0:
643  raise IOError('Unable to create tarfile')
644 
645  print('done')
646 
647  print('Copying tarball to', targetDir, '...', end='')
648  shutil.copy(targetfname, targetfile)
649  print('done')
650  print('Removing local tarball copy ...', end='')
651  os.unlink(targetfname)
652  print('done\n')
653 
654 def transferDirectoryToServer( dirName, localDir, targetDir, server ):
655  username = "atlasdqm"
656  if 'USER' in os.environ.keys():
657  username = os.environ['USER']
658 
659  dirName = dirName.replace(localDir,"")
660 
661  cmd = ""
662  cmd += "tar -czf - -C " + localDir + " " + dirName
663  cmd += " | "
664  cmd += "ssh -l " + username + " " + server + " -x \"umask 002; cd " + targetDir + " ; tar -xzf - \""
665 
666  print(cmd)
667  rv = os.system( cmd )
668  #if rv != 0:
669  # raise IOError('Directory ssh transfer failed')
670  return rv == 0
671 
672 def markCompleteTransfer( dirName, localDir, targetDir, config ):
673  if config.webHandoffDir != '':
674  return
675  if config.server == '':
676  os.system('touch ' + os.path.join(dirName, 'complete'))
677  else:
678  dirName = dirName.replace(localDir, '')
679  username = "atlasdqm"
680  if 'USER' in os.environ.keys():
681  username = os.environ['USER']
682  cmd = "ssh -l " + username + " " + config.server + " -x \"umask 002; cd " + os.path.join(targetDir, dirName) + " ; touch complete\""
683 
684  print(cmd)
685  rv = os.system( cmd )
686  if rv != 0:
687  raise IOError('Directory complete transfer marking failed')
688 
689 
690 def transferFilesToServer( fileList, localDir, targetDir, server ):
691  username = "atlasdqm"
692  if 'USER' in os.environ.keys():
693  username = os.environ['USER']
694  tarFileListName = "./tarFileList.tmp"
695  t = open( tarFileListName, 'w' )
696  for xferFile in fileList:
697  os.system( "chmod 664 " + xferFile )
698  xferFile = xferFile.replace(localDir,"")
699  t.write(xferFile)
700 
701  t.close()
702 
703  cmd = ""
704  cmd += ("tar -czf - -C %s -T %s" % (localDir, tarFileListName))
705  cmd += " | "
706  cmd += "ssh -l " + username + " " + server + " -x \"umask 002; cd " + targetDir + " ; tar -xzf - \""
707 
708  print(cmd)
709  rv = os.system( cmd )
710  os.unlink(tarFileListName)
711  #if rv != 0:
712  # raise IOError('tarfile ssh transfer failed')
713  return rv == 0
714 
715 def transferFilesToEOS(fileList, localDir, eosResultsDir):
716  os.system('export XRD_REQUESTTIMEOUT=10')
717  run_eos = 0
718  for xferFile in fileList:
719  xferFile = xferFile.rstrip()
720  os.system( "chmod 664 " + xferFile )
721  file_name = xferFile.replace(localDir,"")
722 
723  eos = "xrdcp --force --path --silent " + xferFile + " "+ os.path.join(eosResultsDir, file_name)
724 
725  print(eos)
726  run_eos += os.system( eos )
727 
728  return run_eos == 0
729 
730 def retrieveFileFromServer( filePath, localDir, remoteDir, server ):
731  username = "atlasdqm"
732  if 'USER' in os.environ.keys():
733  username = os.environ['USER']
734 
735  filePath = filePath.replace(localDir,"")
736 
737  cmd = ""
738  cmd += "cd " + localDir
739  cmd += " ; "
740  cmd += "ssh -l " + username + " " + server + " -x \"cd " + remoteDir + " ; cat " + filePath + "\""
741  cmd += " > " + filePath
742 
743  print(cmd)
744  rv = os.system( cmd )
745  if rv != 0:
746  raise IOError('file retrieve failed')
747 
748 def generateDQIndexFiles( server, installPath, project, indexFile, runListFile, htmlAddress ):
749  username = "atlasdqm"
750  if 'USER' in os.environ.keys():
751  username = os.environ['USER']
752 
753  cmd = ""
754 
755  if server != "":
756  cmd += "ssh -l " + username + " " + server + " -x \"umask 002; "
757  cmd += installPath + "/generateDQIndexFiles.py " + installPath + " " + project + " " + indexFile + " "
758  cmd += runListFile + " " + htmlAddress + "\""
759  else:
760  cmd += installPath + "/generateDQIndexFiles.py " + installPath + " " + project + " " + indexFile + " "
761  cmd += runListFile + " " + htmlAddress
762 
763  print(cmd)
764  return os.system( cmd ) == 0
765 
766 def importConfiguration(modname):
767  from DataQualityConfigurations import getmodule
768  print('getting configuration', modname)
769  return getmodule(modname)
770 
771 def email(msg, subject, whofrom, addressees):
772  import smtplib
773  from email.mime.text import MIMEText
774  if isinstance(addressees, str):
775  addressees = [addressees]
776  email = MIMEText(msg)
777  email['Subject'] = subject
778  email['From'] = whofrom
779  email['To'] = ','.join(addressees)
780  serv = smtplib.SMTP()
781  serv.connect()
782  serv.sendmail(whofrom, addressees, email.as_string())
783  serv.quit()
784 
785 def addAmiTags(fileList, amitag):
786  fileList = [x.split()[0] for x in fileList if x != '']
787  print('Appending AMI information to metadata; tag =', amitag)
788  for f in fileList:
789  rf = ROOT.TFile.Open(f, 'UPDATE')
790  DataQualityUtils.HanMetadata.addMetadata(rf, 'AMI', {'AMI Tag': amitag})
791  rf.Close()
792 
793 def usage():
794  cmdi = sys.argv[0].rfind("/")
795  cmd = sys.argv[0][cmdi+1:]
796  print("")
797  print("Usage: ", cmd, "<data_file> <config> <processing_version> [run_accumulating [conditions_string]]")
798  print("")
799  print("This is a production utility; use TEST config for development and testing.")
800  print("")
801  print("Processing version is an integer, starting from 1 (not 0)")
802  print("")
803 
804 if __name__ == "__main__":
805  if len(sys.argv) < 4 or len(sys.argv) > 7:
806  usage()
807  sys.exit(0)
808 
809  inputFile = sys.argv[1] # data file
810  runAccumulating = False
811  if len(sys.argv) in (6,7):
812  if sys.argv[4] == "True" or sys.argv[4] == "1":
813  runAccumulating = True
814 
815  if len(sys.argv) == 7:
816  ROOT.gSystem.Load('libDataQualityInterfaces')
817  ROOT.dqi.ConditionsSingleton.getInstance().setCondition(sys.argv[5])
818 
819  configModule = ""
820 
821  if sys.argv[2] == "TEST":
822  configModule = "TestDisplay"
823  elif sys.argv[2] == "RTT":
824  configModule = "RTTDisplay"
825  elif sys.argv[2] == "TCT":
826  configModule = "TCTDisplay"
827  elif sys.argv[2] == "FDR1":
828  configModule = "fdr08_run1"
829  elif sys.argv[2] == "FDR2" or sys.argv[2] == "FDR2a" or sys.argv[2] == "FDR2b" or sys.argv[2] == "FDR2c":
830  configModule = "fdr08_run2"
831  elif sys.argv[2] == "Cosmics08":
832  configModule = "data08_cos"
833  elif sys.argv[2] == "SingleBeam08":
834  configModule = "data08_1beam"
835  else:
836  configModule = sys.argv[2]
837 
838  try:
839  cmod = importConfiguration(configModule)
840  except Exception:
841  print("Could not import configuration module \'" + configModule + "\'")
842  sys.exit(1)
843 
844  try:
845  config = cmod.dqconfig
846  except Exception:
847  print("Configuration object 'dqconfig' not defined in module \'" + configModule + "\'")
848  sys.exit(1)
849 
850 
851  DQWebDisplay( inputFile, runAccumulating, config )
852 
python.DQWebDisplayMod.makeOutputDirectory
def makeOutputDirectory(dirname)
Definition: DQWebDisplayMod.py:467
dqutils::MonitoringFile
Definition: MonitoringFile.h:54
vtune_athena.format
format
Definition: vtune_athena.py:14
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
generateDQIndexFiles
Definition: generateDQIndexFiles.py:1
python.DQWebDisplayMod.verifyHasRunKey
def verifyHasRunKey(inputFile, run)
Definition: DQWebDisplayMod.py:575
python.DQWebDisplayMod.DQWebDisplay
def DQWebDisplay(inputFilePath, runAccumulating, c)
Definition: DQWebDisplayMod.py:50
python.DQCDispatch.getmodule
def getmodule(modname)
Definition: DQCDispatch.py:10
python.handimod.makeCSSFile
def makeCSSFile(htmlDir, name, subname)
Definition: handimod.py:746
python.DQWebDisplayMod.LockAcquisitionException.__init__
def __init__(self, msg)
Definition: DQWebDisplayMod.py:47
python.DQWebDisplayMod.transferDirectoryToServer
def transferDirectoryToServer(dirName, localDir, targetDir, server)
Definition: DQWebDisplayMod.py:654
python.DQWebDisplayMod.importConfiguration
def importConfiguration(modname)
Definition: DQWebDisplayMod.py:766
python.DQWebDisplayMod.transferFilesToServer
def transferFilesToServer(fileList, localDir, targetDir, server)
Definition: DQWebDisplayMod.py:690
DQWebDisplay
Definition: DQWebDisplay.py:1
python.DQWebDisplayMod.findCacheFile
def findCacheFile(inputFilePath, run, stream, cache)
Definition: DQWebDisplayMod.py:585
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
PyAthena::repr
std::string repr(PyObject *o)
returns the string representation of a python object equivalent of calling repr(o) in python
Definition: PyAthenaUtils.cxx:106
python.DQWebDisplayMod.email
def email(msg, subject, whofrom, addressees)
Definition: DQWebDisplayMod.py:771
python.DQWebDisplayMod.transferFilesToEOS
def transferFilesToEOS(fileList, localDir, eosResultsDir)
Definition: DQWebDisplayMod.py:715
DerivationFramework::TriggerMatchingUtils::sorted
std::vector< typename T::value_type > sorted(T begin, T end)
Helper function to create a sorted vector from an unsorted one.
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
python.DQWebDisplayMod.getHanResults
def getHanResults(inputFilePath, *args)
Definition: DQWebDisplayMod.py:477
Trk::open
@ open
Definition: BinningType.h:40
python.DQWebDisplayMod.generateDQIndexFiles
def generateDQIndexFiles(server, installPath, project, indexFile, runListFile, htmlAddress)
Definition: DQWebDisplayMod.py:748
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:569
str
Definition: BTagTrackIpAccessor.cxx:11
dbg::print
void print(std::FILE *stream, std::format_string< Args... > fmt, Args &&... args)
Definition: SGImplSvc.cxx:70
python.DQWebDisplayMod.LockAcquisitionException
Get usable signal handlers.
Definition: DQWebDisplayMod.py:46
python.DQWebDisplayMod.mergeAndCache
def mergeAndCache(inputFilePath, run, stream, cache)
Definition: DQWebDisplayMod.py:482
python.DQWebDisplayMod.usage
def usage()
Definition: DQWebDisplayMod.py:793
python.DQWebDisplayMod.retrieveFileFromServer
def retrieveFileFromServer(filePath, localDir, remoteDir, server)
Definition: DQWebDisplayMod.py:730
DQHistogramMerge
Definition: DQHistogramMerge.py:1
python.DQWebDisplayMod.addAmiTags
def addAmiTags(fileList, amitag)
Definition: DQWebDisplayMod.py:785
python.DQWebDisplayMod.transferDirectoryToHandoffDir
def transferDirectoryToHandoffDir(dirName, localDir, targetDir, config)
Definition: DQWebDisplayMod.py:611
python.DQWebDisplayMod.markCompleteTransfer
def markCompleteTransfer(dirName, localDir, targetDir, config)
Definition: DQWebDisplayMod.py:672