From: Faiyaz Ahmed Date: Tue, 17 Jun 2008 18:47:22 +0000 (+0000) Subject: Timeout curl in the event Apache (PLC side) opens the XMLRPC session, but returns... X-Git-Tag: NodeManager-1.7-13~2 X-Git-Url: http://git.onelab.eu/?p=nodemanager.git;a=commitdiff_plain;h=93888d28005417008aaf2004628d029c9bf1e5b6 Timeout curl in the event Apache (PLC side) opens the XMLRPC session, but returns no data for specified timeout. --- diff --git a/conf_files.py b/conf_files.py index c5d5924..24d5509 100644 --- a/conf_files.py +++ b/conf_files.py @@ -10,7 +10,7 @@ import threading import curlwrapper import logger import tools - +import xmlrpclib class conf_files: def __init__(self, config, noscripts=False): @@ -52,7 +52,7 @@ class conf_files: url = 'https://%s/%s' % (self.config.PLC_BOOT_HOST, cf_rec['source']) try: contents = curlwrapper.retrieve(url, self.config.cacert) - except curlwrapper.CurlException: + except xmlrpclib.ProtocolError,e: logger.log('conf_files: failed to retrieve %s from %s, skipping' % (dest, url)) return if not cf_rec['always_update'] and sha.new(contents).digest() == self.checksum(dest): diff --git a/curlwrapper.py b/curlwrapper.py index e259578..4aa634d 100644 --- a/curlwrapper.py +++ b/curlwrapper.py @@ -1,18 +1,36 @@ -from subprocess import PIPE, Popen +# $Id$ +from subprocess import PIPE, Popen +from select import select +# raise xmplrpclib.ProtocolError +import xmlrpclib +import signal +import os +import logger -class CurlException(Exception): pass +class Sopen(Popen): + def kill(self, signal = signal.SIGTERM): + os.kill(self.pid, signal) -def retrieve(url, cacert=None, postdata=None, timeout=300): +def retrieve(url, cacert=None, postdata=None, timeout=90): options = ('/usr/bin/curl', '--fail', '--silent') if cacert: options += ('--cacert', cacert) if postdata: options += ('--data', '@-') - if timeout: options += ('--max-time', str(timeout)) - p = Popen(options + (url,), stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) + if timeout: + options += ('--max-time', str(timeout)) + options += ('--connect-timeout', str(timeout)) + p = Sopen(options + (url,), 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: raise CurlException(err) - else: return data + if rc != 0: + # when this triggers, the error sometimes doesn't get printed + raise xmlrpclib.ProtocolError(url, rc, err, postdata) + else: + return data diff --git a/plcapi.py b/plcapi.py index 4da9e48..759207e 100644 --- a/plcapi.py +++ b/plcapi.py @@ -1,3 +1,5 @@ +# $Id$ + import safexmlrpc import hmac, sha @@ -15,7 +17,7 @@ class PLCAPI: the new session-based method. """ - def __init__(self, uri, cacert, auth, timeout = 300, **kwds): + def __init__(self, uri, cacert, auth, timeout = 90, **kwds): if isinstance(auth, (tuple, list)): (self.node_id, self.key) = auth self.session = None diff --git a/safexmlrpc.py b/safexmlrpc.py index 71799ff..5346b3c 100644 --- a/safexmlrpc.py +++ b/safexmlrpc.py @@ -1,26 +1,30 @@ +# $Id: safexmlrpc.py 9491 2008-05-28 15:49:13Z thierry $ + """Leverage curl to make XMLRPC requests that check the server's credentials.""" -import curlwrapper import xmlrpclib +import curlwrapper + + +class CertificateCheckingSafeTransport (xmlrpclib.Transport): -class CertificateCheckingSafeTransport(xmlrpclib.Transport): def __init__(self, cacert, timeout): self.cacert = cacert self.timeout = timeout def request(self, host, handler, request_body, verbose=0): self.verbose = verbose - try: - contents = curlwrapper.retrieve('https://%s%s' % (host, handler), - cacert = self.cacert, - postdata = request_body, - timeout = self.timeout) - return xmlrpclib.loads(contents)[0] - except curlwrapper.CurlException, e: - raise xmlrpclib.ProtocolError(host + handler, -1, str(e), '') + url='https://%s%s' % (host, handler) + # this might raise an xmlrpclib.Protocolerror exception + contents = curlwrapper.retrieve(url, + cacert = self.cacert, + postdata = request_body, + timeout = self.timeout) + return xmlrpclib.loads(contents)[0] class ServerProxy(xmlrpclib.ServerProxy): + def __init__(self, uri, cacert, timeout = 300, **kwds): xmlrpclib.ServerProxy.__init__(self, uri, CertificateCheckingSafeTransport(cacert, timeout),