Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-11-26 02:34:13

0001 #!/usr/bin/env python3
0002 
0003 import sys
0004 import os
0005 import re
0006 import string
0007 import mimetypes
0008 import http.client as httplib
0009 import ssl
0010 import gzip
0011 import hashlib
0012 from stat import *
0013 
0014 import urllib.request as urllib2
0015 from subprocess import getstatusoutput
0016 
0017 try:
0018   from Monitoring.DQM import visDQMUtils
0019 except:
0020   from DQMServices.FileIO import visDQMUtils
0021 
0022 if sys.version_info[:3] >= (2, 4, 0):
0023   HTTPS = httplib.HTTPSConnection
0024 else:
0025   HTTPS = httplib.HTTPS
0026 
0027 ssl_key_file = None
0028 ssl_cert_file = None
0029 context = None
0030 
0031 class HTTPSCertAuth(HTTPS):
0032   def __init__(self, host, context = None, *args, **kwargs):
0033     if context is None:
0034        context = ssl._create_default_https_context()
0035     if ssl_key_file or ssl_cert_file:
0036             context.load_cert_chain(ssl_cert_file, ssl_key_file)
0037     HTTPS.__init__(self, host, context = context, **kwargs)
0038 
0039 class HTTPSCertAuthenticate(urllib2.AbstractHTTPHandler):
0040   def default_open(self, req):
0041     return self.do_open(HTTPSCertAuth, req)
0042 
0043 def filetype(filename):
0044   return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
0045 
0046 def encode(args, files):
0047   """
0048     Encode form (name, value) and (name, filename, type) elements into
0049     multi-part/form-data. We don't actually need to know what we are
0050     uploading here, so just claim it's all text/plain.
0051   """
0052   boundary = b'----------=_DQM_FILE_BOUNDARY_=-----------'
0053   (body, crlf) = (b'', b'\r\n')
0054   for (key, value) in args.items():
0055     payload = str(value).encode('utf-8')
0056     body += b'--' + boundary + crlf
0057     body += (b'Content-Disposition: form-data; name="%s"' % key.encode('utf-8')) + crlf
0058     body += crlf + payload + crlf
0059   for (key, filename) in files.items():
0060     body += b'--' + boundary + crlf
0061     body += (b'Content-Disposition: form-data; name="%s"; filename="%s"'
0062              % (key.encode('utf-8'), os.path.basename(filename).encode('utf-8'))) + crlf
0063     body += (b'Content-Type: %s' % filetype(filename).encode('utf-8')) + crlf
0064     body += (b'Content-Length: %d' % os.stat(filename)[ST_SIZE]) + crlf
0065     with open(filename, 'rb') as file:
0066       body += crlf + file.read() + crlf
0067   body += b'--' + boundary + b'--' + crlf + crlf
0068   return (b'multipart/form-data; boundary=' + boundary, body)
0069 
0070 def marshall(args, files, request):
0071   """
0072     Marshalls the arguments to the CGI script as multi-part/form-data,
0073     not the default application/x-www-form-url-encoded.  This improves
0074     the transfer of the large inputs and eases command line invocation
0075     of the CGI script.
0076   """
0077   (type, body) = encode(args, files)
0078   request.add_header('Content-Type', type)
0079   request.add_header('Content-Length', str(len(body)))
0080   request.data = body
0081 
0082 def upload(url, args, files):
0083   ident = "visDQMUpload DQMGUI/%s python/%s" % \
0084     (os.getenv('DQMGUI_VERSION', '?'), "%d.%d.%d" % sys.version_info[:3])
0085   datareq = urllib2.Request(url + '/data/put')
0086   datareq.add_header('Accept-encoding', 'gzip')
0087   datareq.add_header('User-agent', ident)
0088   marshall(args, files, datareq)
0089   if 'https://' in url:
0090     result = urllib2.build_opener(HTTPSCertAuthenticate()).open(datareq)
0091   else:
0092     result = urllib2.build_opener(urllib2.ProxyHandler({})).open(datareq)
0093 
0094   data = result.read()
0095   if result.headers.get ('Content-encoding', '') == 'gzip':
0096     data = gzip.GzipFile (fileobj=StringIO(data)).read ()
0097   return (result.headers, data)
0098 
0099 x509_path = os.getenv("X509_USER_PROXY", None)
0100 if x509_path and os.path.exists(x509_path):
0101   ssl_key_file = ssl_cert_file = x509_path
0102 
0103 if not ssl_key_file:
0104   x509_path = os.getenv("X509_USER_KEY", None)
0105   if x509_path and os.path.exists(x509_path):
0106     ssl_key_file = x509_path
0107 
0108 if not ssl_cert_file:
0109   x509_path = os.getenv("X509_USER_CERT", None)
0110   if x509_path and os.path.exists(x509_path):
0111     ssl_cert_file = x509_path
0112 
0113 if not ssl_key_file and not ssl_cert_file:
0114   (status, uid) = getstatusoutput("id -u")
0115   if os.path.exists("/tmp/x509up_u%s" % uid):
0116     ssl_key_file = ssl_cert_file = "/tmp/x509up_u%s" % uid
0117 
0118 if not ssl_key_file:
0119   x509_path = os.getenv("HOME") + "/.globus/userkey.pem"
0120   if os.path.exists(x509_path):
0121     ssl_key_file = x509_path
0122 
0123 if not ssl_cert_file:
0124   x509_path = os.getenv("HOME") + "/.globus/usercert.pem"
0125   if os.path.exists(x509_path):
0126     ssl_cert_file = x509_path
0127 
0128 if 'https://' in sys.argv[1] and (not ssl_key_file or not os.path.exists(ssl_key_file)):
0129   print("no certificate private key file found", file=sys.stderr)
0130   sys.exit(1)
0131 
0132 if 'https://' in sys.argv[1] and (not ssl_cert_file or not os.path.exists(ssl_cert_file)):
0133   print("no certificate public key file found", file=sys.stderr)
0134   sys.exit(1)
0135 
0136 try:
0137   for file_path in sys.argv[2:]:
0138     # Before even trying to make a call to the other side, we first do a check on
0139     # the filename:
0140     classification_ok, classification_result = visDQMUtils.classifyDQMFile(file_path)
0141     if not classification_ok:
0142       print("Check of filename before upload failed with following message:")
0143       print(classification_result)
0144       sys.exit(1)
0145     # If file check was fine, we continue with the upload method:
0146     else:
0147       print("Using SSL private key", ssl_key_file)
0148       print("Using SSL public key", ssl_cert_file)
0149 
0150       hasher = hashlib.md5()
0151       with open(sys.argv[2], 'rb') as file:
0152         buf = file.read()
0153         hasher.update(buf)
0154 
0155       (headers, data) = \
0156         upload(sys.argv[1],
0157                { 'size': os.stat(sys.argv[2])[ST_SIZE],
0158                  'checksum': 'md5:%s' % hasher.hexdigest() },
0159                { 'file': file_path })
0160       print('Status code: ', headers.get("Dqm-Status-Code", "None"))
0161       print('Message:     ', headers.get("Dqm-Status-Message", "None"))
0162       print('Detail:      ', headers.get("Dqm-Status-Detail", "None"))
0163       print(data.decode('utf-8'))
0164   sys.exit(0)
0165 except urllib2.HTTPError as e:
0166   print('ERROR', e)
0167   print('Status code: ', e.hdrs.get("Dqm-Status-Code", "None"))
0168   print('Message:     ', e.hdrs.get("Dqm-Status-Message", "None"))
0169   print('Detail:      ', e.hdrs.get("Dqm-Status-Detail", "None"))
0170   sys.exit(1)