---
func/commonconfig.py | 10 +++-
func/overlord/client.py | 184 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 191 insertions(+), 3 deletions(-)
diff --git a/func/commonconfig.py b/func/commonconfig.py
index 3823d39..c71138d 100644
--- a/func/commonconfig.py
+++ b/func/commonconfig.py
@@ -29,10 +29,18 @@ class FuncdConfig(BaseConfig):
minion_name = Option('')
method_log_dir = Option("/var/log/func/methods/")
+ ca_file = Option('')
+ cert_file = Option('')
+ key_file = Option('')
class OverlordConfig(BaseConfig):
socket_timeout = FloatOption(0)
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/overlord/client.py b/func/overlord/client.py
index e011929..b0631e7 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
@@ -221,6 +225,176 @@ class Minions(object):
return False
+class PuppetMinions(object):
+ 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
+ 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.cm_config = read_config(CONFIG_FILE, CMConfig)
+ self.group_class = groups.Groups(backend=groups_backend,**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):
+ """
+ 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):
+ 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
+
+ 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):
@@ -292,8 +466,14 @@ 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.overlord_config.puppet_minions:
+ mc = PuppetMinions
+ else:
+ mc = Minions
+
+ self.minions_class = 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
--
1.6.6
_______________________________________________
Func-list mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/func-list