12 commits - cyruslib.py kolabd/__init__.py pykolab/auth pykolab/cli pykolab/imap pykolab/plugins pykolab.spec.in pykolab/utils.py saslauthd/__init__.py wallace/__init__.py

Jeroen van Meeuwen vanmeeuwen at kolabsys.com
Wed Jun 13 12:48:20 CEST 2012


 cyruslib.py                                 |   21 +++++
 kolabd/__init__.py                          |    6 +
 pykolab.spec.in                             |    2 
 pykolab/auth/ldap/__init__.py               |  106 +++++++++++++++++-----------
 pykolab/cli/cmd_list_mailboxes.py           |    2 
 pykolab/cli/cmd_list_quota.py               |   64 ++++++++++++++++
 pykolab/cli/cmd_sync.py                     |    5 +
 pykolab/imap/__init__.py                    |   37 ++++++---
 pykolab/plugins/recipientpolicy/__init__.py |   18 ++++
 pykolab/utils.py                            |   73 +++++++++++++++++++
 saslauthd/__init__.py                       |   12 +++
 wallace/__init__.py                         |    6 +
 12 files changed, 296 insertions(+), 56 deletions(-)

New commits:
commit 968f53e040591fce8790cd0aba030f6f6810e758
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Wed Jun 13 11:47:42 2012 +0100

    Some pylint errors,
    Add lq/lqr functions

diff --git a/pykolab/imap/__init__.py b/pykolab/imap/__init__.py
index dde09ff..047e908 100644
--- a/pykolab/imap/__init__.py
+++ b/pykolab/imap/__init__.py
@@ -300,12 +300,18 @@ class IMAP(object):
                         )
 
                     if not additional_folders == None:
-                        self.user_mailbox_create_additional_folders(mailbox_base_name, additional_folders)
+                        self.user_mailbox_create_additional_folders(
+                                mailbox_base_name,
+                                additional_folders
+                            )
 
         return folder_name
 
     def user_mailbox_create_additional_folders(self, folder, additional_folders):
-        log.debug(_("Creating additional folders for user %s") % (folder), level=8)
+        log.debug(
+                _("Creating additional folders for user %s") % (folder),
+                level=8
+            )
 
         for additional_folder in additional_folders.keys():
             _add_folder = {}
@@ -397,6 +403,9 @@ class IMAP(object):
         """
         return self.has_folder('user%s%s' %(self.imap.separator, mailbox_base_name))
 
+    def user_mailbox_quota(self, mailbox_quota):
+        pass
+
     def user_mailbox_rename(self, old_name, new_name):
         old_name = "user%s%s" % (self.imap.separator,old_name)
         new_name = "user%s%s" % (self.imap.separator,new_name)
@@ -688,6 +697,12 @@ class IMAP(object):
 
         self.imap.dm(mailfolder_path)
 
+    def get_quota(self, mailfolder_path):
+        return self.lq(mailfolder_path)
+
+    def get_quota_root(self, mailfolder_path):
+        return self.lqr(mailfolder_path)
+
     def list_user_folders(self, primary_domain=None, secondary_domains=[]):
         """
             List the INBOX folders in the IMAP backend. Returns a list of unique
@@ -737,5 +752,11 @@ class IMAP(object):
     def lm(self, *args, **kw):
         return self.imap.lm(*args, **kw)
 
+    def lq(self, *args, **kw):
+        return self.imap.lq(*args, **kw)
+
+    def lqr(self, *args, **kw):
+        return self.imap.lqr(*args, **kw)
+
     def undelete_mailfolder(self, *args, **kw):
         self.imap.undelete_mailfolder(*args, **kw)


commit 1d22592d4c67620effdbfb9fdf72b63bc8303ece
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Wed Jun 13 11:47:13 2012 +0100

    Start implementing the quota enforcement again

diff --git a/pykolab/auth/ldap/__init__.py b/pykolab/auth/ldap/__init__.py
index 32f43ff..7f25a24 100644
--- a/pykolab/auth/ldap/__init__.py
+++ b/pykolab/auth/ldap/__init__.py
@@ -792,6 +792,21 @@ class LDAP(pykolab.base.Base):
                 callback=self._synchronize_callback,
             )
 
+    def user_quota(self, entry_id, folder):
+        quota_attribute = self.config_get('quota_attribute')
+
+        if quota_attribute == None:
+            return
+
+        self._bind()
+
+        entry_dn = self.entry_dn(entry_id)
+
+        current_ldap_quota = self.get_entry_attribute(entry_dn, quota_attribute)
+        current_imap_quota = self.imap.get_quota(folder)
+
+        default_quota = self.config_get('default_quota')
+
     ###
     ### API depth level increasing!
     ###
