summaryrefslogtreecommitdiffstats
path: root/certmaster/overlord/client.py
diff options
context:
space:
mode:
Diffstat (limited to 'certmaster/overlord/client.py')
-rwxr-xr-xcertmaster/overlord/client.py336
1 files changed, 0 insertions, 336 deletions
diff --git a/certmaster/overlord/client.py b/certmaster/overlord/client.py
deleted file mode 100755
index cf1009c..0000000
--- a/certmaster/overlord/client.py
+++ /dev/null
@@ -1,336 +0,0 @@
-##
-## func command line interface & client lib
-##
-## Copyright 2007, Red Hat, Inc
-## Michael DeHaan <mdehaan@redhat.com>
-## +AUTHORS
-##
-## This software may be freely redistributed under the terms of the GNU
-## general public license.
-##
-## You should have received a copy of the GNU General Public License
-## along with this program; if not, write to the Free Software
-## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-##
-
-import sys
-import glob
-import os
-
-from func.commonconfig import CMConfig
-from func.config import read_config, CONFIG_FILE
-
-import sslclient
-
-import command
-import groups
-import func.forkbomb as forkbomb
-import func.jobthing as jobthing
-import func.utils as utils
-from func.CommonErrors import *
-
-# ===================================
-# defaults
-# TO DO: some of this may want to come from config later
-
-DEFAULT_PORT = 51234
-FUNC_USAGE = "Usage: %s [ --help ] [ --verbose ] target.example.org module method arg1 [...]"
-
-# ===================================
-
-class CommandAutomagic(object):
- """
- This allows a client object to act as if it were one machine, when in
- reality it represents many.
- """
-
- def __init__(self, clientref, base, nforks=1):
- self.base = base
- self.clientref = clientref
- self.nforks = nforks
-
- def __getattr__(self,name):
- base2 = self.base[:]
- base2.append(name)
- return CommandAutomagic(self.clientref, base2, self.nforks)
-
- 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,nforks=self.nforks)
-
-
-def get_groups():
- group_class = groups.Groups()
- return group_class.get_groups()
-
-
-def get_hosts_by_groupgoo(groups, groupgoo):
- group_gloobs = groupgoo.split(':')
- hosts = []
- for group_gloob in group_gloobs:
- if not group_gloob[0] == "@":
- continue
- if groups.has_key(group_gloob[1:]):
- hosts = hosts + groups[group_gloob[1:]]
- else:
- print "group %s not defined" % group_gloob
- return hosts
-
-# ===================================
-# this is a module level def so we can use it and isServer() from
-# other modules with a Client class
-def expand_servers(spec, port=51234, noglobs=None, verbose=None, just_fqdns=False):
- """
- Given a regex/blob of servers, expand to a list
- of server ids.
- """
-
-
- # FIXME: we need to refactor expand_servers, it seems to do
- # weird things, reload the config and groups config everytime it's
- # called for one, which may or may not be bad... -akl
- config = read_config(CONFIG_FILE, CMConfig)
-
- if noglobs:
- if not just_fqdns:
- return [ "https://%s:%s" % (spec, port) ]
- else:
- return spec
-
- group_dict = get_groups()
-
- all_hosts = []
- all_certs = []
- seperate_gloobs = spec.split(";")
-
- new_hosts = get_hosts_by_groupgoo(group_dict, spec)
-
- seperate_gloobs = spec.split(";")
- seperate_gloobs = seperate_gloobs + new_hosts
- for each_gloob in seperate_gloobs:
- actual_gloob = "%s/%s.cert" % (config.certroot, each_gloob)
- certs = glob.glob(actual_gloob)
- for cert in certs:
- all_certs.append(cert)
- host = cert.replace(config.certroot,"")[1:-5]
- all_hosts.append(host)
-
- all_urls = []
- for x in all_hosts:
- if not just_fqdns:
- all_urls.append("https://%s:%s" % (x, port))
- else:
- all_urls.append(x)
-
- if verbose and len(all_urls) == 0:
- sys.stderr.write("no hosts matched\n")
-
- return all_urls
-
-
-# does the hostnamegoo actually expand to anything?
-def isServer(server_string):
- servers = expand_servers(server_string)
- if len(servers) > 0:
- return True
- return False
-
-
-class Client(object):
-
- def __init__(self, server_spec, port=DEFAULT_PORT, interactive=False,
- verbose=False, noglobs=False, nforks=1, config=None, async=False, init_ssl=True):
- """
- Constructor.
- @server_spec -- something like "*.example.org" or "foosball"
- @port -- is the port where all funcd processes should be contacted
- @verbose -- whether to print unneccessary things
- @noglobs -- specifies server_spec is not a glob, and run should return single values
- @config -- optional config object
- """
- self.config = config
- if config is None:
- self.config = read_config(CONFIG_FILE, CMConfig)
-
-
- self.server_spec = server_spec
- self.port = port
- self.verbose = verbose
- self.interactive = interactive
- self.noglobs = noglobs
- self.nforks = nforks
- self.async = async
-
- self.servers = expand_servers(self.server_spec, port=self.port, noglobs=self.noglobs,verbose=self.verbose)
-
- if init_ssl:
- self.setup_ssl()
-
- def setup_ssl(self, client_key=None, client_cert=None, ca=None):
- # defaults go:
- # certmaster key, cert, ca
- # funcd key, cert, ca
- # raise FuncClientError
- ol_key = '%s/funcmaster.key' % self.config.cadir
- ol_crt = '%s/funcmaster.crt' % self.config.cadir
- myname = utils.get_hostname()
- # maybe /etc/pki/func is a variable somewhere?
- fd_key = '/etc/pki/func/%s.pem' % myname
- fd_crt = '/etc/pki/func/%s.cert' % myname
- self.ca = '%s/funcmaster.crt' % self.config.cadir
- if client_key and client_cert and ca:
- if (os.access(client_key, os.R_OK) and os.access(client_cert, os.R_OK)
- and os.access(ca, os.R_OK)):
- self.key = client_key
- self.cert = client_cert
- self.ca = ca
- # otherwise fall through our defaults
- elif os.access(ol_key, os.R_OK) and os.access(ol_crt, os.R_OK):
- self.key = ol_key
- self.cert = ol_crt
- elif os.access(fd_key, os.R_OK) and os.access(fd_crt, os.R_OK):
- self.key = fd_key
- self.cert = fd_crt
- else:
- raise Func_Client_Exception, 'Cannot read ssl credentials: ssl, cert, ca'
-
-
-
-
- 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")
-
- # WARNING: any missing values in Client's source will yield
- # strange errors with this engaged. Be aware of that.
- """
-
- return CommandAutomagic(self, [name], self.nforks)
-
- # -----------------------------------------------
-
- def job_status(self, jobid):
- """
- Use this to acquire status from jobs when using run with async client handles
- """
- return jobthing.job_status(jobid, client_class=Client)
-
- # -----------------------------------------------
-
- def run(self, module, method, args, nforks=1):
- """
- Invoke a remote method on one or more servers.
- Run returns a hash, the keys are server names, the values are the
- returns.
-
- The returns may include exception objects.
- If Client() was constructed with noglobs=True, the return is instead
- just a single value, not a hash.
- """
-
- results = {}
-
- def process_server(bucketnumber, buckets, server):
-
- conn = sslclient.FuncServer(server, self.key, self.cert, self.ca )
- # conn = xmlrpclib.ServerProxy(server)
-
- if self.interactive:
- sys.stderr.write("on %s running %s %s (%s)\n" % (server,
- module, method, ",".join(args)))
-
- # FIXME: support userland command subclassing only if a module
- # is present, otherwise run as follows. -- MPD
-
- try:
- # thats some pretty code right there aint it? -akl
- # we can't call "call" on s, since thats a rpc, so
- # we call gettatr around it.
- meth = "%s.%s" % (module, method)
-
- # async calling signature has an "imaginary" prefix
- # so async.abc.def does abc.def as a background task.
- # see Wiki docs for details
- if self.async:
- meth = "async.%s" % meth
-
- # this is the point at which we make the remote call.
- retval = getattr(conn, meth)(*args[:])
-
- if self.interactive:
- print retval
- except Exception, e:
- (t, v, tb) = sys.exc_info()
- retval = utils.nice_exception(t,v,tb)
- if self.interactive:
- sys.stderr.write("remote exception on %s: %s\n" %
- (server, str(e)))
-
- if self.noglobs:
- return retval
- else:
- left = server.rfind("/")+1
- right = server.rfind(":")
- server_name = server[left:right]
- return (server_name, retval)
-
- if not self.noglobs:
- if self.nforks > 1 or self.async:
- # using forkbomb module to distribute job over multiple threads
- if not self.async:
- results = forkbomb.batch_run(self.servers, process_server, nforks)
- else:
- results = jobthing.batch_run(self.servers, process_server, nforks)
- else:
- # no need to go through the fork code, we can do this directly
- results = {}
- for x in self.servers:
- (nkey,nvalue) = process_server(0, 0, x)
- results[nkey] = nvalue
- else:
- # globbing is not being used, but still need to make sure
- # URI is well formed.
- expanded = expand_servers(self.server_spec, port=self.port, noglobs=True, verbose=self.verbose)[0]
- results = process_server(0, 0, expanded)
-
- return results
-
- # -----------------------------------------------
-
- def cli_return(self,results):
- """
- As the return code list could return strings and exceptions
- and all sorts of crazy stuff, reduce it down to a simple
- integer return. It may not be useful but we need one.
- """
- numbers = []
- for x in results.keys():
- # faults are the most important
- if type(x) == Exception:
- return -911
- # then pay attention to numbers
- if type(x) == int:
- 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