CMS 3D CMS Logo

confdbOfflineConverter.py
Go to the documentation of this file.
1 #! /usr/bin/env python3
2 import sys, os
3 import re
4 import hashlib
5 import os.path
6 import tempfile
7 import requests
8 import shutil
9 import subprocess
10 import atexit
11 from collections import Counter
12 
14 
15  # the machine aliases and interfaces for the *online* database are
16  # cmsonr1-s.cms, cmsonr2-s.cms, cmsonr3-s.cms
17  # cmsonr1-v.cms, cmsonr2-v.cms, cmsonr3-v.cms
18  # but the -s and -v interfaces resolve to the same hosts.
19  # The actual machines and interfaces are
20  # CMSRAC11-S.cms, CMSRAC12-S.cms, CMSRAC21-S.cms
21  # CMSRAC11-V.cms, CMSRAC12-V.cms, CMSRAC21-V.cms
22 
23  # the possible machines and interfaces for the *offline* database are
24  # cmsr1-s.cms, cmsr2-s.cms, cmsr3-s.cms
25  # cmsr1-v.cms, cmsr2-v.cms, cmsr3-v.cms
26  # but the -s and -v interfaces resolve to the same hosts
27  # The actual machines and interfaces are
28  # itrac50011-s.cern.ch, itrac50063-s.cern.ch, itrac50078-s.cern.ch
29  # itrac50011-v.cern.ch, itrac50063-v.cern.ch, itrac50078-v.cern.ch
30 
31  databases = {}
32  databases['v1'] = {}
33  databases['v1']['offline'] = ( '-t', 'oracle', '-h', 'cmsr1-s.cern.ch', '-d', 'cms_cond.cern.ch', '-u', 'cms_hltdev_reader', '-s', 'convertMe!' )
34  databases['v1']['hltdev'] = databases['v1']['offline'] # for backwards compatibility
35  databases['v1']['online'] = ( '-t', 'oracle', '-h', 'cmsonr1-s.cms', '-d', 'cms_rcms.cern.ch', '-u', 'cms_hlt_r', '-s', 'convertMe!' )
36  databases['v1']['adg'] = ( '-t', 'oracle', '-h', 'cmsr1-s.cern.ch', '-d', 'cms_cond.cern.ch', '-u', 'cms_hlt_gui_r', '-s', 'convertMe!' )
37  databases['v1']['orcoff'] = databases['v1']['adg'] # for backwards compatibility
38  databases['v3'] = {}
39  databases['v3']['run2'] = ( '-t', 'oracle', '-h', 'cmsr1-s.cern.ch,cmsr2-s.cern.ch,cmsr3-s.cern.ch', '-d', 'cms_hlt.cern.ch', '-u', 'cms_hlt_gdr_r', '-s', 'convertMe!' )
40  databases['v3']['run3'] = ( '-t', 'oracle', '-h', 'cmsr1-s.cern.ch,cmsr2-s.cern.ch,cmsr3-s.cern.ch', '-d', 'cms_hlt.cern.ch', '-u', 'cms_hlt_v3_r', '-s', 'convertMe!' )
41  databases['v3']['dev'] = ( '-t', 'oracle', '-h', 'cmsr1-s.cern.ch,cmsr2-s.cern.ch,cmsr3-s.cern.ch', '-d', 'cms_hlt.cern.ch', '-u', 'cms_hlt_gdrdev_r', '-s', 'convertMe1!' )
42  databases['v3']['online'] = ( '-t', 'oracle', '-h', 'cmsonr1-s.cms', '-d', 'cms_rcms.cern.ch', '-u', 'cms_hlt_gdr_r', '-s', 'convertMe!' )
43  databases['v3']['adg'] = ( '-t', 'oracle', '-h', 'cmsonr1-adg1-s.cern.ch', '-d', 'cms_orcon_adg.cern.ch', '-u', 'cms_hlt_gdr_r', '-s', 'convertMe!' )
44 
45  #ip addresses, there is a bug where we cant do dns over the socks server, sigh
46  ips_for_proxy = {
47  'cmsr1-s.cern.ch' : '10.116.96.89',
48  'cmsr2-s.cern.ch' : '10.116.96.139',
49  'cmsr3-s.cern.ch' : '10.116.96.105'
50  }
51 
52  databases['v3-beta'] = dict(databases['v3'])
53  databases['v3-test'] = dict(databases['v3'])
54  databases['v2'] = dict(databases['v3'])
55  #old converter can only handle a single host so we modify the params accordingly
56  for dbkey in databases['v2']:
57  dbparams = databases['v2'][dbkey]
58  if dbparams[3]=='cmsr1-s.cern.ch,cmsr2-s.cern.ch,cmsr3-s.cern.ch':
59  databases['v2'][dbkey] = dbparams[0:3]+('cmsr1-s.cern.ch',)+dbparams[4:]
60 
61  @staticmethod
63  dir = os.path.realpath(dir)
64  if not os.path.isdir(dir):
65  try:
66  os.makedirs(dir)
67  except:
68  return None
69  return dir
70 
71 
72  def __init__(self, version = 'v3', database = 'run3', url = None, verbose = False,
73  proxy = False, proxyHost = 'localhost', proxyPort = '8080'):
74  self.verbose = verbose
75  self.version = version
76  self.baseDir = '/afs/cern.ch/user/c/confdb/www/%s/lib' % version
77  self.baseUrl = 'https://confdb.web.cern.ch/confdb/%s/lib' % version
78  self.jars = ( 'ojdbc8.jar', 'cmssw-evf-confdb-converter.jar' )
79  if version=='v2':
80  #legacy driver for run2 gui
81  self.jars = ( 'ojdbc6.jar', 'cmssw-evf-confdb-converter.jar' )
82  self.workDir = ''
83  self.proxy = proxy
84  self.proxyHost = proxyHost
85  self.proxyPort = proxyPort
86 
87  # check the schema version
88  if version not in self.databases:
89  # unsupported database version
90  sys.stderr.write( "ERROR: unsupported database version \"%s\"\n" % version)
91 
92  # check the database
93  if database in self.databases[version]:
94  # load the connection parameters for the given database
95  self.connect = self.databases[version][database]
96  else:
97  # unsupported database
98  sys.stderr.write( "ERROR: unknown database \"%s\" for version \"%s\"\n" % (database, version))
99  sys.exit(1)
100 
101  if self.proxy:
102  self.proxy_connect_args = ('--dbproxy', '--dbproxyport', self.proxyPort, '--dbproxyhost', self.proxyHost)
103  temp_connect = []
104  for entry in self.connect:
105  for key,item in self.ips_for_proxy.items():
106  entry = entry.replace(key,item)
107  temp_connect.append(entry.replace(key,item))
108  self.connect = tuple(temp_connect)
109  else:
110  self.proxy_connect_args = ()
111 
112  # check for a custom base URL
113  if url is not None:
114  self.baseUrl = url
115 
116  # try to read the .jar files from AFS, or download them
117  if os.path.isdir(self.baseDir) and all(os.path.isfile(self.baseDir + '/' + jar) for jar in self.jars):
118  # read the .jar fles from AFS
119  self.workDir = self.baseDir
120  else:
121  # try to use $CMSSW_BASE/tmp
122  self.workDir = OfflineConverter.CheckTempDirectory(os.path.join(os.environ['CMSSW_BASE'],'tmp','confdb',self.version))
123  if not self.workDir:
124  # try to use $TMP
125  self.workDir = OfflineConverter.CheckTempDirectory(os.path.join(os.environ['TMP'],'confdb',self.version))
126  if not self.workDir:
127  # create a new temporary directory, and install a cleanup callback
128  self.workDir = tempfile.mkdtemp()
129  atexit.register(shutil.rmtree, self.workDir)
130  # download the .jar files
131  version_website = requests.get(self.baseUrl+"/../confdb.version").text
132  jars_require_update = True
133  if os.path.exists(os.path.join(self.workDir,"confdb.version")):
134  with open(os.path.join(self.workDir,"confdb.version")) as f:
135  version_existing = f.read()
136  if version_existing==version_website:
137  jars_require_update = False
138 
139  if jars_require_update:
140  for jar in self.jars:
141  # download to a temporay name and use an atomic rename (in case an other istance is downloading the same file
142  handle, temp = tempfile.mkstemp(dir = self.workDir, prefix = jar + '.')
143  os.close(handle)
144  request = requests.get(self.baseUrl + '/' + jar)
145  with open(temp,'wb') as f:
146  f.write(request.content)
147  os.rename(temp, self.workDir + '/' + jar)
148  #jars updated, write their version
149  handle, temp = tempfile.mkstemp(dir = self.workDir, prefix = "confdb.version" + '.')
150  os.close(handle)
151  with open(temp,'w') as f:
152  f.write(version_website)
153  os.rename(temp,os.path.join(self.workDir,"confdb.version"))
154 
155  # setup the java command line and CLASSPATH
156  if self.verbose:
157  sys.stderr.write("workDir = %s\n" % self.workDir)
158  # use non-blocking random number source /dev/urandom (instead of /dev/random), see:
159  # http://blockdump.blogspot.fr/2012/07/connection-problems-inbound-connection.html
160  # deal with timezone region not found
161  # http://stackoverflow.com/questions/9156379/ora-01882-timezone-region-not-found
162  # increase the thread stack size from the default of 1 MB to work around java.lang.StackOverflowError errors, see
163  # man java
164  self.javaCmd = ( 'java', '-cp', ':'.join(self.workDir + '/' + jar for jar in self.jars), '-Djava.security.egd=file:///dev/urandom', '-Doracle.jdbc.timezoneAsRegion=false', '-Xss32M', 'confdb.converter.BrowserConverter' )
165 
166 
167  def query(self, *args):
168  args = self.javaCmd + self.connect + self.proxy_connect_args + args
169  if self.verbose:
170  sys.stderr.write("\n" + ' '.join(args) + "\n\n" )
171  sub = subprocess.Popen(
172  args,
173  stdin = None,
174  stdout = subprocess.PIPE,
175  stderr = subprocess.PIPE,
176  shell = False,
177  universal_newlines = True )
178  out,err = sub.communicate()
179  # 12_0 uses "HLTSchedule", confdb was changed to make this "schedule", this resets it back for this release
180  out = out.replace("fragment.schedule","fragment.HLTSchedule").replace("process.schedule","process.HLTSchedule")
181  return out,err
182 
183 def help():
184  sys.stdout.write("""Usage: %s OPTIONS
185 
186  --v1|--v2|--v3|--v3-beta|--v3-test (specify the ConfDB version [default: v3])
187 
188  --run3|--run2|--dev|--online|--adg (specify the target db [default: run3], online will only work inside p5 network)
189 
190  Note that for v1
191  --orcoff is a synonim of --adg
192  --offline is a synonim of --hltdev
193 
194  --configId <id> (specify the configuration by id)
195  --configName <name> (specify the configuration by name)
196  --runNumber <run> (specify the configuration by run number)
197  [exactly one of --configId OR --configName OR --runNumber is required]
198 
199  --cff (retrieve configuration *fragment*)
200  --input <f1.root[,f2.root]> (insert PoolSource with specified fileNames)
201  --input <files.list> (read a text file which lists input ROOT files)
202  --output <out.root> (insert PoolOutputModule w/ specified fileName)
203  --nopsets (exclude all globale psets)
204  --noedsources (exclude all edsources)
205  --noes (exclude all essources *and* esmodules)
206  --noessources (exclude all essources)
207  --noesmodules (exclude all esmodules)
208  --noservices (exclude all services)
209  --nooutput (exclude all output modules)
210  --nopaths (exclude all paths [+=referenced seqs&mods])
211  --nosequences (don't define sequences [+=referenced s&m])
212  --nomodules (don't define modules)
213  --psets <pset1[,pset2]> (include only specified global psets)
214  --psets <-pset1[,-pset2]> (include all global psets but the specified)
215  --essources <ess1[,ess2]> (include only specified essources)
216  --essources <-ess1[,-ess2]> (include all essources but the specified)
217  --esmodules <esm1[,esm2]> (include only specified esmodules)
218  --esmodules <-esm1[,-esm2]> (include all esmodules but the specified)
219  --services <svc1[,svc2]> (include only specified services)
220  --services <-svc1[,-svc2]> (include all services but the specified)
221  --paths <p1[,p2]> (include only specified paths)
222  --paths <-p1[,-p2]> (include all paths but the specified)
223  --streams <s1[,s2]> (include only specified streams)
224  --datasets <d1[,d2]> (include only specified datasets)
225  --sequences <s1[,s2]> (include sequences, referenced or not!)
226  --modules <p1[,p2]> (include modules, referenced or not!)
227  --blocks <m1::p1[,p2][,m2]> (generate parameter blocks)
228 
229  --verbose (print additional details)
230 """)
231 
232 
233 def main():
234  args = sys.argv[1:]
235  version = 'v3'
236  db = 'run3'
237  verbose = False
238 
239  if not args:
240  help()
241  sys.exit(1)
242 
243  if '--help' in args or '-h' in args:
244  help()
245  sys.exit(0)
246 
247  if '--verbose' in args:
248  verbose = True
249  args.remove('--verbose')
250 
251  arg_count = Counter(args)
252  db_count = arg_count['--v1'] + arg_count['--v2'] + arg_count['--v3'] + arg_count['--v3-beta'] + arg_count['--v3-test']
253  if db_count>1:
254  sys.stderr.write( 'ERROR: conflicting database version specifications: "--v1", "--v2", "--v3", "--v3-beta", and "--v3-test" are mutually exclusive options' )
255  sys.exit(1)
256 
257  if '--v1' in args:
258  version = 'v1'
259  db = 'offline'
260  args.remove('--v1')
261 
262  if '--v2' in args:
263  version = 'v2'
264  db = 'run2'
265  args.remove('--v2')
266 
267  if '--v3' in args:
268  version = 'v3'
269  db = 'run3'
270  args.remove('--v3')
271 
272  if '--v3-beta' in args:
273  version = 'v3-beta'
274  db = 'run3'
275  args.remove('--v3-beta')
276 
277  if '--v3-test' in args:
278  version = 'v3-test'
279  db = 'dev'
280  args.remove('--v3-test')
281 
282  proxy=False
283  proxy_host = "localhost"
284  proxy_port = "8080"
285  if '--dbproxy' in args:
286  proxy = True
287  args.remove('--dbproxy')
288  if '--dbproxyhost' in args:
289  proxy_host = args.pop(args.index('--dbproxyhost')+1)
290  args.remove('--dbproxyhost')
291  if '--dbproxyport' in args:
292  proxy_port = args.pop(args.index('--dbproxyport')+1)
293  args.remove('--dbproxyport')
294 
295 
296  _dbs = {}
297  _dbs['v1'] = [ '--%s' % _db for _db in OfflineConverter.databases['v1'] ] + [ '--runNumber' ]
298  _dbs['v2'] = [ '--%s' % _db for _db in OfflineConverter.databases['v2'] ] + [ '--runNumber' ]
299  _dbs['v3'] = [ '--%s' % _db for _db in OfflineConverter.databases['v3'] ] + [ '--runNumber']
300  _dbs['v3-beta'] = [ '--%s' % _db for _db in OfflineConverter.databases['v3-beta'] ] + [ '--runNumber' ]
301  _dbs['v3-test'] = [ '--%s' % _db for _db in OfflineConverter.databases['v3-test'] ] + [ '--runNumber' ]
302  _dbargs = set(args) & set(sum(_dbs.values(), []))
303 
304  if _dbargs:
305  if len(_dbargs) > 1:
306  sys.stderr.write( "ERROR: too many database specifications: \"" + "\", \"".join( _dbargs) + "\"\n" )
307  sys.exit(1)
308 
309  _arg = _dbargs.pop()
310  db = _arg[2:]
311  if db == 'runNumber':
312  db = 'adg'
313  else:
314  args.remove(_arg)
315 
316  if not db in OfflineConverter.databases[version]:
317  sys.stderr.write( "ERROR: database version \"%s\" incompatible with specification \"%s\"\n" % (version, db) )
318  sys.exit(1)
319 
320  converter = OfflineConverter(version = version, database = db, verbose = verbose,
321  proxy = proxy, proxyHost = proxy_host, proxyPort=proxy_port)
322  out, err = converter.query( * args )
323  if 'ERROR' in err:
324  sys.stderr.write( "%s: error while retriving the HLT menu\n\n%s\n\n" % (sys.argv[0], err) )
325  sys.exit(1)
326  else:
327  sys.stdout.write( out )
328 
329 
330 if __name__ == "__main__":
331  main()
confdbOfflineConverter.OfflineConverter.proxy
proxy
Definition: confdbOfflineConverter.py:82
align::Counter
std::function< unsigned int(align::ID)> Counter
Definition: AlignableIndexer.h:31
confdbOfflineConverter.OfflineConverter.baseUrl
baseUrl
Definition: confdbOfflineConverter.py:76
confdbOfflineConverter.OfflineConverter.ips_for_proxy
ips_for_proxy
Definition: confdbOfflineConverter.py:46
confdbOfflineConverter.OfflineConverter.javaCmd
javaCmd
Definition: confdbOfflineConverter.py:163
join
static std::string join(char **cmd)
Definition: RemoteFile.cc:17
confdbOfflineConverter.OfflineConverter.proxy_connect_args
proxy_connect_args
Definition: confdbOfflineConverter.py:101
python.cmstools.all
def all(container)
workaround iterator generators for ROOT classes
Definition: cmstools.py:25
confdbOfflineConverter.OfflineConverter.verbose
verbose
Definition: confdbOfflineConverter.py:73
confdbOfflineConverter.OfflineConverter
Definition: confdbOfflineConverter.py:13
mps_monitormerge.items
list items
Definition: mps_monitormerge.py:29
confdbOfflineConverter.OfflineConverter.version
version
Definition: confdbOfflineConverter.py:74
confdbOfflineConverter.OfflineConverter.__init__
def __init__(self, version='v3', database='run3', url=None, verbose=False, proxy=False, proxyHost='localhost', proxyPort='8080')
Definition: confdbOfflineConverter.py:72
confdbOfflineConverter.OfflineConverter.connect
connect
Definition: confdbOfflineConverter.py:94
confdbOfflineConverter.OfflineConverter.proxyHost
proxyHost
Definition: confdbOfflineConverter.py:83
confdbOfflineConverter.OfflineConverter.jars
jars
Definition: confdbOfflineConverter.py:77
confdbOfflineConverter.main
def main()
Definition: confdbOfflineConverter.py:233
confdbOfflineConverter.OfflineConverter.databases
databases
Definition: confdbOfflineConverter.py:31
confdbOfflineConverter.OfflineConverter.proxyPort
proxyPort
Definition: confdbOfflineConverter.py:84
main
Definition: main.py:1
confdbOfflineConverter.OfflineConverter.query
def query(self, *args)
Definition: confdbOfflineConverter.py:167
confdbOfflineConverter.help
def help()
Definition: confdbOfflineConverter.py:183
confdbOfflineConverter.OfflineConverter.workDir
workDir
Definition: confdbOfflineConverter.py:81
confdbOfflineConverter.OfflineConverter.CheckTempDirectory
def CheckTempDirectory(dir)
Definition: confdbOfflineConverter.py:62
confdbOfflineConverter.OfflineConverter.baseDir
baseDir
Definition: confdbOfflineConverter.py:75
python.rootplot.root2matplotlib.replace
def replace(string, replacements)
Definition: root2matplotlib.py:444