@@ -942,6 +957,8 @@ class LDAP(pykolab.base.Base):
         if not entry[mailserver_attribute] == server:
             self.set_entry_attribute(entry, mailserver_attribute, server)
 
+        self.user_quota(entry, folder)
+
     def _change_delete_group(self, entry, change):
         """
             An entry of type group was deleted.


commit dd9464f89d8a8632f5ae777b5964ff0d04be7bb9
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Wed Jun 13 11:46:45 2012 +0100

    Clarify it's not UTF-7 exactly, it's IMAP UTF-7 ;-)

diff --git a/pykolab/cli/cmd_list_mailboxes.py b/pykolab/cli/cmd_list_mailboxes.py
index 185dea2..3451e7c 100644
--- a/pykolab/cli/cmd_list_mailboxes.py
+++ b/pykolab/cli/cmd_list_mailboxes.py
@@ -41,7 +41,7 @@ def cli_options():
                                 dest    = "raw",
                                 action  = "store_true",
                                 default = False,
-                                help    = _("Display raw UTF-7 folder names"))
+                                help    = _("Display raw IMAP UTF-7 folder names"))
 
 def execute(*args, **kw):
     """


commit 8c1f5eb1594913d07d727409fb682dd5e6416b60
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Wed Jun 13 11:40:24 2012 +0100

    Add command 'list-quota'

diff --git a/pykolab/cli/cmd_list_quota.py b/pykolab/cli/cmd_list_quota.py
new file mode 100644
index 0000000..d71f272
--- /dev/null
+++ b/pykolab/cli/cmd_list_quota.py
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+# 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 sys
+
+import commands
+
+import pykolab
+
+from pykolab.imap import IMAP
+from pykolab.translate import _
+
+log = pykolab.getLogger('pykolab.cli')
+conf = pykolab.getConf()
+
+def __init__():
+    commands.register('list_quota', execute, description=description(), aliases=['lq'])
+
+def description():
+    return """List quota for a folder."""
+
+def execute(*args, **kw):
+    """
+        List quota for a mailbox
+    """
+
+    try:
+        quota_folder = conf.cli_args.pop(0)
+    except IndexError, e:
+        quota_folder = '*'
+
+    imap = IMAP()
+    imap.connect()
+
+    folders = []
+
+    quota_folders = imap.lm(quota_folder)
+    for quota_folder in quota_folders:
+        try:
+            (used, quota) = imap.get_quota(quota_folder)
+            percentage = round((used/quota)*100, 1)
+            print "%d (Used: %d, Percentage: %d)" % (quota, used, percentage)
+        except:
+            (quota_root, used, quota) = imap.get_quota_root(quota_folder)
+            percentage = round((used/quota)*100, 1)
+            print "%d (Root: %s, Used: %d, Percentage: %d)" % (quota, quota_root, used, percentage)
+
+


commit 9d544f1ed4f7181d11916d3cf19a00e08acfe1a3
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Wed Jun 13 11:39:54 2012 +0100

    Fix command-line sync

diff --git a/pykolab/cli/cmd_sync.py b/pykolab/cli/cmd_sync.py
index 2cbb05f..4ac675a 100644
--- a/pykolab/cli/cmd_sync.py
+++ b/pykolab/cli/cmd_sync.py
@@ -19,8 +19,10 @@
 
 import commands
 
+import time
 import pykolab
 
+from pykolab.auth import Auth
 from pykolab.translate import _
 
 log = pykolab.getLogger('pykolab.cli')
@@ -30,6 +32,7 @@ def __init__():
     commands.register('sync', execute, description="Synchronize Kolab Users with IMAP.")
 
 def execute(*args, **kw):
+    auth = Auth()
     log.debug(_("Listing domains..."), level=5)
     start_time = time.time()
     domains = auth.list_domains()
@@ -48,7 +51,7 @@ def execute(*args, **kw):
         log.debug(_("Running for domain %s") % (primary_domain), level=8)
         auth.connect(primary_domain)
         start_time = time.time()
