[Freeipa-devel] [PATCH] improved modlist generator

Kevin McCarthy kmccarth at redhat.com
Mon Aug 20 23:20:23 UTC 2007


This patch is an improved version of the modlist generator.  It only
updates the particular attribute values that changed (which will be
important for attributes with large numbers of multiple values, like
groups).

Currently, this will error out if two people edit the same field instead
of providing last-update wins.  In order to provide that, we need to
send the deletes and the adds using two separate transactions and ignore
"not found" errors for the deletes.

I will tackle that next.

-Kevin

-------------- next part --------------
# HG changeset patch
# User Kevin McCarthy <kmccarth at redhat.com>
# Date 1187651892 25200
# Node ID 708f908afcb75641a095a68effe9b322b80f363c
# Parent  d5039d3c50402f2b518b30abbc8c902b9c882464
Improved modlist generator.

diff -r d5039d3c5040 -r 708f908afcb7 ipa-server/ipaserver/ipaldap.py
--- a/ipa-server/ipaserver/ipaldap.py	Mon Aug 20 14:23:23 2007 -0700
+++ b/ipa-server/ipaserver/ipaldap.py	Mon Aug 20 16:18:12 2007 -0700
@@ -314,16 +314,47 @@ class IPAdmin(SimpleLDAPObject):
 
         sctrl = self.__get_server_controls__()
 
-        # find the differences but don't remove attributes that are missing
-        # from the update
-        modlist = modifyModlist(olduser, newuser, None, 1)
+        modlist = self.generateModList(olduser, newuser)
 
         try:
             self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
             self.modify_s(dn, modlist)
         except ldap.LDAPError, e:
             raise e
+            # raise Exception, modlist
         return "Success"
+
+    def generateModList(self, old_entry, new_entry):
+        """A mod list generator that computes more precise modification lists
+           than the python-ldap version.  This version purposely generates no
+           REPLACE operations, to deal with multi-user updates more properly."""
+        modlist = []
+
+        keys = set(old_entry.keys())
+        keys.update(new_entry.keys())
+
+        for key in keys:
+            new_values = new_entry.get(key, [])
+            if not(isinstance(new_values,list) or isinstance(new_values,tuple)):
+                new_values = [new_values]
+            new_values = filter(lambda value:value!=None, new_values)
+            new_values = set(new_values)
+
+            old_values = old_entry.get(key, [])
+            if not(isinstance(old_values,list) or isinstance(old_values,tuple)):
+                old_values = [old_values]
+            old_values = filter(lambda value:value!=None, old_values)
+            old_values = set(old_values)
+
+            adds = list(new_values.difference(old_values))
+            removes = list(old_values.difference(new_values))
+
+            if len(adds) > 0:
+                modlist.append((ldap.MOD_ADD, key, adds))
+            if len(removes) > 0:
+                modlist.append((ldap.MOD_DELETE, key, removes))
+
+        return modlist
 
     def inactivateEntry(self,dn,has_key):
         """Rather than deleting entries we mark them as inactive.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 2228 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/freeipa-devel/attachments/20070820/cdb1a3c0/attachment.bin>


More information about the Freeipa-devel mailing list