CMS 3D CMS Logo

tier0.py
Go to the documentation of this file.
1 from __future__ import print_function
2 
3 #-toDo: move this to common?
4 
5 import logging
6 import cStringIO
7 import json
8 import os
9 import sys
10 import time
11 import subprocess
12 
13 import pycurl
14 
15 tier0Url = 'https://cmsweb.cern.ch/t0wmadatasvc/prod/'
16 
18  '''Tier0 exception.
19  '''
20 
21  def __init__(self, message):
22  self.args = (message, )
23 
24 
25 def unique(seq, keepstr=True):
26  t = type(seq)
27  if t in (unicode, str):
28  t = (list, t('').join)[bool(keepstr)]
29  try:
30  remaining = set(seq)
31  seen = set()
32  return t(c for c in seq if (c in remaining and not remaining.remove(c)))
33  except TypeError: # hashing didn't work, see if seq is sortable
34  try:
35  from itertools import groupby
36  s = sorted(enumerate(seq),key=lambda i_v1:(i_v1[1],i_v1[0]))
37  return t(next(g) for k,g in groupby(s, lambda i_v: i_v[1]))
38  except: # not sortable, use brute force
39  seen = []
40  return t(c for c in seq if not (c in seen or seen.append(c)))
41 
43 
44  def __init__( self, curl, response, proxy, timeout ):
45  super( ResponseError, self ).__init__( response )
46  self.args += ( curl, proxy )
47  self.timeout = timeout
48 
49  def __str__( self ):
50  errStr = """Wrong response for curl connection to Tier0DataSvc from URL \"%s\"""" %( self.args[1].getinfo( self.args[1].EFFECTIVE_URL ), )
51  if self.args[ -1 ]:
52  errStr += """ using proxy \"%s\"""" %( str( self.args[ -1 ] ), )
53  errStr += """ with timeout \"%d\" with error code \"%d\".""" %( self.timeout, self.args[1].getinfo( self.args[1].RESPONSE_CODE) )
54  if self.args[0].find( '<p>' ) != -1:
55  errStr += """\nFull response: \"%s\".""" %( self.args[0].partition('<p>')[-1].rpartition('</p>')[0], )
56  else:
57  errStr += """\nFull response: \"%s\".""" %( self.args[0], )
58  return errStr
59 
60 #TODO: Add exceptions for each category of HTTP error codes
61 #TODO: check response code and raise corresponding exceptions
62 
63 def _raise_http_error( curl, response, proxy, timeout ):
64  raise ResponseError( curl, response, proxy, timeout )
65 
67 
68  def __init__( self, uri, timeOut, retries, retryPeriod, proxy, debug ):
69  """
70  Parameters:
71  uri: Tier0DataSvc URI;
72  timeOut: time out for Tier0DataSvc HTTPS calls;
73  retries: maximum retries for Tier0DataSvc HTTPS calls;
74  retryPeriod: sleep time between two Tier0DataSvc HTTPS calls;
75  proxy: HTTP proxy for accessing Tier0DataSvc HTTPS calls;
76  debug: if set to True, enables debug information.
77  """
78  self._uri = uri
79  self._timeOut = timeOut
80  self._retries = retries
81  self._retryPeriod = retryPeriod
82  self._proxy = proxy
83  self._debug = debug
84 
85  def setDebug( self ):
86  self._debug = True
87 
88  def unsetDebug( self ):
89  self._debug = False
90 
91  def setProxy( self, proxy ):
92  self._proxy = proxy
93 
94  def _queryTier0DataSvc( self, url ):
95  """
96  Queries Tier0DataSvc.
97  url: Tier0DataSvc URL.
98  @returns: dictionary, from whence the required information must be retrieved according to the API call.
99  Raises if connection error, bad response, or timeout after retries occur.
100  """
101 
102  userAgent = "User-Agent: ConditionWebServices/1.0 python/%d.%d.%d PycURL/%s" % ( sys.version_info[ :3 ] + ( pycurl.version_info()[ 1 ], ) )
103 
104  proxy = ""
105  if self._proxy: proxy = ' --proxy=%s ' % self._proxy
106 
107  debug = " -s -S "
108  if self._debug: debug = " -v "
109 
110  cmd = '/usr/bin/curl -k -L --user-agent "%s" %s --connect-timeout %i --retry %i %s %s ' % (userAgent, proxy, self._timeOut, self._retries, debug, url)
111 
112  # time the curl to understand if re-tries have been carried out
113  start = time.time()
114  process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
115  (stdoutdata, stderrdata) = process.communicate()
116  retcode = process.returncode
117  end = time.time()
118 
119  if retcode != 0 or stderrdata:
120  # if the first curl has failed, logg its stderror and prepare and independent retry
121  msg = "looks like curl returned an error: retcode=%s and took %s seconds" % (retcode,(end-start),)
122  msg += ' msg = "'+str(stderrdata)+'"'
123  logging.error(msg)
124 
125  time.sleep(10)
126  cmd = '/usr/bin/curl -k -L --user-agent "%s" %s --connect-timeout %i --retry %i %s %s ' % (userAgent, proxy, self._timeOut, self._retries, "-v", url)
127  process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
128  (stdoutdata, stderrdata) = process.communicate()
129  retcode = process.returncode
130  if retcode != 0:
131  msg = "looks like curl returned an error for the second time: retcode=%s" % (retcode,)
132  msg += ' msg = "'+str(stderrdata)+'"'
133  logging.error(msg)
134  raise Tier0Error(msg)
135  else :
136  msg = "curl returned ok upon the second try"
137  logging.info(msg)
138 
139  return json.loads( ''.join(stdoutdata).replace( "'", '"').replace(' None', ' "None"') )
140 
141 
142  def getFirstSafeRun( self ):
143  """
144  Queries Tier0DataSvc to get the first condition safe run.
145  Parameters:
146  @returns: integer, the run number.
147  Raises if connection error, bad response, timeout after retries occur, or if the run number is not available.
148  """
149  firstConditionSafeRunAPI = "firstconditionsaferun"
150  safeRunDict = self._queryTier0DataSvc( os.path.join( self._uri, firstConditionSafeRunAPI ) )
151  if safeRunDict is None:
152  errStr = """First condition safe run is not available in Tier0DataSvc from URL \"%s\"""" %( os.path.join( self._uri, firstConditionSafeRunAPI ), )
153  if self._proxy:
154  errStr += """ using proxy \"%s\".""" %( str( self._proxy ), )
155  raise Tier0Error( errStr )
156  return int(safeRunDict['result'][0])
157 
158  def getGlobalTag( self, config ):
159  """
160  Queries Tier0DataSvc to get the most recent Global Tag for a given workflow.
161  Parameters:
162  config: Tier0DataSvc API call for the workflow to be looked for;
163  @returns: a string with the Global Tag name.
164  Raises if connection error, bad response, timeout after retries occur, or if no Global Tags are available.
165  """
166  data = self._queryTier0DataSvc( os.path.join( self._uri, config ) )
167  gtnames = sorted(unique( [ str( di[ 'global_tag' ] ) for di in data['result'] if di[ 'global_tag' ] is not None ] ))
168  try:
169  recentGT = gtnames[-1]
170  return recentGT
171  except IndexError:
172  errStr = """No Global Tags for \"%s\" are available in Tier0DataSvc from URL \"%s\"""" %( config, os.path.join( self._uri, config ) )
173  if self._proxy:
174  errStr += """ using proxy \"%s\".""" %( str( self._proxy ), )
175  raise Tier0Error( errStr )
176 
177 
178 def test( url ):
179  t0 = Tier0Handler( url, 1, 1, 1, None, debug=False)
180 
181  print(' fcsr = %s (%s)' % (t0.getFirstSafeRun(), type(t0.getFirstSafeRun()) ))
182  print(' reco_config = %s' % t0.getGlobalTag('reco_config'))
183  print(' express_config = %s' % t0.getGlobalTag('express_config'))
184  print('\n')
185 
186 
187 if __name__ == '__main__':
188  test( tier0Url )
189 
def __str__(self)
Definition: tier0.py:49
def getFirstSafeRun(self)
Definition: tier0.py:142
def __init__(self, message)
Definition: tier0.py:21
def replace(string, replacements)
def _queryTier0DataSvc(self, url)
Definition: tier0.py:94
S & print(S &os, JobReport::InputFile const &f)
Definition: JobReport.cc:65
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:20
def getGlobalTag(self, config)
Definition: tier0.py:158
def _raise_http_error(curl, response, proxy, timeout)
Definition: tier0.py:63
def __init__(self, uri, timeOut, retries, retryPeriod, proxy, debug)
Definition: tier0.py:68
def setDebug(self)
Definition: tier0.py:85
def unique(seq, keepstr=True)
Definition: tier0.py:25
def test(url)
Definition: tier0.py:178
def __init__(self, curl, response, proxy, timeout)
Definition: tier0.py:44
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
def unsetDebug(self)
Definition: tier0.py:88
#define str(s)
def setProxy(self, proxy)
Definition: tier0.py:91