CMS 3D CMS Logo

visDQMUpload.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 
3 from __future__ import print_function
4 import sys
5 import os
6 import re
7 import string
8 import mimetypes
9 import http.client as httplib
10 import ssl
11 import gzip
12 import hashlib
13 from stat import *
14 
15 import urllib.request as urllib2
16 from subprocess import getstatusoutput
17 
18 try:
19  from Monitoring.DQM import visDQMUtils
20 except:
21  from DQMServices.FileIO import visDQMUtils
22 
23 if sys.version_info[:3] >= (2, 4, 0):
24  HTTPS = httplib.HTTPSConnection
25 else:
26  HTTPS = httplib.HTTPS
27 
28 ssl_key_file = None
29 ssl_cert_file = None
30 context = None
31 
33  def __init__(self, host, context = None, *args, **kwargs):
34  if context is None:
35  context = ssl._create_default_https_context()
36  if ssl_key_file or ssl_cert_file:
37  context.load_cert_chain(ssl_cert_file, ssl_key_file)
38  HTTPS.__init__(self, host, context = context, **kwargs)
39 
40 class HTTPSCertAuthenticate(urllib2.AbstractHTTPHandler):
41  def default_open(self, req):
42  return self.do_open(HTTPSCertAuth, req)
43 
44 def filetype(filename):
45  return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
46 
47 def encode(args, files):
48  """
49  Encode form (name, value) and (name, filename, type) elements into
50  multi-part/form-data. We don't actually need to know what we are
51  uploading here, so just claim it's all text/plain.
52  """
53  boundary = b'----------=_DQM_FILE_BOUNDARY_=-----------'
54  (body, crlf) = (b'', b'\r\n')
55  for (key, value) in args.items():
56  payload = str(value).encode('utf-8')
57  body += b'--' + boundary + crlf
58  body += (b'Content-Disposition: form-data; name="%s"' % key.encode('utf-8')) + crlf
59  body += crlf + payload + crlf
60  for (key, filename) in files.items():
61  body += b'--' + boundary + crlf
62  body += (b'Content-Disposition: form-data; name="%s"; filename="%s"'
63  % (key.encode('utf-8'), os.path.basename(filename).encode('utf-8'))) + crlf
64  body += (b'Content-Type: %s' % filetype(filename).encode('utf-8')) + crlf
65  body += (b'Content-Length: %d' % os.stat(filename)[ST_SIZE]) + crlf
66  with open(filename, 'rb') as file:
67  body += crlf + file.read() + crlf
68  body += b'--' + boundary + b'--' + crlf + crlf
69  return (b'multipart/form-data; boundary=' + boundary, body)
70 
71 def marshall(args, files, request):
72  """
73  Marshalls the arguments to the CGI script as multi-part/form-data,
74  not the default application/x-www-form-url-encoded. This improves
75  the transfer of the large inputs and eases command line invocation
76  of the CGI script.
77  """
78  (type, body) = encode(args, files)
79  request.add_header('Content-Type', type)
80  request.add_header('Content-Length', str(len(body)))
81  request.data = body
82 
83 def upload(url, args, files):
84  ident = "visDQMUpload DQMGUI/%s python/%s" % \
85  (os.getenv('DQMGUI_VERSION', '?'), "%d.%d.%d" % sys.version_info[:3])
86  datareq = urllib2.Request(url + '/data/put')
87  datareq.add_header('Accept-encoding', 'gzip')
88  datareq.add_header('User-agent', ident)
89  marshall(args, files, datareq)
90  if 'https://' in url:
91  result = urllib2.build_opener(HTTPSCertAuthenticate()).open(datareq)
92  else:
93  result = urllib2.build_opener(urllib2.ProxyHandler({})).open(datareq)
94 
95  data = result.read()
96  if result.headers.get ('Content-encoding', '') == 'gzip':
97  data = gzip.GzipFile (fileobj=StringIO(data)).read ()
98  return (result.headers, data)
99 
100 x509_path = os.getenv("X509_USER_PROXY", None)
101 if x509_path and os.path.exists(x509_path):
102  ssl_key_file = ssl_cert_file = x509_path
103 
104 if not ssl_key_file:
105  x509_path = os.getenv("X509_USER_KEY", None)
106  if x509_path and os.path.exists(x509_path):
107  ssl_key_file = x509_path
108 
109 if not ssl_cert_file:
110  x509_path = os.getenv("X509_USER_CERT", None)
111  if x509_path and os.path.exists(x509_path):
112  ssl_cert_file = x509_path
113 
114 if not ssl_key_file and not ssl_cert_file:
115  (status, uid) = getstatusoutput("id -u")
116  if os.path.exists("/tmp/x509up_u%s" % uid):
117  ssl_key_file = ssl_cert_file = "/tmp/x509up_u%s" % uid
118 
119 if not ssl_key_file:
120  x509_path = os.getenv("HOME") + "/.globus/userkey.pem"
121  if os.path.exists(x509_path):
122  ssl_key_file = x509_path
123 
124 if not ssl_cert_file:
125  x509_path = os.getenv("HOME") + "/.globus/usercert.pem"
126  if os.path.exists(x509_path):
127  ssl_cert_file = x509_path
128 
129 if 'https://' in sys.argv[1] and (not ssl_key_file or not os.path.exists(ssl_key_file)):
130  print("no certificate private key file found", file=sys.stderr)
131  sys.exit(1)
132 
133 if 'https://' in sys.argv[1] and (not ssl_cert_file or not os.path.exists(ssl_cert_file)):
134  print("no certificate public key file found", file=sys.stderr)
135  sys.exit(1)
136 
137 try:
138  for file_path in sys.argv[2:]:
139  # Before even trying to make a call to the other side, we first do a check on
140  # the filename:
141  classification_ok, classification_result = visDQMUtils.classifyDQMFile(file_path)
142  if not classification_ok:
143  print("Check of filename before upload failed with following message:")
144  print(classification_result)
145  sys.exit(1)
146  # If file check was fine, we continue with the upload method:
147  else:
148  print("Using SSL private key", ssl_key_file)
149  print("Using SSL public key", ssl_cert_file)
150 
151  hasher = hashlib.md5()
152  with open(sys.argv[2], 'rb') as file:
153  buf = file.read()
154  hasher.update(buf)
155 
156  (headers, data) = \
157  upload(sys.argv[1],
158  { 'size': os.stat(sys.argv[2])[ST_SIZE],
159  'checksum': 'md5:%s' % hasher.hexdigest() },
160  { 'file': file_path })
161  print('Status code: ', headers.get("Dqm-Status-Code", "None"))
162  print('Message: ', headers.get("Dqm-Status-Message", "None"))
163  print('Detail: ', headers.get("Dqm-Status-Detail", "None"))
164  print(data.decode('utf-8'))
165  sys.exit(0)
166 except urllib2.HTTPError as e:
167  print('ERROR', e)
168  print('Status code: ', e.hdrs.get("Dqm-Status-Code", "None"))
169  print('Message: ', e.hdrs.get("Dqm-Status-Message", "None"))
170  print('Detail: ', e.hdrs.get("Dqm-Status-Detail", "None"))
171  sys.exit(1)
def filetype(filename)
Definition: visDQMUpload.py:44
def upload(url, args, files)
Definition: visDQMUpload.py:83
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
Definition: Utilities.cc:47
def __init__(self, host, context=None, args, kwargs)
Definition: visDQMUpload.py:33
def encode(args, files)
Definition: visDQMUpload.py:47
def marshall(args, files, request)
Definition: visDQMUpload.py:71
#define str(s)
def classifyDQMFile(path)
Definition: visDQMUtils.py:29