summaryrefslogtreecommitdiffstats
path: root/overlord
diff options
context:
space:
mode:
authorMichael DeHaan <mdehaan@mdehaan.rdu.redhat.com>2007-09-26 13:32:01 -0400
committerMichael DeHaan <mdehaan@mdehaan.rdu.redhat.com>2007-09-26 13:32:01 -0400
commitbfc293cf605ecca02f8d45e27c33909c7778e649 (patch)
treea8d11afffda391ff72d69ff9408d0c4cf28a022d /overlord
parente3493766701ac84e6d76257659be27c209ecb12e (diff)
downloadthird_party-func-bfc293cf605ecca02f8d45e27c33909c7778e649.tar.gz
third_party-func-bfc293cf605ecca02f8d45e27c33909c7778e649.tar.xz
third_party-func-bfc293cf605ecca02f8d45e27c33909c7778e649.zip
Two things. First Client("*").hardware.info() and the like now works, due to some clever magic with getattr. You have one client object that can address multiples and returns a hash with the results for each machine. Second, results are hashes, not lists, and we are a bit more clever in returning a return code the CLI .. the highest int wins if there's an int, for instance. Still, return codes are relatively meaningless for multi-control ... the true power is in scripting things.
Diffstat (limited to 'overlord')
-rwxr-xr-xoverlord/client.py69
-rw-r--r--overlord/test_func.py7
2 files changed, 67 insertions, 9 deletions
diff --git a/overlord/client.py b/overlord/client.py
index 3427e20..87b665a 100755
--- a/overlord/client.py
+++ b/overlord/client.py
@@ -33,6 +33,32 @@ FUNC_USAGE = "Usage: %s [ --help ] [ --verbose ] target.example.org module metho
# ===================================
+class CommandAutomagic():
+ """
+ This allows a client object to act as if it were one machine, when in
+ reality it represents many.
+ """
+
+ def __init__(self, clientref, base):
+ self.base = base
+ self.clientref = clientref
+
+ def __getattr__(self,name):
+ base2 = self.base[:]
+ base2.append(name)
+ return CommandAutomagic(self.clientref, base2)
+
+ def __call__(self, *args):
+ if not self.base:
+ raise AttributeError("something wrong here")
+ if len(self.base) < 2:
+ raise AttributeError("no method called: %s" % ".".join(self.base))
+ module = self.base[0]
+ method = ".".join(self.base[1:])
+ return self.clientref.run(module,method,args)
+
+# ===================================
+
class Client():
def __init__(self, server_spec, port=DEFAULT_PORT, verbose=False, silent=False):
@@ -79,6 +105,22 @@ class Client():
return all_urls
+ # -----------------------------------------------
+
+ def __getattr__(self, name):
+ """
+ This getattr allows manipulation of the object as if it were
+ a XMLRPC handle to a single machine, when in reality it is a handle
+ to an unspecified number of machines.
+
+ So, it enables stuff like this:
+
+ Client("*.example.org").yum.install("foo")
+ """
+
+ return CommandAutomagic(self, [name])
+
+
# -----------------------------------------------
def run(self, module, method, args):
@@ -87,7 +129,7 @@ class Client():
"""
count = len(self.servers)
- results = []
+ results = {}
for server in self.servers:
@@ -114,7 +156,7 @@ class Client():
if not self.silent:
sys.stderr.write("remote exception on %s: %s\n" % (server, str(e)))
- results.append(retval)
+ results[server] = retval
return results
@@ -126,17 +168,26 @@ class Client():
and all sorts of crazy stuff, reduce it down to a simple
integer return. It may not be useful but we need one.
"""
- nonzeros = []
- for x in results:
+ numbers = []
+ for x in results.keys():
# faults are the most important
if type(x) == Exception:
return -911
- # then pay attention to non-zeros
+ # then pay attention to numbers
if type(x) == int:
- nonzeros.append(x)
- if len(nonzeros) > 0:
- return nonzeros[1]
- return 0
+ numbers.append(x)
+
+ # if there were no numbers, assume 0
+ if len(numbers) == 0:
+ return 0
+
+ # if there were numbers, return the highest
+ # (presumably the worst error code
+ max = -9999
+ for x in numbers:
+ if x > max:
+ max = x
+ return max
# ===================================================================
diff --git a/overlord/test_func.py b/overlord/test_func.py
index bcce45d..d759a2e 100644
--- a/overlord/test_func.py
+++ b/overlord/test_func.py
@@ -4,13 +4,20 @@
# FIXME: should import the client lib, not XMLRPC lib, when we are done
import xmlrpclib
+import sys
+TEST_GETATTR = True
TEST_PROCESS = False
TEST_VIRT = False
TEST_SERVICES = False
TEST_HARDWARE = False
TEST_SMART = True
+if TEST_GETATTR:
+ import func.overlord.client as func_client
+ print func_client.Client("*").hardware.info()
+ sys.exit(1)
+
# get a connecton (to be replaced by client lib logic)
s = xmlrpclib.ServerProxy("http://127.0.0.1:51234")