- clean up PuppetMinions class - make grep, listminions and groups stop importing Minions and overlord directly - make grep, listminions, groups use the overlord objects with the proper config settings, not just the defaults. --- func/overlord/client.py | 177 +++++++++--------------------- func/overlord/cmd_modules/grep.py | 71 +++++++----- func/overlord/cmd_modules/listminions.py | 4 +- func/overlord/groups.py | 4 + 4 files changed, 100 insertions(+), 156 deletions(-) diff --git a/func/overlord/client.py b/func/overlord/client.py index 7e0d8fa..fdbc301 100644 --- a/func/overlord/client.py +++ b/func/overlord/client.py @@ -107,7 +107,9 @@ class Minions(object): self.exclude_spec = exclude_spec self.cm_config = read_config(CONFIG_FILE, CMConfig) - self.group_class = groups.Groups(backend=groups_backend,**kwargs) + self.group_class = groups.Groups(backend=groups_backend, + get_hosts_for_spec=self.get_hosts_for_spec, + **kwargs) #lets make them sets so we dont loop again and again self.all_hosts = set() @@ -203,19 +205,28 @@ class Minions(object): #we keep it all the time as a set so return list(self.all_hosts) - def get_urls(self): - self._get_new_hosts() - self._get_all_hosts() - for host in self.all_hosts: + def get_urls(self, hosts=[]): + if not hosts: + self._get_new_hosts() + self._get_all_hosts() + hosts = self.all_hosts + results = self.all_urls + else: + results = [] + + for host in hosts: if not self.just_fqdns: - self.all_urls.append("https://%s:%s" % (host, self.port)) + host_res = "https://%s:%s" % (host, self.port) else: - self.all_urls.append(host) + host_res = host + + if not host_res in results: # this might get slow if there are thousands of hosts + results.append(host_res) - if self.verbose and len(self.all_urls) == 0: + if self.verbose and len(results) == 0: sys.stderr.write("no hosts matched\n") - return self.all_urls + return results # FIXME: hmm, dont like this bit of the api... -al; def is_minion(self): @@ -225,17 +236,11 @@ class Minions(object): return False -class PuppetMinions(object): - def __init__(self, spec, port=51234, +class PuppetMinions(Minions): + def __init__(self, spec, port=51234, noglobs=None, verbose=None, just_fqdns=False, groups_backend="conf", delegate=False, minionmap={},exclude_spec=None,**kwargs): - - # open inventory.txt - # for each CN (uniqued) in there - # open the ca_crl.pem file - if the serial of the CN shows up in there - # remove those from the list of hosts - self.spec = spec self.port = port self.noglobs = noglobs @@ -247,35 +252,16 @@ class PuppetMinions(object): self.cm_config = read_config(CONFIG_FILE, CMConfig) self.overlord_config = read_config(OVERLORD_CONFIG_FILE, OverlordConfig) - self.cm_config = read_config(CONFIG_FILE, CMConfig) - self.group_class = groups.Groups(backend=groups_backend,**kwargs) - + + self.group_class = groups.Groups(backend=groups_backend, + get_hosts_for_spec=self.get_hosts_for_spec, + **kwargs) #lets make them sets so we dont loop again and again self.all_hosts = set() self.all_certs = set() self.all_urls = [] - def _get_new_hosts(self): - self.new_hosts = self._get_group_hosts(self.spec) - return self.new_hosts - def _get_group_hosts(self,spec): - return self.group_class.get_hosts_by_group_glob(spec) - - def _get_hosts_for_specs(self,seperate_gloobs): - """ - Gets the hosts and certs for proper spec - """ - tmp_hosts = set() - tmp_certs = set() - for each_gloob in seperate_gloobs: - if each_gloob.startswith('@'): - continue - h,c = self._get_hosts_for_spec(each_gloob) - tmp_hosts = tmp_hosts.union(h) - tmp_certs = tmp_certs.union(c) - - return tmp_hosts,tmp_certs def _get_hosts_for_spec(self,each_gloob): """ @@ -334,67 +320,6 @@ class PuppetMinions(object): serials.append(serial) return serials - def get_hosts_for_spec(self,spec): - """ - Be careful when editting that method it will be used - also by groups api to pull machines to have better - glob control there ... - """ - return self._get_hosts_for_spec(spec)[0] - - - - def _get_all_hosts(self): - """ - Gets hosts that are included and excluded by user - a better orm like spec so user may say - func "*" --exclude "www.*;@mygroup" ... - """ - included_part = self._get_hosts_for_specs(self.spec.split(";")+self.new_hosts) - self.all_certs=self.all_certs.union(included_part[1]) - self.all_hosts=self.all_hosts.union(included_part[0]) - #excluded ones - if self.exclude_spec: - #get first groups ypu dont want to run : - group_exclude = self._get_group_hosts(self.exclude_spec) - excluded_part = self._get_hosts_for_specs(self.exclude_spec.split(";")+group_exclude) - self.all_certs = self.all_certs.difference(excluded_part[1]) - self.all_hosts = self.all_hosts.difference(excluded_part[0]) - - - - def get_all_hosts(self): - """ - Get current host list - """ - self._get_new_hosts() - self._get_all_hosts() - - #we keep it all the time as a set so - return list(self.all_hosts) - - def get_urls(self): - self._get_new_hosts() - self._get_all_hosts() - for host in self.all_hosts: - if not self.just_fqdns: - self.all_urls.append("https://%s:%s" % (host, self.port)) - else: - self.all_urls.append(host) - - if self.verbose and len(self.all_urls) == 0: - sys.stderr.write("no hosts matched\n") - - return self.all_urls - - # FIXME: hmm, dont like this bit of the api... -al; - def is_minion(self): - self.get_urls() - if len(self.all_urls) > 0: - return True - return False - - # does the hostnamegoo actually expand to anything? def is_minion(minion_string): @@ -426,18 +351,17 @@ class Overlord(object): @config -- optional config object """ - self.config = read_config(FUNCD_CONFIG_FILE, FuncdConfig) + self.cm_config = read_config(CONFIG_FILE, CMConfig) + self.funcd_config = read_config(FUNCD_CONFIG_FILE, FuncdConfig) + self.config = read_config(OVERLORD_CONFIG_FILE, OverlordConfig) + if config: + self.config = config - self.cm_config = config - if config is None: - self.cm_config = read_config(CONFIG_FILE, CMConfig) - - self.overlord_config = read_config(OVERLORD_CONFIG_FILE, OverlordConfig) + self.overlord_config = self.config # for backward compat self.server_spec = server_spec self.exclude_spec = exclude_spec - # we could make this settable in overlord.conf as well self.port = port if self.config.listen_port: self.port = self.config.listen_port @@ -449,8 +373,8 @@ class Overlord(object): # the default self.timeout = DEFAULT_TIMEOUT # the config file - if self.overlord_config.socket_timeout != 0.0: - self.timeout = self.overlord_config.socket_timeout + if self.config.socket_timeout != 0.0: + self.timeout = self.config.socket_timeout # commandline if timeout: self.timeout = timeout @@ -466,15 +390,16 @@ class Overlord(object): #overlord_query stuff self.overlord_query = OverlordQuery() - if self.overlord_config.puppet_minions: - mc = PuppetMinions + if self.config.puppet_minions: + self._mc = PuppetMinions else: - mc = Minions + self._mc = Minions - self.minions_class = mc(self.server_spec, port=self.port, + self.minions_class = self._mc(self.server_spec, port=self.port, noglobs=self.noglobs, verbose=self.verbose, exclude_spec=self.exclude_spec) self.minions = self.minions_class.get_urls() + if len(self.minions) == 0: raise Func_Client_Exception, 'Can\'t find any minions matching \"%s\". ' % self.server_spec @@ -497,12 +422,12 @@ class Overlord(object): # funcd key, cert, ca # raise FuncClientError - if not client_key and self.overlord_config.key_file != '': - client_key = self.overlord_config.key_file - if not client_cert and self.overlord_config.cert_file != '': - client_cert = self.overlord_config.cert_file - if not ca and self.overlord_config.ca_file != '': - ca = self.overlord_config.ca_file + if not client_key and self.config.key_file != '': + client_key = self.config.key_file + if not client_cert and self.config.cert_file != '': + client_cert = self.config.cert_file + if not ca and self.config.ca_file != '': + ca = self.config.ca_file ol_key = '%s/certmaster.key' % self.cm_config.cadir ol_crt = '%s/certmaster.crt' % self.cm_config.cadir @@ -798,7 +723,6 @@ class Overlord(object): def process_server(bucketnumber, buckets, server): - conn = sslclient.FuncServer(server, self.key, self.cert, self.ca, self.timeout) # conn = xmlrpclib.ServerProxy(server) @@ -856,13 +780,14 @@ class Overlord(object): if kwargs.has_key('call_path'): #we're delegating if this key exists delegation_path = kwargs['call_path'] spec = kwargs['suboverlord'] #the sub-overlord directly beneath this one - minionobj = Minions(spec, port=self.port, verbose=self.verbose) + minions_hosts = self.minions_class.get_hosts_for_spec(spec) use_delegate = True #signal to process_server to call delegate method - minionurls = minionobj.get_urls() #the single-item url list to make async + minionurls = minionobj.get_urls(hosts=minion_hosts) #the single-item url list to make async #tools such as jobthing/forkbomb happy else: #we're directly calling minions, so treat everything normally spec = self.server_spec - minionurls = self.minions + minionurls = self.minions_class.get_urls() + #print "Minion_url is :",minionurls #print "Process server is :",process_server @@ -870,7 +795,6 @@ class Overlord(object): if self.nforks > 1 or self.async: # using forkbomb module to distribute job over multiple threads if not self.async: - results = forkbomb.batch_run(minionurls, process_server, nforks) else: minion_info =dict(spec=spec,module=module,method=method) @@ -882,10 +806,11 @@ class Overlord(object): (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] - expanded_minions = Minions(spec, port=self.port, noglobs=True, verbose=self.verbose) + expanded_minions = self._mc(spec, port=self.port, noglobs=True, verbose=self.verbose) minions = expanded_minions.get_urls()[0] results = process_server(0, 0, minions) diff --git a/func/overlord/cmd_modules/grep.py b/func/overlord/cmd_modules/grep.py index cade1d7..b7f1ac5 100644 --- a/func/overlord/cmd_modules/grep.py +++ b/func/overlord/cmd_modules/grep.py @@ -40,16 +40,15 @@ class Grep(base_command.BaseCommand): default=self.delegate, action="store_true") self.parser.add_option('-m', '--modules', dest="modules", - help="a list of modules to be searched", - default=self.delegate, - action="store", - type="string") + help="modules to be searched", + default=[], + action="append") def handleOptions(self, options): self.options = options self.verbose = options.verbose - + # I'm not really a fan of the "module methodname" approach # but we'll keep it for now -akl @@ -84,28 +83,35 @@ class Grep(base_command.BaseCommand): # which is better, this is across hosts (aka, walk across the # hosts, then ask all the module.grep methods to it, then on to # next host - + + existent_minions_class = self.overlord_obj.minions_class # keep a copy + for host in host_modules.keys(): + host_only_mc = self.overlord_obj._mc(host, noglobs=True) + host_only_mc.get_all_hosts() + self.overlord_obj.minions_class = host_only_mc for module in host_modules[host]: - if self.options.verbose: - print "Scanning module: %s on host: %s" %(module, host) + if self.options.modules and module in self.options.modules: + if self.options.verbose: + print "Scanning module: %s on host: %s" %(module, host) + + tmp_res = self.overlord_obj.run(module,"grep",[self.word]) - tmp_res = self.overlord_obj.run(module,"grep",[self.word]) - - if self.options.async: - tmp_res = self.overlord_obj.local.utils.async_poll(tmp_res,None) - #FIXME: I'm not sure what the best format for this is... - if tmp_res[host]: - print "%s: %s" % (host, pprint.pformat(tmp_res[host])) - + if self.options.async: + tmp_res = self.overlord_obj.local.utils.async_poll(tmp_res,None) + #FIXME: I'm not sure what the best format for this is... + if tmp_res[host]: + print "%s: %s" % (host, pprint.pformat(tmp_res[host])) + + self.overlord_obj.minions_class = existent_minions_class # put it back + def _get_host_grep_modules(self, server_spec): """ In cases when user doesnt supply the module list we have to consider that all of the modules are chosen so that method will return a list of them """ - from func.overlord.client import Minions,Overlord - + #insetad of getting all of the modules we consider #that all of machines has the same modules ... @@ -114,19 +120,28 @@ class Grep(base_command.BaseCommand): #FIXME: we need to change this to create a dict of hostname->modules # so we only call module.grep on systems that report it. things like # virt/hardware aren't available on all guests - m = Minions(server_spec) - hosts = m.get_all_hosts() + + if not hasattr(self, 'overlord_obj'): + self.getOverlord() + + hosts = self.overlord_obj.minions_class.get_all_hosts() + existent_minions_class = self.overlord_obj.minions_class # keep a copy if not hosts: raise Exception("No minions on system!") + + for host in hosts: - fc = Overlord(host, noglobs=True) - module_methods = fc.system.inventory() + host_only_mc = self.overlord_obj._mc(host, noglobs=True) + self.overlord_obj.minions_class = host_only_mc + module_methods = self.overlord_obj.system.inventory() - for module in module_methods: + for hn in module_methods: + for module in module_methods[hn]: # searching for "grep"? meta - if "grep" in module_methods[module]: - if not host_modules.has_key(host): - host_modules[host] = [] - host_modules[host].append(module) - + if "grep" in module_methods[hn][module]: + if not host_modules.has_key(host): + host_modules[host] = [] + host_modules[host].append(module) + + self.overlord_obj.minions_class = existent_minions_class # put it back return host_modules diff --git a/func/overlord/cmd_modules/listminions.py b/func/overlord/cmd_modules/listminions.py index 5264791..8d36d15 100644 --- a/func/overlord/cmd_modules/listminions.py +++ b/func/overlord/cmd_modules/listminions.py @@ -37,8 +37,8 @@ class ListMinions(base_command.BaseCommand): def do(self, args): self.server_spec = self.parentCommand.server_spec - - minion_set = client.Minions(self.server_spec, port=self.port) + self.getOverlord() + minion_set = self.overlord_obj.minions_class servers = minion_set.get_all_hosts() servers.sort() for server in servers: diff --git a/func/overlord/groups.py b/func/overlord/groups.py index 80754f0..b957a63 100644 --- a/func/overlord/groups.py +++ b/func/overlord/groups.py @@ -20,6 +20,10 @@ class Groups(object): Initialize the backend you are going to use """ #initialize here the backend + if 'get_hosts_for_spec' in kwargs: + self.get_hosts_for_spec = kwargs['get_hosts_for_spec'] + del kwargs['get_hosts_for_spec'] + self.backend = choose_backend(**kwargs) -- 1.6.6 _______________________________________________ Func-list mailing list Func-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/func-list