reguire gnupg1 on f>=31; sense the system to use gpg1 when installed
[nodemanager.git] / curlwrapper.py
index c1f59c3..a877b07 100644 (file)
@@ -1,72 +1,50 @@
+# Note
+# in spring 2010, an attempt was made to use pycurl instead of forking curl
+# it turned out, however, that after around 10 cycles of the nodemanager,
+# attempts to call GetSlivers were failing with a curl error 60
+# we are thus reverting to the version from tag curlwrapper.py-NodeManager-2.0-8
+# the (broken) pycurl version can be found in tags 2.0-9 and 2.0-10
+
+from subprocess import PIPE, Popen
+from select import select
+import xmlrpc.client
+import signal
 import os
-import xmlrpclib
-import urllib
-import pycurl
-from cStringIO import StringIO
 
 import logger
 
-# a pycurl-based replacement for the previous version that relied on forking curl
+verbose=False
+#verbose=True
 
-debug=False
+class Sopen(Popen):
+    def kill(self, signal = signal.SIGTERM):
+        os.kill(self.pid, signal)
 
 def retrieve(url, cacert=None, postdata=None, timeout=90):
-    curl= pycurl.Curl()
-    curl.setopt(pycurl.URL,url)
-    if debug: logger.verbose('curlwrapper: new instance %r -> %s'%(curl,url))
-
-    # reproduce --fail from the previous version
-    curl.setopt(pycurl.FAILONERROR,1)
-    # don't want curl sending any signals
-    curl.setopt(pycurl.NOSIGNAL, 1)
-
-    # do not follow location when attempting to download a file
-    # curl.setopt(pycurl.FOLLOWLOCATION, 0)
-
-    # store result on the fly
-    buffer=StringIO()
-    curl.setopt(pycurl.WRITEFUNCTION,buffer.write)
-
-    # set timeout
-    if timeout:
-        curl.setopt(pycurl.CONNECTTIMEOUT, timeout)
-        curl.setopt(pycurl.TIMEOUT, timeout)
-        if debug: logger.verbose('curlwrapper: timeout set to %r'%timeout)
-
-    # set cacert
-    if cacert:
-        curl.setopt(pycurl.CAINFO, cacert)
-        curl.setopt(pycurl.SSL_VERIFYPEER, 2)
-        if debug: logger.verbose('curlwrapper: using cacert %s'%cacert)
-    else:
-        curl.setopt(pycurl.SSL_VERIFYPEER, 0)
-
-    # set postdata
-    if postdata:
-        if isinstance(postdata,dict):
-            postfields = urllib.urlencode(postdata)
-            if debug: logger.verbose('curlwrapper: using encoded postfields %s'%postfields)
-        else:
-            postfields=postdata
-            if debug: logger.verbose('curlwrapper: using raw postfields %s'%postfields)
-        curl.setopt(pycurl.POSTFIELDS, postfields)
-
-    # go
-    try:
-        curl.perform()
-        errcode = curl.getinfo(pycurl.HTTP_CODE)
-
-        if debug: logger.verbose('curlwrapper: closing pycurl object')
-        curl.close()
-
-        # check the code, return 1 if successfull
-        if errcode == 60:
-            raise xmlrpclib.ProtocolError (url,errcode, "SSL certificate validation failed", postdata)
-        elif errcode != 200:
-            raise xmlrpclib.ProtocolError (url,errcode, "http error %d"%errcode, postdata)
-
-    except pycurl.error, err:
-        errno, errstr = err
-        raise xmlrpclib.ProtocolError(url, errno, "curl error %d: '%s'\n" %(errno,curl.errstr()),postdata )
-
-    return buffer.getvalue()
+#    command = ('/usr/bin/curl', '--fail', '--silent')
+    command = ('/usr/bin/curl', '--fail', )
+    if cacert: command += ('--cacert', cacert)
+    if postdata: command += ('--data', '@-')
+    if timeout: 
+        command += ('--max-time', str(timeout))
+        command += ('--connect-timeout', str(timeout))
+    command += (url, )
+    if verbose:
+        print('Invoking ', command)
+        if postdata: print('with postdata=', postdata)
+    p = Sopen(command , stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
+    if postdata: p.stdin.write(postdata)
+    p.stdin.close()
+    sout, sin, serr = select([p.stdout, p.stderr], [], [], timeout)
+    if len(sout) == 0 and len(sin) == 0 and len(serr) == 0: 
+        logger.verbose("curlwrapper: timed out after %s" % timeout)
+        p.kill(signal.SIGKILL) 
+    data = p.stdout.read()
+    err = p.stderr.read()
+    rc = p.wait()
+    if rc != 0: 
+        # when this triggers, the error sometimes doesn't get printed
+        logger.log ("curlwrapper: retrieve, got stderr <%s>"%err)
+        raise xmlrpc.client.ProtocolError(url, rc, err, postdata)
+    else: 
+        return data