CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
alcaDQMUpload.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 import sys, os, os.path, re, string, httplib, mimetypes, urllib, urllib2, httplib, gzip, md5
4 from cStringIO import StringIO
5 from stat import *
6 import optparse
7 
8 try:
9  import hashlib
10 except:
11  pass
12 
13 HTTPS = httplib.HTTPS
14 if sys.version_info[:3] >= (2, 4, 0):
15  HTTPS = httplib.HTTPSConnection
16 
17 ssl_key_file = None
18 ssl_cert_file = None
19 
21  def __init__(self, host, *args, **kwargs):
22  HTTPS.__init__(self, host, key_file = ssl_key_file, cert_file = ssl_cert_file, **kwargs)
23 
24 class HTTPSCertAuthenticate(urllib2.AbstractHTTPHandler):
25  def default_open(self, req):
26  return self.do_open(HTTPSCertAuth, req)
27 
28 def filetype(filename):
29  return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
30 
31 def encode(args, files):
32  """
33  Encode form (name, value) and (name, filename, type) elements into
34  multi-part/form-data. We don't actually need to know what we are
35  uploading here, so just claim it's all text/plain.
36  """
37  boundary = '----------=_DQM_FILE_BOUNDARY_=-----------'
38  (body, crlf) = ('', '\r\n')
39  for (key, value) in args.items():
40  body += '--' + boundary + crlf
41  body += ('Content-disposition: form-data; name="%s"' % key) + crlf
42  body += crlf + str(value) + crlf
43  for (key, filename) in files.items():
44  body += '--' + boundary + crlf
45  body += ('Content-Disposition: form-data; name="%s"; filename="%s"'
46  % (key, os.path.basename(filename))) + crlf
47  body += ('Content-Type: %s' % filetype(filename)) + crlf
48  body += crlf + open(filename, "r").read() + crlf
49  body += '--' + boundary + '--' + crlf + crlf
50  return ('multipart/form-data; boundary=' + boundary, body)
51 
52 def marshall(args, files, request):
53  """
54  Marshalls the arguments to the CGI script as multi-part/form-data,
55  not the default application/x-www-form-url-encoded. This improves
56  the transfer of the large inputs and eases command line invocation
57  of the CGI script.
58  """
59  (type, body) = encode(args, files)
60  request.add_header('Content-type', type)
61  request.add_header('Content-length', str(len(body)))
62  request.add_data(body)
63 
64 def upload(url, args, files):
65  ident = "visDQMUpload DQMGUI/%s CMSSW/%s python/%s" % \
66  (os.getenv('DQMGUI_VERSION', '?'),
67  os.getenv('DQM_CMSSW_VERSION', os.getenv('CMSSW_VERSION', '?')),
68  "%d.%d.%d" % sys.version_info[:3])
69  cookie = None
70  if url.startswith("https:"):
71  authreq = urllib2.Request(url + '/authenticate')
72  authreq.add_header('User-agent', ident)
73  result = urllib2.build_opener(HTTPSCertAuthenticate()).open(authreq)
74  cookie = result.headers.get('Set-Cookie')
75  if not cookie:
76  raise RuntimeError("Did not receive authentication cookie")
77  cookie = cookie.split(";")[0]
78 
79  datareq = urllib2.Request(url + '/data/put')
80  datareq.add_header('Accept-encoding', 'gzip')
81  datareq.add_header('User-agent', ident)
82  if cookie:
83  datareq.add_header('Cookie', cookie)
84  marshall(args, files, datareq)
85  result = urllib2.build_opener().open(datareq)
86  data = result.read()
87  if result.headers.get ('Content-encoding', '') == 'gzip':
88  data = gzip.GzipFile (fileobj=StringIO(data)).read ()
89  return (result.headers, data)
90 
91 def print_help(*args):
92  sys.stdout.write("\n")
93  sys.stdout.write("This scripts intends to do the upload of files to the DQM server. It\n")
94  sys.stdout.write("runs some basic checks on the file name as it is crucial to follow\n")
95  sys.stdout.write("the naming convention.\n")
96  sys.stdout.write("\n")
97  sys.stdout.write("Mandatory Option\n")
98  sys.stdout.write(" -d, --destination parameter to specify the DQM server\n")
99  sys.stdout.write("\n")
100  sys.stdout.write(" Proxy Options\n")
101  sys.stdout.write(" The script will try to find your grid proxy automatically. To\n")
102  sys.stdout.write(" do so, it checks $X509_* environment variables and your globus\n")
103  sys.stdout.write(" directory (~/.globus). To override this automatism, you can use\n")
104  sys.stdout.write(" the following two options:\n")
105  sys.stdout.write(" --ssl-key-file location of your private key\n")
106  sys.stdout.write(" --ssl-cert-file location of your public key\n")
107  sys.stdout.write("\n")
108  sys.stdout.write("Other Options\n")
109  sys.stdout.write(" -h, --help show this help message\n")
110  sys.stdout.write(" -s, --no-submission suppress the submission\n")
111  sys.stdout.write(" -r, --no-registration suppress the submission\n")
112  sys.stdout.write(" --no-filename-check omit the file name check\n")
113  sys.stdout.write("\n")
114  sys.exit(0)
115 
116 def checkSSL(opts):
117  global ssl_key_file
118  global ssl_cert_file
119 
120  if opts.ssl_key_file and os.path.exists(opts.ssl_key_file):
121  ssl_key_file = opts.ssl_key_file
122  if opts.ssl_cert_file and os.path.exists(opts.ssl_cert_file):
123  ssl_cert_file = opts.ssl_cert_file
124 
125  if not ssl_key_file:
126  x509_path = os.getenv("X509_USER_PROXY", None)
127  if x509_path and os.path.exists(x509_path):
128  ssl_key_file = ssl_cert_file = x509_path
129 
130  if not ssl_key_file:
131  x509_path = os.getenv("X509_USER_KEY", None)
132  if x509_path and os.path.exists(x509_path):
133  ssl_key_file = x509_path
134 
135  if not ssl_cert_file:
136  x509_path = os.getenv("X509_USER_CERT", None)
137  if x509_path and os.path.exists(x509_path):
138  ssl_cert_file = x509_path
139 
140  if not ssl_key_file:
141  x509_path = os.getenv("HOME") + "/.globus/userkey.pem"
142  if os.path.exists(x509_path):
143  ssl_key_file = x509_path
144 
145  if not ssl_cert_file:
146  x509_path = os.getenv("HOME") + "/.globus/usercert.pem"
147  if os.path.exists(x509_path):
148  ssl_cert_file = x509_path
149 
150  if not ssl_key_file or not os.path.exists(ssl_key_file):
151  sys.stderr.write("no certificate private key file found, please specify one via $X509_USER_PROXY, $X509_USER_KEY or --ssl-key-file\n")
152  sys.exit(2)
153 
154  if not ssl_cert_file or not os.path.exists(ssl_cert_file):
155  sys.stderr.write("no certificate public key file found, please specify one via $X509_USER_CERT or --ssl-cert-file\n")
156  sys.exit(3)
157 
158  print "Using SSL private key", ssl_key_file
159  print "Using SSL public key", ssl_cert_file
160 
161 
162 def checkFileName(fileName):
163  regWhitespace = re.compile('.*\s.*')
164  if regWhitespace.match(fileName):
165  sys.stderr.write("whitespace detected!\n")
166  return False
167 
168  regRelval=re.compile('.*relval.*')
169  regCMSSW=re.compile('.*CMSSW_[0-9]+_[0-9]+_[0-9]+_.*')
170  regCMSSWpre=re.compile('.*CMSSW_[0-9]+_[0-9]+_[0-9]+_pre[0-9]+_.*')
171  if regRelval.match(fileName):
172  # TODO check for pre-versions
173  if not regCMSSW.match(fileName):
174  print "no CMSSW"
175  return True
176  # DQM stuff
177 
178 def startUpload(url, filename):
179  global ssl_key_file
180  global ssl_cert_file
181 
182  print url, filename
183  try:
184  (headers, data) = \
185  upload(url,
186  { 'size': os.stat(filename).st_size,
187  'checksum': "md5:%s" % md5.new(file(filename).read()).hexdigest() },
188  { 'file': filename })
189  print 'Status code: ', headers.get("Dqm-Status-Code", "None")
190  print 'Message: ', headers.get("Dqm-Status-Message", "None")
191  print 'Detail: ', headers.get("Dqm-Status-Detail", "None")
192  print data
193  except urllib2.HTTPError, e:
194  print "ERROR", e
195  print 'Status code: ', e.hdrs.get("Dqm-Status-Code", "None")
196  print 'Message: ', e.hdrs.get("Dqm-Status-Message", "None")
197  print 'Detail: ', e.hdrs.get("Dqm-Status-Detail", "None")
198  sys.exit(1)
199 
200 def getURL(filename, destination):
201  filename = filename.split("/")[-1]
202  regMC=re.compile('.*_R([0-9]*)__*')
203  if regMC.match(filename):
204  m = re.search('.*_R([0-9]*)(__.*).root',filename)
205  runNr = m.group(1)
206  dataset = m.group(2).replace("__","/")
207  else:
208  m = re.search('.*_R([0-9]*)(_?.*).root',filename)
209  runNr = m.group(1)
210  dataset = m.group(2).replace("__","/")
211  if dataset=="":
212  dataset="/Global/Online/ALL"
213  if not runNr:
214  runNr="1"
215  if (int(runNr)==1):
216  return destination+"start?workspace=summary;dataset="+dataset+";sampletype=offline_data"
217  else:
218  return destination+"start?workspace=summary;runnr="+runNr+";dataset="+dataset+";sampletype=online_data"
219 
220 def registerFileAtLogServer(filename, destination, tags):
221  filename = filename.split("/")[-1]
222  regMC=re.compile('.*_R([0-9]*)__*')
223  if regMC.match(filename):
224  m = re.search('.*_R([0-9]*)(__.*).root',filename)
225  runNr = m.group(1)
226  dataset = m.group(2).replace("__","/")
227  else:
228  m = re.search('.*_R([0-9]*)(_?.*).root',filename)
229  runNr = m.group(1)
230  dataset = m.group(2).replace("__","/")
231  if dataset=="":
232  dataset="/Global/Online/ALL"
233  tempurl = "https://www-ekp.physik.uni-karlsruhe.de/~zeise/cgi-bin/register.py?run="+runNr+"&dataset="+dataset+"&filename="+filename+"&tags="+tags+"&instance="+destination
234  print "Link that is used to register: ", tempurl
235  urllib.urlopen(tempurl)
236 
237 def main(args):
238  global opts
239  parser = optparse.OptionParser(add_help_option=False)
240  parser.add_option("-h", "--help", action="callback", callback=print_help),
241  parser.add_option("", "--no-filename-check", dest="no_filename_check", default=False, action="store_true")
242  parser.add_option("-d", "--destination", dest="destination", default="", action="store")
243  parser.add_option("-t", "--tags", dest="tags", default="", action="store")
244  parser.add_option("-s", "--no-submission", dest="submission", default=True, action="store_false")
245  parser.add_option("-r", "--no-registration", dest="registration", default=True, action="store_false")
246  parser.add_option("","--ssl-key-file", dest="ssl_key_file", default="", action="store")
247  parser.add_option("","--ssl-cert-file", dest="ssl_cert_file", default="", action="store")
248  (opts, args) = parser.parse_args()
249  opts.abort = False
250 
251  if not opts.destination:
252  sys.stderr.write("no destination specified\n")
253  sys.exit(4)
254  checkSSL(opts)
255 
256  if len(args)==0:
257  sys.stderr.write("no input files specified\n")
258  sys.exit(1)
259  for fileName in args:
260  fileName=fileName.strip()
261  if not os.path.exists(fileName):
262  sys.stderr.write("file '%s' doesn't exist!\n" % fileName)
263  continue
264  if not opts.no_filename_check and not checkFileName(fileName):
265  continue
266  sys.stderr.write("file '%s' passed name check, upload will follow!\n" % fileName)
267  if opts.submission:
268  startUpload(opts.destination, fileName)
269  else:
270  sys.stdout.write("file '%s' would be uploaded to '%s'\n" % (fileName, opts.destination))
271  if opts.registration:
272  registerFileAtLogServer(fileName, opts.destination, opts.tags)
273  print "You should see the plots here: "+getURL(fileName, opts.destination)
274 
275 if __name__ == '__main__':
276  sys.exit(main(sys.argv[1:]))
277 
278 
def replace
Definition: linker.py:10
def registerFileAtLogServer
Definition: main.py:1