CMS 3D CMS Logo

conddblib.py
Go to the documentation of this file.
1 '''CMS Conditions DB Python library.
2 '''
3 
4 __author__ = 'Miguel Ojeda'
5 __copyright__ = 'Copyright 2013, CERN'
6 __credits__ = ['Giacomo Govi', 'Miguel Ojeda', 'Andreas Pfeiffer']
7 __license__ = 'Unknown'
8 __maintainer__ = 'Giacomo Govi'
9 __email__ = 'giacomo.govi@cern.ch'
10 
11 
12 import os
13 import hashlib
14 import logging
15 
16 import sqlalchemy
17 import sqlalchemy.ext.declarative
18 import enum
19 from sqlalchemy import Enum
20 
21 schema_name = 'cms_conditions'
22 dbuser_name = 'cms_conditions'
23 dbreader_user_name = 'cms_cond_general_r'
24 dbwriter_user_name = 'cms_cond_general_w'
25 logger = logging.getLogger(__name__)
26 
27 #authentication/authorization params
28 authPathEnvVar = 'COND_AUTH_PATH'
29 dbkey_filename = 'db.key'
30 dbkey_folder = os.path.join('.cms_cond',dbkey_filename)
31 
32 # frontier services
33 PRO ='PromptProd'
34 ARC ='FrontierArc'
35 INT ='FrontierInt'
36 DEV ='FrontierPrep'
37 # oracle read only services
38 ORAPRO = 'cms_orcon_adg'
39 ORAARC = 'cmsarc_lb'
40 # oracle masters
41 ORAINT = 'cms_orcoff_int'
42 ORADEV = 'cms_orcoff_prep'
43 ONLINEORAPRO = 'cms_orcon_prod'
44 ONLINEORAINT = 'cmsintr_lb'
45 
46 # Set initial level to WARN. This so that log statements don't occur in
47 # the absense of explicit logging being enabled.
48 if logger.level == logging.NOTSET:
49  logger.setLevel(logging.WARN)
50 
51 # Utility functions
52 def hash(data):
53  return hashlib.sha1(data.encode('ascii')).hexdigest()
54 
55 
56 # Constants
57 empty_label = '-'
58 
59 name_length = 100
60 description_length = 4000
61 hash_length = len(hash(''))
62 
63 web_experts_email = 'cms-cond-dev@cern.ch'
64 offline_db_experts_email = 'cms-offlinedb-exp@cern.ch'
65 offline_db_experts_phone = '+41 22 76 70817, or 70817 from CERN; check https://twiki.cern.ch/twiki/bin/viewauth/CMS/DBShifterHelpPage if it does not work; availability depends on the state of the LHC'
66 
67 contact_help = 'If you need assistance, please write an email to %s and %s. If you need immediate/urgent assistance, you can call the Offline DB expert on call (%s).' % (offline_db_experts_email, web_experts_email, offline_db_experts_phone)
68 database_help = '''
69  The database parameter (--db) refers to the database where the tool
70  will connect to read all the data. By default, the production account
71  (through Frontier) will be used.
72 
73  In subcommands which take a source and a destination, --db always refers to
74  the source, and --destdb to the destination. For both of them the following
75  rules apply.
76 
77  The database parameter can be an official alias, a filename or any
78  valid SQLAlchemy URL.
79 
80  The official aliases are the following strings (first column):
81 
82  Alias Level Database RO/RW Notes
83  ------------ ----------- ------------- ---------- -------------------------------
84 
85  pro Production Frontier (ADG) read-only Default.
86  arc Archive Frontier read-only
87  int Integration Frontier read-only
88  dev Development Frontier read-only
89  boost Production Frontier read-only
90  boostprep Development Frontier read-only
91 
92  orapro Production Oracle (ADG) read-only Password required.
93  oraarc Archive Oracle read-only Password required.
94  oraint Integration Oracle read-write Password required.
95  oradev Development Oracle read-write Password required.
96 
97  onlineorapro Production Oracle read-write Password required. Online only.
98  onlineoraint Online Int Oracle read-write Password required. Online only.
99 
100  Most of the time, if you are a regular user, you will want to read/copy
101  conditions from the Frontier production account. Therefore, you can omit
102  the --db parameter, unless you want to read from somewhere else,
103  e.g. from your local SQLite file.
104 
105  In addition, the parameter may be a filename (path) pointing to a local
106  SQLite file, e.g.
107 
108  file.db
109  relative/path/to/file.db
110  /absolute/path/to/file.db
111 
112  Finally, any valid SQLAlchemy URL can be used. This allows full
113  flexibility in cases where it may be needed, e.g.
114 
115  sqlite:// In-memory, volatile SQLite DB.
116  oracle://user@devdb11 Your private Oracle DB in devdb11 [*]
117 
118  [*] See https://account.cern.ch/ -> Services for more information
119  on personal Oracle accounts.
120 
121  For the official aliases, the password will be asked automatically
122  interactively. The same applies for Oracle URLs where the password
123  was not provided inside it, e.g.:
124 
125  oracle://user@devdb11 The tool will prompt you for the password.
126  oracle://user:pass@devdb11 Password inlined. [+]
127 
128  [+] Caution: Never write passwords in command-line parameters in
129  multi-user machines (e.g. lxplus), since other users can see them
130  in the process table (e.g. ps).
131 
132  This means that both the official aliases and the filenames are shortcuts
133  to the full SQLAlchemy URL equivalents, e.g. the following are the same:
134 
135  relative/path/to/file.db === sqlite:///relative/path/to/file.db
136  /absolute/path/to/file.db === sqlite:////absolute/path/to/file.db
137 '''
138 
139 def oracle_connection_string(db_service, db_schema ):
140  return 'oracle://%s/%s'%(db_service,db_schema)
141 
142 class Synchronization(enum.Enum):
143  any = 'any'
144  validation = 'validation'
145  mc = 'mc'
146  runmc = 'runmc'
147  hlt = 'hlt'
148  express = 'express'
149  prompt = 'prompt'
150  pcl = 'pcl'
151  offline = 'offline'
152 
153 synch_list = list(x.value for x in list(Synchronization))
154 
155 class TimeType(enum.Enum):
156  Run = 'Run'
157  Time = 'Time'
158  Lumi = 'Lumi'
159  Hash = 'Hash'
160  User = 'User'
161 
162 
163 # Schema definition
164 _Base = sqlalchemy.ext.declarative.declarative_base()
165 
166 def fq_name( schema_name, table_name ):
167  name = table_name
168  if schema_name is not None:
169  name = '%s.%s' %(schema_name, table_name)
170  return name
171 
172 db_models = {}
173 
174 class _Col(Enum):
175  nullable = 0
176  notNull = 1
177  pk = 2
178 
179 class DbRef:
180  def __init__(self,refType, refColumn):
181  self.rtype = refType
182  self.rcol = refColumn
183 
184 def fq_col( schema, table, column ):
185  fqn = '%s.%s' %(table, column)
186  if schema is not None:
187  fqn = '%s.%s' %(schema,fqn)
188  return fqn
189 
190 def make_dbtype( backendName, schemaName, baseType ):
191  members = {}
192  deps_reg = set()
193  dbtype_name = '%s_%s' %(baseType.__name__,backendName)
194  members['__tablename__'] = baseType.__tablename__
195  members['__table_args__'] = None
196  if schemaName is not None:
197  members['__table_args__'] = {'schema': schemaName }
198  for k,v in baseType.columns.items():
199  defColVal = None
200  if len(v)==3:
201  defColVal = v[2]
202  if isinstance(v[0],DbRef):
203  refColDbt = v[0].rtype.columns[v[0].rcol][0]
204  pk = (True if v[1]==_Col.pk else False)
205  if v[1]==_Col.pk:
206  members[k] = sqlalchemy.Column(refColDbt,sqlalchemy.ForeignKey(fq_col(schemaName,v[0].rtype.__tablename__,v[0].rcol)),primary_key=True)
207  else:
208  nullable = (False if v[1] == _Col.notNull else True)
209  members[k] = sqlalchemy.Column(refColDbt,sqlalchemy.ForeignKey(fq_col(schemaName,v[0].rtype.__tablename__,v[0].rcol)),nullable=nullable)
210  if v[0].rtype.__name__ not in deps_reg:
211  deps_reg.add(v[0].rtype.__name__)
212  reftype_name = '%s_%s' %(v[0].rtype.__name__,backendName)
213  members[(v[0].rtype.__name__).lower()] = sqlalchemy.orm.relationship(reftype_name)
214  else:
215  if v[1]==_Col.pk:
216  members[k] = sqlalchemy.Column(v[0],primary_key=True)
217  else:
218  nullable = (True if v[1]==_Col.nullable else False)
219  if defColVal is None:
220  members[k] = sqlalchemy.Column(v[0],nullable=nullable)
221  else:
222  members[k] = sqlalchemy.Column(v[0],nullable=nullable, default=defColVal)
223  dbType = type(dbtype_name,(_Base,),members)
224 
225  if backendName not in db_models.keys():
226  db_models[backendName] = {}
227  db_models[backendName][baseType.__name__] = dbType
228  return dbType
229 
230 def getSchema(tp):
231  if tp.__table_args__ is not None:
232  return tp.__table_args__['schema']
233  return None
234 
235 class Tag:
236  __tablename__ = 'TAG'
237  columns = { 'name': (sqlalchemy.String(name_length),_Col.pk),
238  'time_type': (sqlalchemy.Enum(*tuple(TimeType.__members__.keys())),_Col.notNull),
239  'object_type': (sqlalchemy.String(name_length),_Col.notNull),
240  'synchronization': (sqlalchemy.Enum(*tuple(Synchronization.__members__.keys())),_Col.notNull),
241  'description': (sqlalchemy.String(description_length),_Col.notNull),
242  'last_validated_time':(sqlalchemy.BIGINT,_Col.notNull),
243  'end_of_validity':(sqlalchemy.BIGINT,_Col.notNull),
244  'insertion_time':(sqlalchemy.TIMESTAMP,_Col.notNull),
245  'modification_time':(sqlalchemy.TIMESTAMP,_Col.notNull),
246  'protection_code':(sqlalchemy.Integer,_Col.notNull,0) }
247 
249  __tablename__ = 'TAG_METADATA'
250  columns = { 'tag_name': (DbRef(Tag,'name'),_Col.pk),
251  'min_serialization_v': (sqlalchemy.String(20),_Col.notNull),
252  'min_since': (sqlalchemy.BIGINT,_Col.notNull),
253  'modification_time':(sqlalchemy.TIMESTAMP,_Col.notNull) }
254 
256  __tablename__ = 'TAG_AUTHORIZATION'
257  columns = { 'tag_name': (DbRef(Tag,'name'),_Col.pk),
258  'access_type': (sqlalchemy.Integer,_Col.notNull),
259  'credential': (sqlalchemy.String(name_length),_Col.notNull),
260  'credential_type':(sqlalchemy.Integer,_Col.notNull) }
261 
262 class Payload:
263  __tablename__ = 'PAYLOAD'
264  columns = { 'hash': (sqlalchemy.CHAR(hash_length),_Col.pk),
265  'object_type': (sqlalchemy.String(name_length),_Col.notNull),
266  'data': (sqlalchemy.BLOB,_Col.notNull),
267  'streamer_info':(sqlalchemy.BLOB,_Col.notNull),
268  'version':(sqlalchemy.String(20),_Col.notNull),
269  'insertion_time':(sqlalchemy.TIMESTAMP,_Col.notNull) }
270 
271 
272 class IOV:
273  __tablename__ = 'IOV'
274  columns = { 'tag_name':(DbRef(Tag,'name'),_Col.pk),
275  'since':(sqlalchemy.BIGINT,_Col.pk),
276  'insertion_time':(sqlalchemy.TIMESTAMP,_Col.pk),
277  'payload_hash':(DbRef(Payload,'hash'),_Col.notNull) }
278 
279 
280 class GlobalTag:
281  __tablename__ = 'GLOBAL_TAG'
282  columns = { 'name':(sqlalchemy.String(name_length),_Col.pk),
283  'validity': (sqlalchemy.BIGINT,_Col.notNull),
284  'description':(sqlalchemy.String(description_length),_Col.notNull),
285  'release':(sqlalchemy.String(name_length),_Col.notNull),
286  'insertion_time':(sqlalchemy.TIMESTAMP,_Col.notNull),
287  'snapshot_time':(sqlalchemy.TIMESTAMP,_Col.notNull) }
288 
290  __tablename__ = 'GLOBAL_TAG_MAP'
291  columns = { 'global_tag_name':(DbRef(GlobalTag,'name'),_Col.pk),
292  'record':(sqlalchemy.String(name_length),_Col.pk),
293  'label':(sqlalchemy.String(name_length),_Col.pk),
294  'tag_name':(DbRef(Tag,'name'),_Col.notNull) }
295 
296 
297 
298 class TagLog:
299  __tablename__ = 'TAG_LOG'
300  columns = { 'tag_name':(DbRef(Tag,'name'),_Col.pk),
301  'event_time':(sqlalchemy.TIMESTAMP,_Col.pk),
302  'action':(sqlalchemy.String(100),_Col.pk),
303  'user_name':(sqlalchemy.String(100),_Col.notNull),
304  'host_name':(sqlalchemy.String(100),_Col.notNull),
305  'command':(sqlalchemy.String(500),_Col.notNull),
306  'user_text':(sqlalchemy.String(4000),_Col.notNull) }
307 
308 class RunInfo:
309  __tablename__ = 'RUN_INFO'
310  columns = { 'run_number':(sqlalchemy.BIGINT,_Col.pk),
311  'start_time':(sqlalchemy.TIMESTAMP,_Col.notNull),
312  'end_time':(sqlalchemy.TIMESTAMP,_Col.notNull) }
313 
315  __tablename__ = 'BOOST_RUN_MAP'
316  columns = { 'run_number':(sqlalchemy.BIGINT,_Col.pk),
317  'run_start_time':(sqlalchemy.TIMESTAMP,_Col.notNull),
318  'boost_version': (sqlalchemy.String(20),_Col.notNull) }
319 
320 # CondDB object
322 
323  def __init__(self, url):
324  # Workaround to avoid creating files if not present.
325  # Python's sqlite3 module does not use sqlite3_open_v2(),
326  # and therefore we cannot disable SQLITE_OPEN_CREATE.
327  # Only in the case of creating a new database we skip the check.
328  if url.drivername == 'sqlite':
329 
330  self.engine = sqlalchemy.create_engine(url)
331 
332  enabled_foreign_keys = self.engine.execute('pragma foreign_keys').scalar()
333  supports_foreign_keys = enabled_foreign_keys is not None
334  if not supports_foreign_keys:
335  logger.warning('Your SQLite database does not support foreign keys, so constraints will not be checked. Please upgrade.')
336  elif not enabled_foreign_keys:
337  self.engine.execute('pragma foreign_keys = on')
338 
339  else:
340  self.engine = sqlalchemy.create_engine(url, max_identifier_length=30)
341 
342  self._session = sqlalchemy.orm.scoped_session(sqlalchemy.orm.sessionmaker(bind=self.engine))
343 
344  self._is_frontier = url.drivername == 'oracle+frontier'
345  self._is_oracle = url.drivername == 'oracle'
346  self._is_sqlite = url.drivername == 'sqlite'
347 
348  self._is_read_only = self._is_frontier or url.host in {
349  'cms_orcon_adg',
350  'cmsarc_lb',
351  }
352 
353  self._is_official = self._is_frontier or url.host in {
354  'cms_orcon_adg',
355  'cmsarc_lb',
356  'cms_orcoff_int',
357  'cms_orcoff_prep',
358  'cms_orcon_prod',
359  'cmsintr_lb',
360  }
361  self._url = url
362  self._backendName = ('sqlite' if self._is_sqlite else 'oracle' )
363  self._schemaName = ( None if self._is_sqlite else schema_name )
364  logging.debug('Loading db types...')
365  self.get_dbtype(Tag).__name__
366  self.get_dbtype(Payload)
367  self.get_dbtype(IOV)
368  self.get_dbtype(TagLog)
369  self.get_dbtype(GlobalTag)
370  self.get_dbtype(GlobalTagMap)
371  self.get_dbtype(RunInfo)
372  if not self._is_sqlite:
373  self.get_dbtype(TagMetadata)
374  self.get_dbtype(TagAuthorization)
375  self.get_dbtype(BoostRunMap)
376  self._is_valid = self.is_valid()
377 
378  def get_dbtype(self,theType):
379  basename = theType.__name__
380  if self._backendName not in db_models.keys() or basename not in db_models[self._backendName].keys():
381  return make_dbtype( self._backendName, self._schemaName, theType )
382  else:
383  return db_models[self._backendName][basename]
384 
385  def session(self):
386  s = self._session()
387  s.get_dbtype = self.get_dbtype
388  s._is_sqlite = self._is_sqlite
389  s.is_oracle = self.is_oracle
390  s._url = self._url
391  return s
392 
393  @property
394  def metadata(self):
395  return _Base.metadata
396 
397  @property
398  def is_frontier(self):
399  return self._is_frontier
400 
401  @property
402  def is_oracle(self):
403  return self._is_oracle
404 
405  @property
406  def is_sqlite(self):
407  return self._is_sqlite
408 
409  @property
410  def is_read_only(self):
411  return self._is_read_only
412 
413  @property
414  def is_official(self):
415  return self._is_official
416 
417  def is_valid(self):
418  '''Tests whether the current DB looks like a valid CMS Conditions one.
419  '''
420  engine_connection = self.engine.connect()
421  # temporarely avoid the check on the GT tables - there are releases in use where C++ does not create these tables.
422  _Tag = self.get_dbtype(Tag)
423  _IOV = self.get_dbtype(IOV)
424  _Payload = self.get_dbtype(Payload)
425  ret = all([self.engine.dialect.has_table(engine_connection, table.__tablename__,getSchema(table)) for table in [_Tag, _IOV, _Payload]])
426  engine_connection.close()
427  return ret
428 
429  def init(self, drop=False):
430  '''Initializes a database.
431  '''
432  logging.info('Initializing database...')
433  if drop:
434  logging.debug('Dropping tables...')
435  self.metadata.drop_all(self.engine)
436  self._is_valid = False
437  else:
438  if not self._is_valid:
439  logging.debug('Creating tables...')
440  self.get_dbtype(Tag).__table__.create(bind = self.engine)
441  self.get_dbtype(Payload).__table__.create(bind = self.engine)
442  self.get_dbtype(IOV).__table__.create(bind = self.engine)
443  self.get_dbtype(TagLog).__table__.create(bind = self.engine)
444  self.get_dbtype(GlobalTag).__table__.create(bind = self.engine)
445  self.get_dbtype(GlobalTagMap).__table__.create(bind = self.engine)
446  self._is_valid = True
447 
448 def getSessionOnMasterDB( session1, session2 ):
449  key = '%s/%s'
450  sessiondict = { }
451  sessiondict[key %(session1._url.drivername,session1._url.host)] = session1
452  sessiondict[key %(session2._url.drivername,session2._url.host)] = session2
453  masterkey = key %('oracle',ONLINEORAPRO)
454  if masterkey in sessiondict.keys():
455  return sessiondict[masterkey]
456  adgkey = key %('oracle',ORAPRO)
457  if adgkey in sessiondict.keys():
458  return sessiondict[adgkey]
459  frontierkey = key %('frontier',PRO)
460  if frontierkey in sessiondict.keys():
461  return sessiondict[frontierkey]
462  # default case: frontier on pro
463  conn = Connection(make_url())
464  session = conn.session()
465  # is it required?
466  session._conn = conn
467  return session
468 
469 # Connection helpers
471  import subprocess
472  return subprocess.Popen(['cmsGetFnConnect', 'frontier://%s' % database], stdout = subprocess.PIPE).communicate()[0].strip()
473 
474 def _getCMSSQLAlchemyConnectionString(technology,service,schema_name):
475  if technology == 'frontier':
476  import urllib
477  import sys
478  py3k = sys.version_info >= (3, 0)
479  if py3k:
480  return '%s://@%s/%s' % ('oracle+frontier', urllib.parse.quote_plus(_getCMSFrontierConnectionString(service)), schema_name )
481  else:
482  return '%s://@%s/%s' % ('oracle+frontier', urllib.quote_plus(_getCMSFrontierConnectionString(service)), schema_name )
483  elif technology == 'oracle':
484  return '%s://%s@%s' % (technology, schema_name, service)
485 
486 # Entry point
487 def make_url(database='pro',read_only = True):
488  if database.startswith('sqlite:') or database.startswith('sqlite_file:'):
489  ignore, database = database.split(':',1)
490 
491  if ':' in database and '://' not in database: # check if we really got a shortcut like "pro:<schema>" (and not a url like proto://...), if so, disentangle
492  database, schema = database.split(':')
493 
494  officialdbs = {
495  # frontier
496  'pro' : ('frontier','PromptProd', { 'R': schema_name }, ),
497  'arc' : ('frontier','FrontierArc', { 'R': schema_name }, ),
498  'int' : ('frontier','FrontierInt', { 'R': schema_name }, ),
499  'dev' : ('frontier','FrontierPrep', { 'R': schema_name }, ),
500  # oracle adg
501  'orapro': ('oracle', 'cms_orcon_adg', { 'R': dbreader_user_name }, ),
502  'oraarc': ('oracle', 'cmsarc_lb', { 'R': dbreader_user_name }, ),
503  # oracle masters
504  'oraint': ('oracle', 'cms_orcoff_int', { 'R': dbreader_user_name,
505  'W': dbwriter_user_name }, ),
506  'oradev': ('oracle', 'cms_orcoff_prep', { 'R': dbreader_user_name,
507  'W': dbwriter_user_name }, ),
508  'onlineorapro': ('oracle', 'cms_orcon_prod', { 'R': dbreader_user_name,
509  'W': dbwriter_user_name }, ),
510  'onlineoraint': ('oracle', 'cmsintr_lb', { 'R': dbreader_user_name,
511  'W': dbwriter_user_name }, ),
512  }
513 
514  if database in officialdbs.keys():
515  key = ('R' if read_only else 'W')
516  mapping = officialdbs[database]
517  tech = mapping[0]
518  service = mapping[1]
519  schema_dict = mapping[2]
520  if key in schema_dict.keys():
521  database = _getCMSSQLAlchemyConnectionString(tech,service,schema_dict[key])
522  else:
523  raise Exception("Read-only database %s://%s cannot be accessed in update mode." %(tech,service))
524 
525  logging.debug('connection string set to "%s"' % database)
526 
527  try:
528  url = sqlalchemy.engine.url.make_url(database)
529  except sqlalchemy.exc.ArgumentError:
530  url = sqlalchemy.engine.url.make_url('sqlite:///%s' % database)
531  return url
532 
533 def connect(url, authPath=None, verbose=0, as_admin=False):
534  '''Returns a Connection instance to the CMS Condition DB.
535 
536  See database_help for the description of the database parameter.
537 
538  The verbosity level is as follows:
539 
540  0 = No output (default).
541  1 = SQL statements issued, including their parameters.
542  2 = In addition, results of the queries (all rows and the column headers).
543  '''
544 
545  check_admin = as_admin
546  if url.drivername == 'oracle':
547  if url.username is None:
548  logging.error('Could not resolve the username for the connection %s. Please provide a connection in the format oracle://[user]:[pass]@[host]' %url )
549  raise Exception('Connection format error: %s' %url )
550  if url.password is None:
551  if authPath is None:
552  if authPathEnvVar in os.environ:
553  authPath = os.environ[authPathEnvVar]
554  explicit_auth = False
555  if authPath is not None:
556  dbkey_path = os.path.join(authPath,dbkey_folder)
557  if not os.path.exists(dbkey_path):
558  authFile = os.path.join(authPath,'.netrc')
559  if os.path.exists(authFile):
560  entryKey = url.host.lower()+"/"+url.username.lower()
561  logging.debug('Looking up credentials for %s in file %s ' %(entryKey,authFile) )
562  import netrc
563  params = netrc.netrc( authFile ).authenticators(entryKey)
564  if params is not None:
565  (username, account, password) = params
566  url.username = username
567  url.password = password
568  else:
569  msg = 'The entry %s has not been found in the .netrc file.' %entryKey
570  raise TypeError(msg)
571  else:
572  explicit_auth =True
573  else:
574  import libCondDBPyBind11Interface as auth
575  role_code = auth.reader_role
576  if url.username == dbwriter_user_name:
577  role_code = auth.writer_role
578  if check_admin:
579  role_code = auth.admin_role
580  connection_string = oracle_connection_string(url.host.lower(),schema_name)
581  logging.debug('Using db key to get credentials for %s' %connection_string )
582  (dbuser,username,password) = auth.get_credentials_from_db(connection_string,role_code,authPath)
583  if username=='' or password=='':
584  raise Exception('No credentials found to connect on %s with the required access role.'%connection_string)
585  check_admin = False
586  url.username = username
587  url.password = password
588  else:
589  import getpass
590  pwd = getpass.getpass('Password for %s: ' % str(url))
591  if pwd is None or pwd == '':
592  pwd = getpass.getpass('Password for %s: ' % str(url))
593  if pwd is None or pwd == '':
594  raise Exception('Empty password provided, bailing out...')
595  url.password = pwd
596  if check_admin:
597  raise Exception('Admin access has not been granted. Please provide a valid admin db-key.')
598  if check_admin:
599  raise Exception('Admin access is not available for technology "%s".' %url.drivername)
600  if verbose >= 1:
601  logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
602 
603  if verbose >= 2:
604  logging.getLogger('sqlalchemy.engine').setLevel(logging.DEBUG)
605 
606  return Connection(url)
607 
608 
609 def _exists(session, primary_key, value):
610  ret = None
611  try:
612  ret = session.query(primary_key).\
613  filter(primary_key == value).\
614  count() != 0
615  except sqlalchemy.exc.OperationalError:
616  pass
617 
618  return ret
619 
620 def _inserted_before(timestamp):
621  '''To be used inside filter().
622  '''
623 
624  if timestamp is None:
625  # XXX: Returning None does not get optimized (skipped) by SQLAlchemy,
626  # and returning True does not work in Oracle (generates "and 1"
627  # which breaks Oracle but not SQLite). For the moment just use
628  # this dummy condition.
629  return sqlalchemy.literal(True) == sqlalchemy.literal(True)
630 
631  return conddb.IOV.insertion_time <= _parse_timestamp(timestamp)
632 
633 def listObject(session, name, snapshot=None):
634 
635  is_tag = _exists(session, Tag.name, name)
636  result = {}
637  if is_tag:
638  result['type'] = 'Tag'
639  result['name'] = session.query(Tag).get(name).name
640  result['timeType'] = session.query(Tag.time_type).\
641  filter(Tag.name == name).\
642  scalar()
643 
644  result['iovs'] = session.query(IOV.since, IOV.insertion_time, IOV.payload_hash, Payload.object_type).\
645  join(IOV.payload).\
646  filter(
647  IOV.tag_name == name,
648  _inserted_before(snapshot),
649  ).\
650  order_by(IOV.since.desc(), IOV.insertion_time.desc()).\
651  from_self().\
652  order_by(IOV.since, IOV.insertion_time).\
653  all()
654 
655  try:
656  is_global_tag = _exists(session, GlobalTag.name, name)
657  if is_global_tag:
658  result['type'] = 'GlobalTag'
659  result['name'] = session.query(GlobalTag).get(name)
660  result['tags'] = session.query(GlobalTagMap.record, GlobalTagMap.label, GlobalTagMap.tag_name).\
661  filter(GlobalTagMap.global_tag_name == name).\
662  order_by(GlobalTagMap.record, GlobalTagMap.label).\
663  all()
664  except sqlalchemy.exc.OperationalError:
665  sys.stderr.write("No table for GlobalTags found in DB.\n\n")
666 
667  if not is_tag and not is_global_tag:
668  raise Exception('There is no tag or global tag named %s in the database.' % name)
669 
670  return result
671 
672 def getPayload(session, hash):
673  # get payload from DB:
674  data, payloadType = session.query(Payload.data, Payload.object_type).filter(Payload.hash == hash).one()
675  return data
def init(self, drop=False)
Definition: conddblib.py:429
def listObject(session, name, snapshot=None)
Definition: conddblib.py:633
def _parse_timestamp(timestamp)
Definition: conddb2hdf5.py:43
def all(container)
workaround iterator generators for ROOT classes
Definition: cmstools.py:25
def getPayload(session, hash)
Definition: conddblib.py:672
def is_valid(self)
Definition: conddblib.py:417
def metadata(self)
Definition: conddblib.py:394
def getSessionOnMasterDB(session1, session2)
Definition: conddblib.py:448
def is_oracle(self)
Definition: conddblib.py:402
def __init__(self, url)
Definition: conddblib.py:323
def _getCMSFrontierConnectionString(database)
Definition: conddblib.py:470
def is_sqlite(self)
Definition: conddblib.py:406
static void * communicate(void *obj)
Definition: DQMNet.cc:1057
def make_url(database='pro', read_only=True)
Definition: conddblib.py:487
def is_read_only(self)
Definition: conddblib.py:410
def make_dbtype(backendName, schemaName, baseType)
Definition: conddblib.py:190
def is_frontier(self)
Definition: conddblib.py:398
def fq_col(schema, table, column)
Definition: conddblib.py:184
def hash(data)
Definition: conddblib.py:52
def fq_name(schema_name, table_name)
Definition: conddblib.py:166
def getSchema(tp)
Definition: conddblib.py:230
static std::string join(char **cmd)
Definition: RemoteFile.cc:19
def _getCMSSQLAlchemyConnectionString(technology, service, schema_name)
Definition: conddblib.py:474
def get_dbtype(self, theType)
Definition: conddblib.py:378
def oracle_connection_string(db_service, db_schema)
Definition: conddblib.py:139
def is_official(self)
Definition: conddblib.py:414
def connect(url, authPath=None, verbose=0, as_admin=False)
Definition: conddblib.py:533
#define str(s)
def _inserted_before(timestamp)
Definition: conddblib.py:620
def __init__(self, refType, refColumn)
Definition: conddblib.py:180
def _exists(session, primary_key, value)
Definition: conddblib.py:609