From 8f0d4a8ed3cd80ee1c68d3f17e777fa89bcc105a Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Fri, 22 Feb 2008 14:47:15 -0500 Subject: Add failover to the XML-RPC client 433506 --- ipa-python/config.py | 16 +++++++++------- ipa-python/rpcclient.py | 25 ++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 10 deletions(-) (limited to 'ipa-python') diff --git a/ipa-python/config.py b/ipa-python/config.py index 52f5794c..2f5c54f6 100644 --- a/ipa-python/config.py +++ b/ipa-python/config.py @@ -23,6 +23,7 @@ from optparse import OptionParser import krbV import socket import ipa.dnsclient +import re class IPAConfigError(Exception): def __init__(self, msg=''): @@ -37,7 +38,7 @@ class IPAConfigError(Exception): class IPAConfig: def __init__(self): self.default_realm = None - self.default_server = None + self.default_server = [] def get_realm(self): if self.default_realm: @@ -62,7 +63,8 @@ def __parse_config(): if not config.default_realm: config.default_realm = p.get("defaults", "realm") if not config.default_server: - config.default_server = p.get("defaults", "server") + s = p.get("defaults", "server") + config.default_server = re.sub("\s+", "", s).split(',') except: pass @@ -95,12 +97,12 @@ def __discover_config(): for r in rs: if r.dns_type == ipa.dnsclient.DNS_T_SRV: rsrv = r.rdata.server.rstrip(".") - # we take only the first one returned for now - config.default_server = rsrv - return True + config.default_server.append(rsrv) - #if none found - return False + if config.default_server: + return True + else: + return False except: return False diff --git a/ipa-python/rpcclient.py b/ipa-python/rpcclient.py index e95b21f8..2359c5d6 100644 --- a/ipa-python/rpcclient.py +++ b/ipa-python/rpcclient.py @@ -20,6 +20,7 @@ import xmlrpclib import socket import config +import errno from krbtransport import KerbTransport from kerberos import GSSError from ipa import ipaerror, ipautil @@ -31,16 +32,34 @@ from ipa import config class RPCClient: def __init__(self): + self.server = None config.init_config() - def server_url(self): + def server_url(self, server): """Build the XML-RPC server URL from our configuration""" - return "https://" + config.config.get_server() + "/ipa" + return "https://" + server + "/ipa" def setup_server(self): """Create our XML-RPC server connection using kerberos authentication""" - return xmlrpclib.ServerProxy(self.server_url(), KerbTransport()) + if not self.server: + serverlist = config.config.get_server() + + # Try each server until we succeed or run out of servers to try + # Guaranteed by ipa.config to have at least 1 in the list + for s in serverlist: + try: + self.server = s + remote = xmlrpclib.ServerProxy(self.server_url(s), KerbTransport()) + result = remote.ping() + break + except socket.error, e: + if (e[0] == errno.ECONNREFUSED) or (e[0] == errno.ECONNREFUSED) or (e[0] == errno.EHOSTDOWN) or (e[0] == errno.EHOSTUNREACH): + continue + else: + raise e + + return xmlrpclib.ServerProxy(self.server_url(self.server), KerbTransport()) # Higher-level API -- cgit