diff options
-rw-r--r-- | kolabd/Makefile.am | 1 | ||||
-rw-r--r-- | kolabd/__init__.py | 99 | ||||
-rw-r--r-- | kolabd/kolabd.systemd | 15 | ||||
-rw-r--r-- | kolabd/process.py | 37 |
4 files changed, 88 insertions, 64 deletions
diff --git a/kolabd/Makefile.am b/kolabd/Makefile.am index 95cd792..f8e4ca8 100644 --- a/kolabd/Makefile.am +++ b/kolabd/Makefile.am @@ -1,5 +1,6 @@ EXTRA_DIST = \ kolabd.sysconfig \ + kolabd.systemd \ kolabd.sysvinit kolabddir = $(pythondir)/kolabd diff --git a/kolabd/__init__.py b/kolabd/__init__.py index ec05238..2d3f94f 100644 --- a/kolabd/__init__.py +++ b/kolabd/__init__.py @@ -18,9 +18,6 @@ """ The Kolab daemon. - - TODO: Write a pid file, check the pid file has a valid pid, and - consider providing an option to specify the pid file path. """ import os @@ -35,16 +32,15 @@ from pykolab.auth import Auth from pykolab import constants from pykolab.translate import _ -log = pykolab.getLogger('kolabd') +from process import KolabdProcess as Process + +log = pykolab.getLogger('pykolab.daemon') conf = pykolab.getConf() class KolabDaemon(object): def __init__(self): """ - self.args == Arguments passed on the CLI - self.cli_options == Parser results (again, CLI) - self.parser == The actual Parser (from OptionParser) - self.plugins == Our Kolab Plugins + The main Kolab Groupware daemon process. """ daemon_group = conf.add_cli_parser_option_group(_("Daemon Options")) @@ -63,18 +59,14 @@ class KolabDaemon(object): conf.finalize_conf() - self.thread_count = 0 - def run(self): """Run Forest, RUN!""" exitcode = 0 - # TODO: Add a nosync option try: pid = 1 if conf.fork_mode: - self.thread_count += 1 pid = os.fork() if pid == 0: @@ -87,9 +79,11 @@ class KolabDaemon(object): except SystemExit, errcode: exitcode = errcode + except KeyboardInterrupt: exitcode = 1 log.info(_("Interrupted by user")) + except AttributeError, errmsg: exitcode = 1 traceback.print_exc() @@ -100,6 +94,7 @@ class KolabDaemon(object): exitcode = 1 traceback.print_exc() log.error(_("Type Error: %s") % errmsg) + except: exitcode = 2 traceback.print_exc() @@ -113,72 +108,48 @@ class KolabDaemon(object): pid = os.getpid() + primary_domain = conf.get('kolab', 'primary_domain') + while 1: - primary_auth = Auth() + primary_auth = Auth(primary_domain) log.debug(_("Listing domains..."), level=5) start = time.time() + try: domains = primary_auth.list_domains() except: time.sleep(60) continue - if len(domains) == len(domain_auth.keys()): + # domains now is a list of tuples, we want the primary_domains + primary_domains = [] + for primary_domain, secondary_domains in domains: + primary_domains.append(primary_domain) + + # Now we can check if any changes happened. + added_domains = [] + removed_domains = [] + + all_domains = set(primary_domains + domain_auth.keys()) + + for domain in all_domains: + if domain in domain_auth.keys() and domain in primary_domains: + continue + elif domain in domain_auth.keys(): + removed_domains.append(domain) + else: + added_domains.append(domain) + + if len(removed_domains) == 0 and len(added_domains) == 0: time.sleep(600) - end = time.time() - log.debug( - _("Found %d domains in %d seconds") % ( - len(domains), - (end-start) - ), - level=8 - ) + log.debug(_("added domains: %r, removed domains: %r") % (added_domains, removed_domains), level=8) - for primary_domain, secondary_domains in domains: - log.debug( - _("Running for domain %s") % ( - primary_domain - ), - level=5 - ) - - if not pid == 0 and not domain_auth.has_key(primary_domain): - log.debug( - _("Domain %s did not have a key yet") % ( - primary_domain - ), - level=5 - ) - - domain_auth[primary_domain] = Auth() - # TODO: Consider threading for domain name space specific - # Authn/Authz operations. - pid = os.fork() - if pid == 0: - domain_auth[primary_domain].connect(primary_domain) - start_time = time.time() - domain_auth[primary_domain].synchronize( - primary_domain, - secondary_domains - ) - - end_time = time.time() - - log.info( - _("Synchronizing users for %s took %d seconds") - % ( - primary_domain, - (end_time-start_time) - ) - ) - - domain_auth[primary_domain].synchronize( - primary_domain, - secondary_domains - ) + for domain in added_domains: + domain_auth[domain] = Process(domain) + domain_auth[domain].start() def reload_config(self, *args, **kw): pass diff --git a/kolabd/kolabd.systemd b/kolabd/kolabd.systemd new file mode 100644 index 0000000..80305f8 --- /dev/null +++ b/kolabd/kolabd.systemd @@ -0,0 +1,15 @@ +[Unit] +Description=Kolab Groupware Server. +After=syslog.target network.target + +[Service] +Type=forking +PIDFile=/var/run/kolabd/kolabd.pid +EnvironmentFile=/etc/sysconfig/kolabd +ExecStart=/usr/sbin/kolabd $FLAGS +ExecReload=/bin/kill -HUP $MAINPID +ExecStop=/bin/kill -TERM $MAINPID + +[Install] +WantedBy=multi-user.target + diff --git a/kolabd/process.py b/kolabd/process.py new file mode 100644 index 0000000..bf65623 --- /dev/null +++ b/kolabd/process.py @@ -0,0 +1,37 @@ +# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com) +# +# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3 or, at your option, any later version +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +import multiprocessing +import time + +import pykolab +from pykolab.auth import Auth +from pykolab.translate import _ + +log = pykolab.getLogger('pykolab.daemon') +conf = pykolab.getConf() + +class KolabdProcess(multiprocessing.Process): + def __init__(self, domain): + self.domain = domain + multiprocessing.Process.__init__(self, target=self.synchronize, args=(domain,)) + + def synchronize(self, domain): + auth = Auth(domain) + auth.connect(domain) + auth.synchronize() |