X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=curlwrapper.py;h=4383a70fbafa64370be94e5e3e9ab5e5a531acea;hb=570d234b7d7b40416b296de71225f28c826ee991;hp=cf132b79ad1ad17a72e3d110415f0fa19171bd84;hpb=d3a3b2d3ea98e72183d1cb5497c38badaa0c5863;p=nodemanager.git diff --git a/curlwrapper.py b/curlwrapper.py index cf132b7..4383a70 100644 --- a/curlwrapper.py +++ b/curlwrapper.py @@ -1,64 +1,50 @@ -import os +# 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 xmlrpclib -import urllib -import pycurl -from cStringIO import StringIO +import signal +import os import logger -# a pycurl-based replacement for the previous version that relied on forking curl - -def retrieve(url, cacert=None, postdata=None, timeout=90): - curl= pycurl.Curl() - curl.setopt(pycurl.URL,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) +verbose=False +#verbose=True - # set timeout - if timeout: - curl.setopt(pycurl.CONNECTTIMEOUT, timeout) - curl.setopt(pycurl.TIMEOUT, timeout) +class Sopen(Popen): + def kill(self, signal = signal.SIGTERM): + os.kill(self.pid, signal) - # set cacert - if cacert: - curl.setopt(pycurl.CAINFO, cacert) - curl.setopt(pycurl.SSL_VERIFYPEER, 2) - else: - curl.setopt(pycurl.SSL_VERIFYPEER, 0) - - # set postdata - if postdata: - if isinstance(postdata,dict): - postfields = urllib.urlencode(postdata) - else: - postfields=postdata - curl.setopt(pycurl.POSTFIELDS, postfields) - - # go - try: - curl.perform() - - errcode = curl.getinfo(pycurl.HTTP_CODE) - 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,errstr),postdata ) - - return buffer.getvalue() +def retrieve(url, cacert=None, postdata=None, timeout=90): +# 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 xmlrpclib.ProtocolError(url, rc, err, postdata) + else: + return data