summaryrefslogtreecommitdiffstats
path: root/src/lib/Bcfg2/Proxy.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/Bcfg2/Proxy.py')
-rw-r--r--src/lib/Bcfg2/Proxy.py121
1 files changed, 65 insertions, 56 deletions
diff --git a/src/lib/Bcfg2/Proxy.py b/src/lib/Bcfg2/Proxy.py
index 422d642db..220b89b5f 100644
--- a/src/lib/Bcfg2/Proxy.py
+++ b/src/lib/Bcfg2/Proxy.py
@@ -1,13 +1,3 @@
-"""RPC client access to cobalt components.
-
-Classes:
-ComponentProxy -- an RPC client proxy to Cobalt components
-
-Functions:
-load_config -- read configuration files
-
-"""
-
import logging
import re
import socket
@@ -34,7 +24,6 @@ import time
from Bcfg2.Bcfg2Py3k import httplib, xmlrpclib, urlparse
version = sys.version_info[:2]
-has_py23 = version >= (2, 3)
has_py26 = version >= (2, 6)
__all__ = ["ComponentProxy",
@@ -70,50 +59,58 @@ class CertificateError(Exception):
return ("Got unallowed commonName %s from server"
% self.commonName)
+_orig_Method = xmlrpclib._Method
class RetryMethod(xmlrpclib._Method):
"""Method with error handling and retries built in."""
log = logging.getLogger('xmlrpc')
- max_retries = 4
+ max_retries = 3
+ retry_delay = 1
def __call__(self, *args):
for retry in range(self.max_retries):
+ if retry >= self.max_retries - 1:
+ final = True
+ else:
+ final = False
+ msg = None
try:
- return xmlrpclib._Method.__call__(self, *args)
+ return _orig_Method.__call__(self, *args)
except xmlrpclib.ProtocolError:
err = sys.exc_info()[1]
- self.log.error("Server failure: Protocol Error: %s %s" % \
- (err.errcode, err.errmsg))
- raise xmlrpclib.Fault(20, "Server Failure")
+ msg = "Server failure: Protocol Error: %s %s" % \
+ (err.errcode, err.errmsg)
except xmlrpclib.Fault:
- raise
+ msg = sys.exc_info()[1]
except socket.error:
err = sys.exc_info()[1]
if hasattr(err, 'errno') and err.errno == 336265218:
- self.log.error("SSL Key error")
- break
- if hasattr(err, 'errno') and err.errno == 185090050:
- self.log.error("SSL CA error")
- break
- if retry == 3:
- self.log.error("Server failure: %s" % err)
- raise xmlrpclib.Fault(20, err)
+ msg = "SSL Key error: %s" % err
+ elif hasattr(err, 'errno') and err.errno == 185090050:
+ msg = "SSL CA error: %s" % err
+ elif final:
+ msg = "Server failure: %s" % err
except CertificateError:
- ce = sys.exc_info()[1]
- self.log.error("Got unallowed commonName %s from server" \
- % ce.commonName)
- break
+ err = sys.exc_info()[1]
+ msg = "Got unallowed commonName %s from server" % err.commonName
except KeyError:
- self.log.error("Server disallowed connection")
- break
+ err = sys.exc_info()[1]
+ msg = "Server disallowed connection: %s" % err
+ except ProxyError:
+ err = sys.exc_info()[1]
+ msg = err
except:
- self.log.error("Unknown failure", exc_info=1)
- break
- time.sleep(0.5)
- raise xmlrpclib.Fault(20, "Server Failure")
+ err = sys.exc_info()[1]
+ msg = "Unknown failure: %s" % err
+ if msg:
+ if final:
+ self.log.error(msg)
+ raise ProxyError(msg)
+ else:
+ self.log.info(msg)
+ time.sleep(self.retry_delay)
-# sorry jon
-_Method = RetryMethod
+xmlrpclib._Method = RetryMethod
class SSLHTTPConnection(httplib.HTTPConnection):
@@ -192,7 +189,15 @@ class SSLHTTPConnection(httplib.HTTPConnection):
def _connect_py26ssl(self):
"""Initiates a connection using the ssl module."""
- rawsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ # check for IPv6
+ hostip = socket.getaddrinfo(self.host,
+ self.port,
+ socket.AF_UNSPEC,
+ socket.SOCK_STREAM)[0][4][0]
+ if ':' in hostip:
+ rawsock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
+ else:
+ rawsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if self.protocol == 'xmlrpc/ssl':
ssl_protocol_ver = ssl.PROTOCOL_SSLv23
elif self.protocol == 'xmlrpc/tlsv1':
@@ -212,8 +217,7 @@ class SSLHTTPConnection(httplib.HTTPConnection):
self.logger.warning("SSL key specfied, but no cert. Cannot authenticate this client with SSL.")
self.key = None
- if has_py23:
- rawsock.settimeout(self.timeout)
+ rawsock.settimeout(self.timeout)
self.sock = ssl.SSLSocket(rawsock, cert_reqs=other_side_required,
ca_certs=self.ca, suppress_ragged_eofs=True,
keyfile=self.key, certfile=self.cert,
@@ -286,26 +290,21 @@ class XMLRPCTransport(xmlrpclib.Transport):
def make_connection(self, host):
host, self._extra_headers = self.get_host_info(host)[0:2]
- http = SSLHTTPConnection(host,
+ return SSLHTTPConnection(host,
key=self.key,
cert=self.cert,
ca=self.ca,
scns=self.scns,
timeout=self.timeout)
- https = httplib.HTTP()
- https._setup(http)
- return https
def request(self, host, handler, request_body, verbose=0):
"""Send request to server and return response."""
- h = self.make_connection(host)
-
try:
- self.send_request(h, handler, request_body)
- self.send_host(h, host)
- self.send_user_agent(h)
- self.send_content(h, request_body)
- errcode, errmsg, headers = h.getreply()
+ conn = self.send_request(host, handler, request_body, False)
+ response = conn.getresponse()
+ errcode = response.status
+ errmsg = response.reason
+ headers = response.msg
except (socket.error, SSL_ERROR):
err = sys.exc_info()[1]
raise ProxyError(xmlrpclib.ProtocolError(host + handler,
@@ -320,8 +319,17 @@ class XMLRPCTransport(xmlrpclib.Transport):
headers))
self.verbose = verbose
- msglen = int(headers.dict['content-length'])
- return self._get_response(h.getfile(), msglen)
+ return self.parse_response(response)
+
+ if sys.hexversion < 0x03000000:
+ def send_request(self, host, handler, request_body, debug):
+ """ send_request() changed significantly in py3k."""
+ conn = self.make_connection(host)
+ xmlrpclib.Transport.send_request(self, conn, handler, request_body)
+ self.send_host(conn, host)
+ self.send_user_agent(conn)
+ self.send_content(conn, request_body)
+ return conn
def _get_response(self, fd, length):
# read response from input file/socket, and parse it
@@ -345,9 +353,8 @@ class XMLRPCTransport(xmlrpclib.Transport):
return u.close()
-def ComponentProxy(url, user=None, password=None,
- key=None, cert=None, ca=None,
- allowedServerCNs=None, timeout=90):
+def ComponentProxy(url, user=None, password=None, key=None, cert=None, ca=None,
+ allowedServerCNs=None, timeout=90, retries=3, delay=1):
"""Constructs proxies to components.
@@ -357,6 +364,8 @@ def ComponentProxy(url, user=None, password=None,
Additional arguments are passed to the ServerProxy constructor.
"""
+ xmlrpclib._Method.max_retries = retries
+ xmlrpclib._Method.retry_delay = delay
if user and password:
method, path = urlparse(url)[:2]