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