From c3f2470c4d6d9594764d2cd312f9733dbce77791 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Wed, 23 Nov 2011 07:50:25 -0500 Subject: made error handling from bcfg2 client more consistent; avoid some backtraces --- src/lib/Proxy.py | 39 +++++++++++++++++++++++++++++++++++---- src/sbin/bcfg2 | 54 ++++++++++++++++++++++++++++-------------------------- 2 files changed, 63 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/lib/Proxy.py b/src/lib/Proxy.py index b7801a03c..e1406bd99 100644 --- a/src/lib/Proxy.py +++ b/src/lib/Proxy.py @@ -44,6 +44,24 @@ __all__ = ["ComponentProxy", "XMLRPCTransport"] +class ProxyError(Exception): + """ ProxyError provides a consistent reporting interface to + the various xmlrpclib errors that might arise (mainly + ProtocolError and Fault) """ + def __init__(self, err): + if isinstance(err, xmlrpclib.ProtocolError): + # cut out the password in the URL + url = re.sub(r'([^:]+):(.*?)@([^@]+:\d+/)', r'\1:******@\3', + err.url) + self.message = "XML-RPC Protocol Error for %s: %s (%s)" % \ + (url, err.errmsg, err.errcode) + elif isinstance(err, xmlrpclib.Fault): + self.message = "XML-RPC Fault: %s (%s)" % (err.faultString, + err.faultCode) + else: + self.message = str(err) + self.args = (self.message, ) + class CertificateError(Exception): def __init__(self, commonName): self.commonName = commonName @@ -285,12 +303,25 @@ class XMLRPCTransport(xmlrpclib.Transport): self.send_user_agent(h) self.send_content(h, request_body) - errcode, errmsg, headers = h.getreply() + if SSL_LIB == 'py26_ssl': + catch = ssl.SSLError + elif SSL_LIB == 'm2crypto': + catch = SSL.SSLError + try: + errcode, errmsg, headers = h.getreply() + except catch: + err = sys.exc_info()[1] + raise ProxyError(xmlrpclib.ProtocolError(host + handler, + 408, + str(err), + self._extra_headers)) + if errcode != 200: - # scrub password from the host - hoststr = re.sub(r':[^@]+@', ':******@', host) + handler - raise xmlrpclib.ProtocolError(hoststr, errcode, errmsg, headers) + raise ProxyError(xmlrpclib.ProtocolError(host + handler, + errcode, + errmsg, + headers)) self.verbose = verbose msglen = int(headers.dict['content-length']) diff --git a/src/sbin/bcfg2 b/src/sbin/bcfg2 index 5ddfd8791..58f2964f9 100755 --- a/src/sbin/bcfg2 +++ b/src/sbin/bcfg2 @@ -189,23 +189,21 @@ class Client: if self.setup['profile']: try: proxy.AssertProfile(self.setup['profile']) - except xmlrpclib.Fault: + except Bcfg2.Proxy.ProxyError: + err = sys.exc_info()[1] self.fatal_error("Failed to set client profile") - return(1) + self.logger.error(str(err)) + raise SystemExit(1) try: probe_data = proxy.GetProbes() - except xmlrpclib.Fault: - flt = sys.exc_info()[1] - self.logger.error("Failed to download probes from bcfg2") - self.logger.error(flt.faultString) - raise SystemExit(1) - except (Bcfg2.Proxy.CertificateError, + except (Bcfg2.Proxy.ProxyError, + Bcfg2.Proxy.CertificateError, socket.gaierror, socket.error): - e = sys.exc_info()[1] - self.logger.error("Failed to download probes from bcfg2: %s" - % e) + err = sys.exc_info()[1] + self.logger.error("Failed to download probes from bcfg2: %s" % + err) raise SystemExit(1) times['probe_download'] = time.time() @@ -231,31 +229,33 @@ class Client: if len(probes.findall(".//probe")) > 0: try: # upload probe responses - proxy.RecvProbeData(Bcfg2.Client.XML.tostring(probedata, encoding='UTF-8', xml_declaration=True)) - except: - self.logger.error("Failed to upload probe data", exc_info=1) + proxy.RecvProbeData(Bcfg2.Client.XML.tostring(probedata, + encoding='UTF-8', + xml_declaration=True)) + except Bcfg2.Proxy.ProxyError: + err = sys.exc_info()[1] + self.logger.error("Failed to upload probe data: %s" % err) raise SystemExit(1) times['probe_upload'] = time.time() if self.setup['decision'] in ['whitelist', 'blacklist']: try: - self.setup['decision_list'] = proxy.GetDecisionList( \ - self.setup['decision']) + self.setup['decision_list'] = \ + proxy.GetDecisionList(self.setup['decision']) self.logger.info("Got decision list from server:") self.logger.info(self.setup['decision_list']) - except xmlrpclib.Fault: - f = sys.exc_info()[1] - if f.faultCode == 1: - print("GetDecisionList method not supported by server") - else: - self.logger.error("Failed to de", exc_info=1) + except Bcfg2.Proxy.ProxyError: + err = sys.exc_info()[1] + self.logger.error("Failed to get decision list: %s" % err) raise SystemExit(1) try: rawconfig = proxy.GetConfig().encode('UTF-8') - except xmlrpclib.Fault: - self.logger.error("Failed to download configuration from Bcfg2") + except Bcfg2.Proxy.ProxyError: + err = sys.exc_info()[1] + self.logger.error("Failed to download configuration from " + "Bcfg2: %s" % err) raise SystemExit(2) times['config_download'] = time.time() @@ -327,8 +327,10 @@ class Client: proxy.RecvStats(Bcfg2.Client.XML.tostring(feedback, encoding='UTF-8', xml_declaration=True)) - except xmlrpclib.Fault: - self.logger.error("Failed to upload configuration statistics") + except Bcfg2.Proxy.ProxyError: + err = sys.exc_info()[1] + self.logger.error("Failed to upload configuration statistics: " + "%s" % err) raise SystemExit(2) if __name__ == '__main__': -- cgit v1.2.3-1-g7c22