In other words: make *-del commands accept 1 or more primary keys of entries to be deleted. We can now delete more entries at a time with a single command.

Ticket #20

Pavel
>From 1aabeb75114ef01ec23044031664f82ed0364825 Mon Sep 17 00:00:00 2001
From: Pavel Zuna <pz...@redhat.com>
Date: Fri, 1 Oct 2010 12:35:27 -0400
Subject: [PATCH 2/3] Add LDAPMultiQuery base class and make it the base of LDAPDelete.

In other words: make *-del commands accept 1 or more primary keys
of entries to be deleted.

Ticket #20
---
 ipalib/plugins/baseldap.py |   98 +++++++++++++++++++++++++++++---------------
 1 files changed, 65 insertions(+), 33 deletions(-)

diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py
index 1757a45..f6b98e2 100644
--- a/ipalib/plugins/baseldap.py
+++ b/ipalib/plugins/baseldap.py
@@ -345,6 +345,19 @@ class LDAPQuery(CallbackInterface, crud.PKQuery):
             yield self.obj.primary_key.clone(attribute=True, query=True)
 
 
+class LDAPMultiQuery(LDAPQuery):
+    """
+    Base class for commands that need to retrieve one or more existing entries.
+    """
+    def get_args(self):
+        for key in self.obj.get_ancestor_primary_keys():
+            yield key
+        if self.obj.primary_key:
+            yield self.obj.primary_key.clone(
+                attribute=True, query=True, multivalue=True
+            )
+
+
 class LDAPRetrieve(LDAPQuery):
     """
     Retrieve an LDAP entry.
@@ -512,7 +525,7 @@ class LDAPUpdate(LDAPQuery, crud.Update):
         raise exc
 
 
-class LDAPDelete(LDAPQuery):
+class LDAPDelete(LDAPMultiQuery):
     """
     Delete an LDAP entry and all of its direct subentries.
     """
@@ -521,47 +534,66 @@ class LDAPDelete(LDAPQuery):
     def execute(self, *keys, **options):
         ldap = self.obj.backend
 
-        dn = self.obj.get_dn(*keys, **options)
+        def delete_entry(pkey):
+            nkeys = keys[:-1] + (pkey, )
+            dn = self.obj.get_dn(*nkeys, **options)
 
-        for callback in self.PRE_CALLBACKS:
-            if hasattr(callback, 'im_self'):
-                dn = callback(ldap, dn, *keys, **options)
-            else:
-                dn = callback(self, ldap, dn, *keys, **options)
+            for callback in self.PRE_CALLBACKS:
+                if hasattr(callback, 'im_self'):
+                    dn = callback(ldap, dn, *nkeys, **options)
+                else:
+                    dn = callback(self, ldap, dn, *nkeys, **options)
 
-        def delete_subtree(base_dn):
-            truncated = True
-            while truncated:
+            def delete_subtree(base_dn):
+                truncated = True
+                while truncated:
+                    try:
+                        (subentries, truncated) = ldap.find_entries(
+                            None, [''], base_dn, ldap.SCOPE_ONELEVEL
+                        )
+                    except errors.NotFound:
+                        break
+                    else:
+                        for (dn_, entry_attrs) in subentries:
+                            delete_subtree(dn_)
                 try:
-                    (subentries, truncated) = ldap.find_entries(
-                        None, [''], base_dn, ldap.SCOPE_ONELEVEL
-                    )
-                except errors.NotFound:
-                    break
+                    ldap.delete_entry(base_dn, normalize=self.obj.normalize_dn)
+                except errors.ExecutionError, e:
+                    try:
+                        self._call_exc_callbacks(
+                            nkeys, options, e, ldap.delete_entry, base_dn,
+                            normalize=self.obj.normalize_dn
+                        )
+                    except errors.NotFound:
+                        self.obj.handle_not_found(*nkeys)
+
+            delete_subtree(dn)
+
+            for callback in self.POST_CALLBACKS:
+                if hasattr(callback, 'im_self'):
+                    result = callback(ldap, dn, *nkeys, **options)
                 else:
-                    for (dn_, entry_attrs) in subentries:
-                        delete_subtree(dn_)
-            try:
-                ldap.delete_entry(base_dn, normalize=self.obj.normalize_dn)
-            except errors.ExecutionError, e:
-                try:
-                    self._call_exc_callbacks(
-                        keys, options, e, ldap.delete_entry, base_dn,
-                        normalize=self.obj.normalize_dn
-                    )
-                except errors.NotFound:
-                    self.obj.handle_not_found(*keys)
+                    result = callback(self, ldap, dn, *nkeys, **options)
 
-        delete_subtree(dn)
+            return result
 
-        for callback in self.POST_CALLBACKS:
-            if hasattr(callback, 'im_self'):
-                result = callback(ldap, dn, *keys, **options)
+        if not self.obj.primary_key or not isinstance(keys[-1], (list, tuple)):
+            keys = keys[:-1] + (keys[-1], )
+
+        deleted = []
+        failed = []
+        result = True
+        for pkey in keys[-1]:
+            try:
+                if not delete_entry(pkey):
+                    result = False
+            except errors.ExecutionError:
+                failed.append(pkey)
             else:
-                result = callback(self, ldap, dn, *keys, **options)
+                deleted.append(pkey)
 
         if self.obj.primary_key and keys[-1] is not None:
-            return dict(result=result, value=keys[-1])
+            return dict(result=result, value=u','.join(deleted))
         return dict(result=result, value=u'')
 
     def pre_callback(self, ldap, dn, *keys, **options):
-- 
1.7.1.1

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to