-        auth.synchronize(primary_domain, secondary_domains)
+        auth.synchronize()
         end_time = time.time()
 
         log.info(_("Synchronizing users for %s took %d seconds")


commit f2247ae5bc393e813e3775c82e1c051dbbcabd78
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Wed Jun 13 11:39:18 2012 +0100

    Add hard dependency on pyasn1{,-modules}

diff --git a/pykolab.spec.in b/pykolab.spec.in
index 5ff1d7d..332f692 100644
--- a/pykolab.spec.in
+++ b/pykolab.spec.in
@@ -31,6 +31,8 @@ BuildRequires:      python-ldap
 BuildRequires:      python-nose
 Requires:           kolab-cli = %{version}-%{release}
 Requires:           python-ldap >= 2.4
+Requires:           python-pyasn1
+Requires:           python-pyasn1-modules
 Requires(pre):      /usr/sbin/useradd
 Requires(pre):      /usr/sbin/usermod
 Requires(pre):      /usr/sbin/groupadd


commit e3d33d10fbdbf362b89476fbdab6c7a6ca0a45fb
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Wed Jun 13 11:37:40 2012 +0100

    Make use of the new ensure_directory() function (#840)

diff --git a/kolabd/__init__.py b/kolabd/__init__.py
index bf4fc7b..5283c9f 100644
--- a/kolabd/__init__.py
+++ b/kolabd/__init__.py
@@ -91,6 +91,12 @@ class KolabDaemon(object):
 
         exitcode = 0
 
+        utils.ensure_directory(
+                os.path.dirname(conf.pidfile),
+                conf.process_username,
+                conf.process_groupname
+            )
+
         try:
             try:
                 (ruid, euid, suid) = os.getresuid()
diff --git a/saslauthd/__init__.py b/saslauthd/__init__.py
index 6daebf3..1497dda 100644
--- a/saslauthd/__init__.py
+++ b/saslauthd/__init__.py
@@ -60,6 +60,12 @@ class SASLAuthDaemon(object):
 
         conf.finalize_conf()
 
+        utils.ensure_directory(
+                os.path.dirname(conf.pidfile),
+                conf.process_username,
+                conf.process_groupname
+            )
+
         self.thread_count = 0
 
     def run(self):
@@ -116,6 +122,12 @@ class SASLAuthDaemon(object):
 
         s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
 
+        utils.ensure_directory(
+                '/var/run/saslauthd/',
+                conf.process_username,
+                conf.process_groupname
+            )
+
         # TODO: The saslauthd socket path could be a setting.
         try:
             os.remove('/var/run/saslauthd/mux')
diff --git a/wallace/__init__.py b/wallace/__init__.py
index 45ad211..5d056df 100644
--- a/wallace/__init__.py
+++ b/wallace/__init__.py
@@ -116,6 +116,12 @@ class WallaceDaemon(object):
 
         conf.finalize_conf()
 
+        utils.ensure_directory(
+                os.path.dirname(conf.pidfile),
+                conf.process_username,
+                conf.process_groupname
+            )
+
         import modules
         modules.__init__()
 


commit 1df64e63556db23be0d701ca10c4fd35f87f9aec
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Wed Jun 13 11:37:19 2012 +0100

    Add helper function to ensure a directory exists, and with the correct permissions

diff --git a/pykolab/utils.py b/pykolab/utils.py
index f0fa30a..f766983 100644
--- a/pykolab/utils.py
+++ b/pykolab/utils.py
@@ -121,6 +121,79 @@ def ask_confirmation(question, default="y", all_inclusive_no=True):
             else:
                 return True
 
+def ensure_directory(_dir, _user='root', _group='root'):
+    os.makedirs(_dir)
+    try:
+        try:
+            (ruid, euid, suid) = os.getresuid()
+            (rgid, egid, sgid) = os.getresgid()
+        except AttributeError, errmsg:
+            ruid = os.getuid()
+            rgid = os.getgid()
+
+        if ruid == 0:
+            # Means we can setreuid() / setregid() / setgroups()
+            if rgid == 0:
+                # Get group entry details
+                try:
+                    (
+                            group_name,
+                            group_password,
+                            group_gid,
+                            group_members
+                        ) = grp.getgrnam(_group)
+
+                except KeyError:
+                    print >> sys.stderr, _("Group %s does not exist") % (
+                            _group
+                        )
+
+                    sys.exit(1)
+
+                # Set real and effective group if not the same as current.
+                if not group_gid == rgid:
+                    log.debug(
+                            _("Switching real and effective group id to %d") % (
+                                    group_gid
+                                ),
+                            level=8
+                        )
+
+                    os.chown(_dir, -1, group_gid)
+
+            if ruid == 0:
+                # Means we haven't switched yet.
+                try:
+                    (
+                            user_name,
+                            user_password,
+                            user_uid,
+                            user_gid,
+                            user_gecos,
+                            user_homedir,
+                            user_shell
+                        ) = pwd.getpwnam(_user)
+
+                except KeyError:
+                    print >> sys.stderr, _("User %s does not exist") % (_user)
+
+                    sys.exit(1)
+
+
+                # Set real and effective user if not the same as current.
+                if not user_uid == ruid:
+                    log.debug(
+                            _("Switching real and effective user id to %d") % (
+                                    user_uid
+                                ),
+                            level=8
+                        )
+
+                    os.chown(_dir, user_uid, -1)
+
+    except:
+        log.error(_("Could not change the permissions on %s") % (_dir))
+
 def generate_password():
     import subprocess
 


commit d310f8a8ba453cc1030a6a83cbdd8332a5fb64ff
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Wed Jun 13 11:35:06 2012 +0100

    Add QUOTAROOT command lqr

diff --git a/cyruslib.py b/cyruslib.py
index 7df43a0..20dd55b 100644
--- a/cyruslib.py
+++ b/cyruslib.py
@@ -586,6 +586,27 @@ class CYRUS:
             self.__verbose( '[GETQUOTA %s] BAD: Error while parsing results' % mailbox )
             return 0, 0
 
+    def lqr(self, mailbox):
+        """List Quota Root"""
+        self.__prepare('GETQUOTAROOT', mailbox)
+        res, msg = self.__docommand("getquotaroot", self.decode(mailbox))
+        (_mailbox, _root) = msg[0][0].split()
+
+        match = re_q0.match(msg[1][0])
+        if match:
+            self.__verbose( '[GETQUOTAROOT %s] QUOTAROOT (Unlimited)' % mailbox )
+            return _root, 0, 0
+
+        match = re_q.match(msg[1][0])
+        try:
+            used = int(match.group(2))
+            quota = int(match.group(3))
+            self.__verbose( '[GETQUOTAROOT %s] %s: QUOTA (%d/%d)' % (mailbox, res, used, quota) )
+            return _root, used, quota
+        except:
+            self.__verbose( '[GETQUOTAROOT %s] BAD: Error while parsing results' % mailbox )
+            return _root, 0, 0
+
     def sq(self, mailbox, limit):
         """Set Quota"""
         self.__prepare('SETQUOTA', mailbox)


commit 5c1c4c70bae2be6e50063434e8ec69ef89bd4983
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Tue Jun 12 13:08:50 2012 +0100

    Search for or fallback to the default_locale for the user's preferredlanguage attribute. (#839)

diff --git a/pykolab/plugins/recipientpolicy/__init__.py b/pykolab/plugins/recipientpolicy/__init__.py
index ab72980..1c97857 100644
--- a/pykolab/plugins/recipientpolicy/__init__.py
+++ b/pykolab/plugins/recipientpolicy/__init__.py
@@ -61,6 +61,15 @@ class KolabRecipientpolicy(object):
         elif not user_attrs['domain'] == kw['primary_domain']:
             user_attrs['domain'] = kw['primary_domain']
 
+        if not user_attrs.has_key('preferredlanguage'):
+            default_locale = conf.get(user_attrs['domain'], 'default_locale')
+            if default_locale == None:
+                default_locale = conf.get(user_attrs['domain'], 'default_locale')
+            if default_locale == None:
+                default_locale = 'en_US'
+
+            user_attrs['preferredlanguage'] = default_locale
+
         try:
             mail = kw['primary_mail'] % user_attrs
             mail = utils.translate(mail, user_attrs['preferredlanguage'])
@@ -91,6 +100,15 @@ class KolabRecipientpolicy(object):
         elif not user_attrs['domain'] == kw['primary_domain']:
             user_attrs['domain'] = kw['primary_domain']
 
+        if not user_attrs.has_key('preferredlanguage'):
+            default_locale = conf.get(user_attrs['domain'], 'default_locale')
+            if default_locale == None:
+                default_locale = conf.get(user_attrs['domain'], 'default_locale')
+            if default_locale == None:
+                default_locale = 'en_US'
+
+            user_attrs['preferredlanguage'] = default_locale
+
         try:
             exec("alternative_mail_routines = %s" % kw['secondary_mail'])
         except Exception, e:


commit ac539faed494c3abdf6abbbae42fbb9dfcb4aad8
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Mon Jun 11 14:12:50 2012 +0100

    Remove synchronize() function (obsolete)

diff --git a/pykolab/imap/__init__.py b/pykolab/imap/__init__.py
index 9735312..dde09ff 100644
--- a/pykolab/imap/__init__.py
+++ b/pykolab/imap/__init__.py
@@ -734,18 +734,6 @@ class IMAP(object):
 
         return folders
 
-    def synchronize(self, users=[], primary_domain=None, secondary_domains=[]):
-        self.connect(domain=primary_domain)
-        self.users.extend(users)
-
-        self.move_user_folders(users, domain=primary_domain)
-
-        self.inbox_folders.extend(self.create_user_folders(users, primary_domain, secondary_domains))
-
-        self.set_user_folder_quota(users, primary_domain, secondary_domains, self.inbox_folders)
-
-        self.set_user_mailhost(users, primary_domain, secondary_domains, self.inbox_folders)
-
     def lm(self, *args, **kw):
         return self.imap.lm(*args, **kw)
 


commit 3df45ed444e38853e683334b4a5cbdd7e3d17d2a
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Mon Jun 11 14:12:40 2012 +0100

    Sort functions alphabetically

diff --git a/pykolab/auth/ldap/__init__.py b/pykolab/auth/ldap/__init__.py
index c075742..32f43ff 100644
--- a/pykolab/auth/ldap/__init__.py
+++ b/pykolab/auth/ldap/__init__.py
@@ -818,50 +818,18 @@ class LDAP(pykolab.base.Base):
             except ldap.INVALID_CREDENTIALS:
                 log.error(_("Invalid bind credentials"))
 
-    def _change_add_user(self, entry, change):
-        """
-            An entry of type user was added.
+    def _change_add_group(self, entry, change):
         """
-        mailserver_attribute = self.config_get('mailserver_attribute')
-        if mailserver_attribute == None:
-            mailserver_attribute = 'mailhost'
-
-        result_attribute = conf.get('cyrus-sasl', 'result_attribute')
-
-        if not entry.has_key(mailserver_attribute):
-            entry[mailserver_attribute] = \
-                self.get_entry_attribute(entry, mailserver_attribute)
-
-        rcpt_addrs = self.recipient_policy(entry)
-        for key in rcpt_addrs:
-            entry[key] = rcpt_addrs[key]
-
-        if not entry.has_key(result_attribute):
-            return
-
-        if entry[result_attribute] == None:
-            return
-
-        cache.get_entry(self.domain, entry)
-
-        self.imap.connect(domain=self.domain)
-
-        if not self.imap.user_mailbox_exists(entry[result_attribute]):
-            folder = self.imap.user_mailbox_create(
-                    entry[result_attribute],
-                    entry[mailserver_attribute]
-                )
-        else:
-            folder = "user%s%s" % (self.imap.separator,entry[result_attribute])
-
-        server = self.imap.user_mailbox_server(folder)
+            An entry of type group was added.
 
-        if not entry[mailserver_attribute] == server:
-            self.set_entry_attribute(entry, mailserver_attribute, server)
+            The Kolab daemon has little to do for this type of action on this
+            type of entry.
+        """
+        pass
 
-    def _change_add_group(self, entry, change):
+    def _change_add_resource(self, entry, change):
         """
-            An entry of type group was added.
+            An entry of type resource was added.
 
             The Kolab daemon has little to do for this type of action on this
             type of entry.
@@ -933,6 +901,47 @@ class LDAP(pykolab.base.Base):
         #if server == None:
             #self.entry_set_attribute(mailserver_attribute, server)
 
+    def _change_add_user(self, entry, change):
+        """
+            An entry of type user was added.
+        """
+        mailserver_attribute = self.config_get('mailserver_attribute')
+        if mailserver_attribute == None:
+            mailserver_attribute = 'mailhost'
+
+        result_attribute = conf.get('cyrus-sasl', 'result_attribute')
+
+        if not entry.has_key(mailserver_attribute):
+            entry[mailserver_attribute] = \
+                self.get_entry_attribute(entry, mailserver_attribute)
+
+        rcpt_addrs = self.recipient_policy(entry)
+        for key in rcpt_addrs:
+            entry[key] = rcpt_addrs[key]
+
+        if not entry.has_key(result_attribute):
+            return
+
+        if entry[result_attribute] == None:
+            return
+
+        cache.get_entry(self.domain, entry)
+
+        self.imap.connect(domain=self.domain)
+
+        if not self.imap.user_mailbox_exists(entry[result_attribute]):
+            folder = self.imap.user_mailbox_create(
+                    entry[result_attribute],
+                    entry[mailserver_attribute]
+                )
+        else:
+            folder = "user%s%s" % (self.imap.separator,entry[result_attribute])
+
+        server = self.imap.user_mailbox_server(folder)
+
+        if not entry[mailserver_attribute] == server:
+            self.set_entry_attribute(entry, mailserver_attribute, server)
+
     def _change_delete_group(self, entry, change):
         """
             An entry of type group was deleted.





More information about the commits mailing list