From 9763fdb11c8abbcb80ac8ff3ef3f4ff9d6148ff7 Mon Sep 17 00:00:00 2001 From: Adrian Likins Date: Tue, 9 Oct 2007 15:13:24 -0400 Subject: make func_command use the new handleArguments method from command.Command. Use this to fetch the hostnamegoo client.py: pull out expand_servers to module scope, and isServer(). This method basically tries to see if what we think is hostnamegoo is actually hostnamegoo. Kind of a guess atm. cmd_modules/call.py: change this so it doesn't do it's own parsing out of the hostname goo, instead using that from func_command (aka, the top level command parser) cmd_modules/show.py: just a cmd line module in early development --- func/overlord/client.py | 76 ++++++++++++++++++++++----------------- func/overlord/cmd_modules/call.py | 19 +++++----- func/overlord/cmd_modules/show.py | 71 ++++++++++++++++++++++++++++++++++++ func/overlord/func_command.py | 18 +++++++++- 4 files changed, 140 insertions(+), 44 deletions(-) create mode 100644 func/overlord/cmd_modules/show.py (limited to 'func') diff --git a/func/overlord/client.py b/func/overlord/client.py index ec304a5..641ad76 100755 --- a/func/overlord/client.py +++ b/func/overlord/client.py @@ -63,6 +63,47 @@ class CommandAutomagic(object): # =================================== + + +# 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): + config = read_config(CONFIG_FILE, CMConfig) + """ + Given a regex/blob of servers, expand to a list + of server ids. + """ + + if noglobs: + return [ "https://%s:%s" % (spec, port) ] + + all_hosts = [] + all_certs = [] + seperate_gloobs = spec.split(";") + 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: + all_urls.append("https://%s:%s" % (x, port)) + + 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, @@ -84,7 +125,8 @@ class Client(object): self.verbose = verbose self.interactive = interactive self.noglobs = noglobs - self.servers = self.expand_servers(self.server_spec) + self.servers = expand_servers(self.server_spec,port=self.port, + noglobs=self.noglobs,verbose=self.verbose) # default cert/ca/key is the same as the certmaster ca - need to # be able to change that on the cli @@ -93,38 +135,6 @@ class Client(object): # yes, they're the same, that's the point self.ca = '%s/funcmaster.crt' % self.config.cadir - # ----------------------------------------------- - - def expand_servers(self,spec): - """ - Given a regex/blob of servers, expand to a list - of server ids. - """ - - if self.noglobs: - return [ "https://%s:%s" % (spec, self.port) ] - - all_hosts = [] - all_certs = [] - seperate_gloobs = spec.split(";") - for each_gloob in seperate_gloobs: - actual_gloob = "%s/%s.cert" % (self.config.certroot, each_gloob) - certs = glob.glob(actual_gloob) - for cert in certs: - all_certs.append(cert) - host = cert.replace(self.config.certroot,"")[1:-5] - all_hosts.append(host) - - all_urls = [] - for x in all_hosts: - all_urls.append("https://%s:%s" % (x, self.port)) - - if self.verbose and len(all_urls) == 0: - sys.stderr.write("no hosts matched\n") - - return all_urls - - # ----------------------------------------------- def __getattr__(self, name): """ diff --git a/func/overlord/cmd_modules/call.py b/func/overlord/cmd_modules/call.py index 07a3aa2..0f69713 100644 --- a/func/overlord/cmd_modules/call.py +++ b/func/overlord/cmd_modules/call.py @@ -36,11 +36,6 @@ class Call(client.command.Command): def parse(self, argv): self.argv = argv - # FIXME? not sure this is good or bad, but it seems - # wronky... we try to grab the hostnamegoo from the - # args to the parentCommand - self.server_spec = self.argv[0] - return command.Command.parse(self, argv) @@ -52,7 +47,6 @@ class Call(client.command.Command): return pprint.pformat(data) if self.options.json: - print "fffffffffffffffffffffffffffffffffffffffffff" try: import simplejson return simplejson.dumps(data) @@ -69,10 +63,15 @@ class Call(client.command.Command): # I kind of feel like we shouldn't be parsing args here, but I'm # not sure what the write place is -al; - self.server_spec = args[0] - self.module = args[1] - self.method = args[2] - self.method_args = args[3:] + self.module = args[0] + self.method = args[1] + self.method_args = args[2:] + + # this could get weird, sub sub classes might be calling this + # this with multiple.parentCommand.parentCommands... + # maybe command.py needs a way to set attrs on subCommands? + # or some sort of shared datastruct? + self.server_spec = self.parentCommand.server_spec client_obj = client.Client(self.server_spec,port=self.port,interactive=True, verbose=self.verbose, config=self.config) diff --git a/func/overlord/cmd_modules/show.py b/func/overlord/cmd_modules/show.py new file mode 100644 index 0000000..10f44b3 --- /dev/null +++ b/func/overlord/cmd_modules/show.py @@ -0,0 +1,71 @@ +#!/usr/bin/python + +import optparse +import pprint +import xmlrpclib + +from func.overlord import command +from func.overlord import client + +DEFAULT_PORT = 51234 + + +class ShowHardware(client.command.Command): + name = "hardware" + useage = "show hardware details" + + # FIXME: we might as well make verbose be in the subclass + # and probably an inc variable while we are at it + def addOptions(self): + self.parser.add_option("-v", "--verbose", dest="verbose", + action="store_true") + self.parser.add_option("-p", "--port", dest="port", + default=DEFAULT_PORT) + + + def parse(self, argv): + self.argc = argv + return command.Command.parse(self.argv) + + def do(self,args): + client_obj = client.Client(self.server_spec,port=self.port,interactive=True, + verbose=self.verbose, config=self.config) + + + +class Show(client.command.Command): + name = "show" + useage = "various simple report stuff" + subCommands = [ShowHardware] + def addOptions(self): + self.parser.add_option("-v", "--verbose", dest="verbose", + action="store_true") + self.parser.add_option("-p", "--port", dest="port", + default=DEFAULT_PORT) + + def handleOptions(self, options): + self.options = options + + self.verbose = options.verbose + self.port = options.port + + + def parse(self, argv): + self.argv = argv + + return command.Command.parse(self, argv) + + + def do(self, args): + print "do args", args + return "bar" +# client_obj = client.Client(self.server_spec,port=self.port,interactive=True, +# verbose=self.verbose, config=self.config) +# results = client_obj.run(self.module, self.method, self.method_args) + + # TO DO: add multiplexer support + # probably as a higher level module. + + # dump the return code stuff atm till we figure out the right place for it +# return self.format_return(results) + diff --git a/func/overlord/func_command.py b/func/overlord/func_command.py index dceec18..2210334 100644 --- a/func/overlord/func_command.py +++ b/func/overlord/func_command.py @@ -5,13 +5,18 @@ import sys import command + +#FIXME: need a plug-in runtime module loader here from cmd_modules import call +from cmd_modules import show + +from func.overlord import client class FuncCommandLine(command.Command): name = "client" useage = "func is the commandline interface to a func minion" - subCommandClasses = [call.Call] + subCommandClasses = [call.Call,show.Show] def __init__(self): @@ -26,6 +31,17 @@ class FuncCommandLine(command.Command): self.parser.add_option("--list-minions", dest="list_minions", action="store_true", help="list all available minions") + def handleArguments(self, args): + server_string = args[0] + # try to be clever about this for now + if client.isServer(server_string): + self.server_spec = server_string + args.pop(0) + # if it doesn't look like server, assume it + # is a sub command? that seems wrong, what about + # typo's and such? How to catch that? -akl + # maybe a class variable self.data on Command? + def handleOptions(self, options): if options.version: #FIXME -- cgit