CMS 3D CMS Logo

popcon2dropbox.py
Go to the documentation of this file.
1 import subprocess
2 import json
3 import netrc
4 import sqlite3
5 import os
6 import sys
7 import shutil
8 import logging
9 from datetime import datetime
10 
11 dbName = 'popcon'
12 dbFileName = '%s.db' %dbName
13 dbFileForDropBox = dbFileName
14 dbLogFile = '%s_log.db' %dbName
15 errorInImportFileFolder = 'import_errors'
16 dateformatForFolder = "%y-%m-%d-%H-%M-%S"
17 dateformatForLabel = "%y-%m-%d %H:%M:%S"
18 
19 auth_path_key = 'COND_AUTH_PATH'
20 
21 messageLevelEnvVar = 'POPCON_LOG_LEVEL'
22 fmt_str = "[%(asctime)s] %(levelname)s: %(message)s"
23 logLevel = logging.INFO
24 if messageLevelEnvVar in os.environ:
25  levStr = os.environ[messageLevelEnvVar]
26  if levStr == 'DEBUG':
27  logLevel = logging.DEBUG
28 logFormatter = logging.Formatter(fmt_str)
29 logger = logging.getLogger()
30 logger.setLevel(logLevel)
31 consoleHandler = logging.StreamHandler(sys.stdout)
32 consoleHandler.setFormatter(logFormatter)
33 logger.addHandler(consoleHandler)
34 
35 def checkFile():
36  # check if the expected input file is there...
37  # exit code < 0 => error
38  # exit code = 0 => skip
39  # exit code = 1 => import
40  if not os.path.exists( dbFileName ):
41  logger.error('The file expected as an input %s has not been found.'%dbFileName )
42  return -1
43 
44  empty = True
45  try:
46  dbcon = sqlite3.connect( dbFileName )
47  dbcur = dbcon.cursor()
48  dbcur.execute('SELECT * FROM IOV')
49  rows = dbcur.fetchall()
50  for r in rows:
51  empty = False
52  dbcon.close()
53  if empty:
54  logger.warning('The file expected as an input %s contains no data. The import will be skipped.'%dbFileName )
55  return 0
56  return 1
57  except Exception as e:
58  logger.error('Check on input data failed: %s' %str(e))
59  return -2
60 
61 def saveFileForImportErrors( datef, withMetadata=False ):
62  # save a copy of the files in case of upload failure...
63  leafFolderName = datef.strftime(dateformatForFolder)
64  fileFolder = os.path.join( errorInImportFileFolder, leafFolderName)
65  if not os.path.exists(fileFolder):
66  os.makedirs(fileFolder)
67  df= '%s.db' %dbName
68  dataDestFile = os.path.join( fileFolder, df)
69  if not os.path.exists(dataDestFile):
70  shutil.copy2(df, dataDestFile)
71  if withMetadata:
72  mf= '%s.txt' %dbName
73  metadataDestFile = os.path.join( fileFolder, mf )
74  if not os.path.exists(metadataDestFile):
75  shutil.copy2(df, metadataDestFile)
76  logger.error("Upload failed. Data file and metadata saved in folder '%s'" %os.path.abspath(fileFolder))
77 
78 def upload( args ):
79  destDb = args.destDb
80  destTag = args.destTag
81  comment = args.comment
82 
83  datef = datetime.now()
84 
85  # first remove any existing metadata file...
86  if os.path.exists( '%s.txt' %dbName ):
87  logger.debug('Removing already existing file %s' %dbName)
88  os.remove( '%s.txt' %dbName )
89 
90  # dump Metadata for the Upload
91  uploadMd = {}
92  uploadMd['destinationDatabase'] = destDb
93  tags = {}
94  tagInfo = {}
95  tags[ destTag ] = tagInfo
96  uploadMd['destinationTags'] = tags
97  uploadMd['inputTag'] = destTag
98  uploadMd['since'] = None
99  datelabel = datef.strftime(dateformatForLabel)
100  commentStr = ''
101  if not comment is None:
102  commentStr = comment
103  uploadMd['userText'] = '%s : %s' %(datelabel,commentStr)
104  with open( '%s.txt' %dbName, 'wb') as jf:
105  jf.write( json.dumps( uploadMd, sort_keys=True, indent = 2 ) )
106  jf.write('\n')
107 
108  # run the upload
109  uploadCommand = 'uploadConditions.py %s' %dbName
110  try:
111  pipe = subprocess.Popen( uploadCommand, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
112  stdout = pipe.communicate()[0]
113  print stdout
114  retCode = pipe.returncode
115  if retCode != 0:
116  saveFileForImportErrors( datef, True )
117  ret |= retCode
118  except Exception as e:
119  ret |= 1
120  logger.error(str(e))
121  return ret
122 
123 def copy( args ):
124  destDb = args.destDb
125  destTag = args.destTag
126  comment = args.comment
127 
128  datef = datetime.now()
129  destMap = { "oracle://cms_orcoff_prep/cms_conditions": "oradev", "oracle://cms_orcon_prod/cms_conditions": "onlineorapro" }
130  if destDb.lower() in destMap.keys():
131  destDb = destMap[destDb.lower()]
132  else:
133  logger.error( 'Destination connection %s is not supported.' %destDb )
134  return
135  # run the copy
136  note = '"Importing data with O2O execution"'
137  commandOptions = '--force --yes --db %s copy %s %s --destdb %s --synchronize --note %s' %(dbFileName,destTag,destTag,destDb,note)
138  copyCommand = 'conddb %s' %commandOptions
139  logger.info( 'Executing command: %s' %copyCommand )
140  try:
141  pipe = subprocess.Popen( copyCommand, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
142  stdout = pipe.communicate()[0]
143  print stdout
144  retCode = pipe.returncode
145  if retCode != 0:
146  saveFileForImportErrors( datef )
147  ret = retCode
148  except Exception as e:
149  ret = 1
150  logger.error( str(e) )
151  return ret
152 
153 def run( args ):
154  if args.auth is not None and not args.auth=='':
155  if auth_path_key in os.environ:
156  logger.warning("Cannot set authentication path to %s in the environment, since it is already set." %args.auth)
157  else:
158  logger.info("Setting the authentication path to %s in the environment." %args.auth)
159  os.environ[auth_path_key]=args.auth
160  if os.path.exists( '%s.db' %dbName ):
161  logger.info("Removing files with name %s" %dbName )
162  os.remove( '%s.db' %dbName )
163  if os.path.exists( '%s.txt' %dbName ):
164  os.remove( '%s.txt' %dbName )
165  command = 'cmsRun %s ' %args.job_file
166  command += ' destinationDatabase=%s' %args.destDb
167  command += ' destinationTag=%s' %args.destTag
168  command += ' 2>&1'
169  pipe = subprocess.Popen( command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
170  stdout = pipe.communicate()[0]
171  retCode = pipe.returncode
172  print stdout
173  logger.info('PopCon Analyzer return code is: %s' %retCode )
174  if retCode!=0:
175  logger.error( 'O2O job failed. Skipping upload.' )
176  return retCode
177 
178  ret = checkFile()
179  if ret < 0:
180  return ret
181  elif ret == 0:
182  return 0
183  if args.copy:
184  return copy( args )
185  return upload( args )
def upload(args)
def saveFileForImportErrors(datef, withMetadata=False)