Commit 4b5547a2 authored by Gary Wong's avatar Gary Wong

Eschew M2Crypto.m2xmlrpclib. It dies horribly under Python 2.7.

Invoke HTTPConnection or M2Crypto's HTTPSConnection directly, instead, and
process everything through xmlrpclib's utility functions on the way in and
out by hand.

(Note that we can't use native Python's HTTPSConnection, or native
xmlrpclib with an HTTPS URL for that matter, because Python's SSL
support does not handle custom callbacks to retrieve passphrases,
which we want to do.  We can't override that behaviour with Python
code, since it lives in a binary shared library.)
parent 1967d584
......@@ -16,9 +16,8 @@ from urlparse import urlsplit, urlunsplit
from urllib import splitport
import xmlrpclib
import M2Crypto
from M2Crypto import X509
import socket
import time;
import time
import httplib
# Debugging output.
debug = 0
......@@ -123,7 +122,7 @@ for opt, arg in opts:
elif opt in ( "--delete" ):
DELETE = 1
cert = X509.load_cert( CERTIFICATE )
cert = M2Crypto.X509.load_cert( CERTIFICATE )
# XMLRPC server: use www.emulab.net for the clearinghouse.
XMLRPC_SERVER = { "ch" : "www.emulab.net" }
......@@ -208,12 +207,7 @@ def geni_am_response_handler(method, method_args):
#
def do_method(module, method, params, URI=None, quiet=False, version=None,
response_handler=None):
if not os.path.exists(CERTIFICATE):
return Fatal("error: missing emulab certificate: %s\n" % CERTIFICATE)
from M2Crypto.m2xmlrpclib import SSL_Transport
from M2Crypto import SSL
if URI == None and CMURI and (module == "cm" or module == "cmv2"):
URI = CMURI
elif URI == None and SAURI and module == "sa":
......@@ -239,59 +233,61 @@ def do_method(module, method, params, URI=None, quiet=False, version=None,
URI = URI + "/" + version
pass
scheme, netloc, path, query, fragment = urlsplit(URI)
if not scheme:
URI = "https://" + URI
pass
scheme, netloc, path, query, fragment = urlsplit(URI)
if scheme == "https":
host,port = splitport(netloc)
if not port:
netloc = netloc + ":443"
URI = urlunsplit((scheme, netloc, path, query, fragment));
pass
pass
url = urlsplit(URI, "https")
if debug:
# print URI + " " + method + " " + str(params);
print URI + " " + method
pass
ctx = SSL.Context("sslv23")
ctx.load_cert(CERTIFICATE, CERTIFICATE, PassPhraseCB)
ctx.set_verify(SSL.verify_none, 16)
ctx.set_allow_unknown_ca(0)
print str( url ) + " " + method
if url.scheme == "https":
if not os.path.exists(CERTIFICATE):
if not quiet:
print >> sys.stderr, "error: missing emulab certificate: " + CERTIFICATE
return (-1, None)
port = url.port if url.port else 443
ctx = M2Crypto.SSL.Context("sslv23")
ctx.load_cert(CERTIFICATE, CERTIFICATE, PassPhraseCB)
ctx.set_verify(M2Crypto.SSL.verify_none, 16)
ctx.set_allow_unknown_ca(0)
# Get a handle on the server,
server = xmlrpclib.ServerProxy(URI, SSL_Transport(ctx), verbose=0)
server = M2Crypto.httpslib.HTTPSConnection( url.hostname, port, ssl_context = ctx )
elif url.scheme == "http":
port = url.port if url.port else 80
server = httplib.HTTPConnection( url.hostname, port )
# Get a pointer to the function we want to invoke.
meth = getattr(server, method)
meth_args = [ params ]
if response_handler:
# If a response handler was passed, use it and return the result.
# This is the case when running the GENI AM.
return response_handler(meth, params)
def am_helper( server, path, body ):
server.request( "POST", path, body )
return xmlrpclib.loads( server.getresponse().read() )[ 0 ][ 0 ]
return response_handler( ( lambda *x: am_helper( server, url.path, xmlrpclib.dumps( x, method ) ) ), params )
#
# Make the call.
#
while True:
try:
response = apply(meth, meth_args)
break
except xmlrpclib.Fault, e:
if not quiet: print >> sys.stderr, e.faultString
if e.faultCode == 503:
print >> sys.stderr, "Will try again in a moment. Be patient!"
server.request( "POST", url.path, xmlrpclib.dumps( (params,), method ) )
response = server.getresponse()
if response.status == 503:
if not quiet:
print >> sys.stderr, "Will try again in a moment. Be patient!"
time.sleep(5.0)
continue
pass
elif response.status != 200:
if not quiet:
print >> sys.stderr, response.status + " " + response.reason
return (-1,None)
response = xmlrpclib.loads( response.read() )[ 0 ][ 0 ]
break
except httplib.HTTPException, e:
if not quiet: print >> sys.stderr, e
return (-1, None)
except xmlrpclib.ProtocolError, e:
if not quiet: print >> sys.stderr, e.errmsg
except xmlrpclib.Fault, e:
if not quiet: print >> sys.stderr, e.faultString
return (-1, None)
except M2Crypto.SSL.Checker.WrongHost, e:
if not quiet:
......@@ -302,7 +298,6 @@ def do_method(module, method, params, URI=None, quiet=False, version=None,
print >> sys.stderr, e
pass
return (-1, None)
pass
#
# Parse the Response, which is a Dictionary. See EmulabResponse in the
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment