diff --git a/func/commonconfig.py b/func/commonconfig.py
index 3823d39..f8e2c7f 100644
--- a/func/commonconfig.py
+++ b/func/commonconfig.py
@@ -29,10 +29,20 @@ class FuncdConfig(BaseConfig):
     minion_name = Option('')
     
     method_log_dir = Option("/var/log/func/methods/")
+    use_certmaster = BoolOption(True)
+    ca_file = Option('')
+    cert_file = Option('')
+    key_file = Option('')
 
 class OverlordConfig(BaseConfig):
     socket_timeout = FloatOption(0)
+    listen_port = IntOption('51234')
     backend = Option('conf')
     group_db = Option('')
-
+    key_file = Option('')
+    cert_file = Option('')
+    ca_file = Option('')
+    puppet_minions = BoolOption(False)
+    puppet_inventory = Option('/var/lib/puppet/ssl/ca/inventory.txt')
+    puppet_crl = Option('/var/lib/puppet/ssl/ca/ca_crl.pem')
 
diff --git a/func/minion/server.py b/func/minion/server.py
index fbe5c4b..96f796f 100644
--- a/func/minion/server.py
+++ b/func/minion/server.py
@@ -100,6 +100,9 @@ class XmlRpcInterface(object):
         methods.sort()
         return methods
     
+    def load_module(self, name):
+        """FIXME load a module and set it up on the running xmlrpc instance"""
+        pass
     
     import func.minion.modules.func_module as fm
     @fm.findout
@@ -243,13 +246,23 @@ class FuncSSLXMLRPCServer(AuthedXMLRPCServer.AuthedSSLXMLRPCServer,
 
         XmlRpcInterface.__init__(self)
         hn = func_utils.get_hostname_by_route()
-
-        self.key = "%s/%s.pem" % (self.cm_config.cert_dir, hn)
-        self.cert = "%s/%s.cert" % (self.cm_config.cert_dir, hn)
-        self.ca = "%s/ca.cert" % self.cm_config.cert_dir
+        
+        if self.config.key_file != '':
+            self.key = self.config.key_file
+        else:
+            self.key = "%s/%s.pem" % (self.cm_config.cert_dir, hn)            
+        
+        if self.config.cert_file != '':
+            self.cert = self.config.cert_file
+        else:
+            self.cert = "%s/%s.cert" % (self.cm_config.cert_dir, hn)
+        if self.config.ca_file != '':
+            self.ca = self.config.ca_file
+        else:
+            self.ca = "%s/ca.cert" % self.cm_config.cert_dir
+        
         
         self._our_ca = certs.retrieve_cert_from_file(self.ca)
-
         self.acls = acls_mod.Acls(config=self.config)
         
         AuthedXMLRPCServer.AuthedSSLXMLRPCServer.__init__(self, args,
@@ -358,8 +371,10 @@ def main(argv):
         print "serving...\n"
 
     try:
-        hn = futils.get_hostname_by_route()
-        requester.request_cert(hn)
+        config = read_config("/etc/func/minion.conf", FuncdConfig)
+        if config.use_certmaster:
+            hn = futils.get_hostname_by_route()
+            requester.request_cert(hn)
         serve()
     except codes.FuncException, e:
         print >> sys.stderr, 'error: %s' % e
diff --git a/func/overlord/base_command.py b/func/overlord/base_command.py
index fd77e4b..275bd95 100644
--- a/func/overlord/base_command.py
+++ b/func/overlord/base_command.py
@@ -33,13 +33,16 @@ class BaseCommand(command.Command):
     forks=1
     delegate=False
     mapfile=DEFAULT_MAPLOC
-    
+
     # temporary work around FIXME 
     # we really need a way to store what port each minion is
     # listening on, though this is probably workable for most
     # cases. Though it should probably be a different config
     # file, since FuncdConfig is for the minion server, not
     def getOverlord(self):
+        ol_config = None
+        if self.parentCommand.conffile:
+            ol_config = read_config(self.parentCommand.conffile, commonconfig.OverlordConfig)
         self.overlord_obj = client.Overlord(self.server_spec,
                                             interactive=self.interactive,
                                             verbose=self.verbose,
@@ -48,6 +51,7 @@ class BaseCommand(command.Command):
                                             delegate=self.delegate,
                                             mapfile=self.mapfile,
                                             timeout=self.parentCommand.socket_timeout,
-                                            exclude_spec=self.parentCommand.exclude_spec)
+                                            exclude_spec=self.parentCommand.exclude_spec,
+                                            config=ol_config)
 
 
diff --git a/func/overlord/client.py b/func/overlord/client.py
index e011929..1b05964 100644
--- a/func/overlord/client.py
+++ b/func/overlord/client.py
@@ -18,6 +18,10 @@ import sys
 import glob
 import os
 import time
+import shlex
+import subprocess
+import re
+import fnmatch
 import func.yaml as yaml
 
 from certmaster.commonconfig import CMConfig
@@ -103,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()
@@ -199,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):
@@ -221,6 +236,100 @@ class Minions(object):
         return False
 
 
+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):
+        self.spec = spec
+        self.port = port
+        self.noglobs = noglobs
+        self.verbose = verbose
+        self.just_fqdns = just_fqdns
+        self.delegate = delegate
+        self.minionmap = minionmap
+        self.exclude_spec = exclude_spec
+
+        self.cm_config = read_config(CONFIG_FILE, CMConfig)
+        self.overlord_config = read_config(OVERLORD_CONFIG_FILE, OverlordConfig)
+
+        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_hosts_for_spec(self,each_gloob):
+        """
+        Pull only for specified spec
+        """
+        #these will be returned
+        tmp_certs = set()
+        tmp_hosts = set()
+        
+        # revoked certs
+        revoked_serials = self._return_revoked_serials(self.overlord_config.puppet_crl)
+        # get all hosts
+        if os.access(self.overlord_config.puppet_inventory, os.R_OK):
+            fo = open(self.overlord_config.puppet_inventory, 'r')
+            host_inv = {}
+            time_format = '%Y-%m-%dT%H:%M:%S%Z'
+            now = time.time()
+            for line in fo.readlines():
+                if re.match('\s*(#|$)', line):
+                    continue
+                (serial, before, after, cn) = line.split()
+                if int(serial, 16) in revoked_serials:
+                    continue
+                before = time.strftime('%s', time.strptime(before, time_format))
+                if now < int(before):
+                    continue
+                after = time.strftime('%s', time.strptime(after, time_format))
+                if now > int(after):
+                    continue
+
+                hn = cn.replace('/CN=','')
+                hn = hn.replace('\n','')
+                if hn in host_inv:
+                    if host_inv[hn] > serial:
+                        continue
+                host_inv[hn] = serial
+
+            for hostname in host_inv.keys():
+                if fnmatch.fnmatch(hostname, each_gloob):
+                    tmp_hosts.add(hostname)
+                    # don't return certs path - just hosts
+
+        return tmp_hosts,tmp_certs
+
+    def _return_revoked_serials(self, crlfile):
+        try:
+            serials = []
+            crltext = open(crlfile, 'r').read()
+            from OpenSSL import crypto
+            crl = crypto.load_crl(crypto.FILETYPE_PEM, crltext)
+            revs = crl.get_revoked()
+            for revoked in revs:
+                serials.append(str(revoked.get_serial()))
+            return serials
+        except (ImportError, AttributeError), e:
+            call = '/usr/bin/openssl crl -text -noout -in %s' % crlfile
+            call = shlex.split(call)
+            serials = []
+            (res,err) = subprocess.Popen(call, stdout=subprocess.PIPE).communicate()
+            for line in res.split('\n'):
+                if line.find('Serial Number:') == -1:
+                    continue
+                (crap, serial) = line.split(':')
+                serial = serial.strip()
+                serial = int(serial, 16)
+                serials.append(serial)  
+            return serials
+
 
 # does the hostnamegoo actually expand to anything?
 def is_minion(minion_string):
@@ -252,18 +361,17 @@ class Overlord(object):
         @config -- optional config object
         """
 
-        self.config  = read_config(FUNCD_CONFIG_FILE, FuncdConfig)
-
-        self.cm_config = config
-        if config is None:
-            self.cm_config = read_config(CONFIG_FILE, CMConfig)
+        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.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
@@ -275,8 +383,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
@@ -292,9 +400,16 @@ class Overlord(object):
         
         #overlord_query stuff
         self.overlord_query = OverlordQuery()
-
-        self.minions_class = Minions(self.server_spec, port=self.port, noglobs=self.noglobs, verbose=self.verbose,exclude_spec=self.exclude_spec)
+        if self.config.puppet_minions:
+            self._mc = PuppetMinions
+        else:
+            self._mc = Minions
+            
+        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
         
@@ -316,6 +431,14 @@ class Overlord(object):
           # certmaster key, cert, ca
           # funcd key, cert, ca
           # raise FuncClientError
+        
+        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
         myname = func_utils.get_hostname_by_route()
@@ -610,7 +733,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)
 
@@ -668,13 +790,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
         
@@ -682,7 +805,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)
@@ -694,10 +816,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/command.py b/func/overlord/command.py
index 0a8e1c6..1290728 100644
--- a/func/overlord/command.py
+++ b/func/overlord/command.py
@@ -14,9 +14,6 @@ Command class.
 import optparse
 import sys
 
-from certmaster.config import read_config, CONFIG_FILE
-
-from certmaster.commonconfig import CMConfig
 
 class CommandHelpFormatter(optparse.IndentedHelpFormatter):
     """
@@ -124,8 +121,7 @@ class Command:
         self.stdout = stdout
         self.stderr = stderr
         self.parentCommand = parentCommand
-
-        self.config = read_config(CONFIG_FILE, CMConfig)
+        
 
         # create subcommands if we have them
         self.subCommands = {}
diff --git a/func/overlord/func_command.py b/func/overlord/func_command.py
index 8f4dffa..a443693 100644
--- a/func/overlord/func_command.py
+++ b/func/overlord/func_command.py
@@ -26,7 +26,8 @@ class FuncCommandLine(command.Command):
     socket_timeout = None
     subCommandClasses = []
     exclude_spec = None
-
+    conffile = None
+    
     def __init__(self):
         modules = module_loader.load_modules('func/overlord/cmd_modules/', base_command.BaseCommand)
         for x in modules.keys():
@@ -43,7 +44,8 @@ class FuncCommandLine(command.Command):
                                help="exclude some of minions",
                                action="store",
                                type="string")
-
+        self.parser.add_option('-c', '--conf', dest="conffile", 
+                               help="specify an overlord.conf file for func to use")
 
     # just some ugly goo to try to guess if arg[1] is hostnamegoo or
     # a command name
@@ -72,3 +74,7 @@ class FuncCommandLine(command.Command):
 
         if options.exclude:
             self.exclude_spec = options.exclude
+
+        if options.conffile:
+            self.conffile = options.conffile
+            
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)
 
 
