]> Frank Brehm's Git Trees - pixelpark/ldap-migration.git/commitdiff
Better error handling on write operations
authorFrank Brehm <frank.brehm@pixelpark.com>
Thu, 26 Nov 2020 16:30:44 +0000 (17:30 +0100)
committerFrank Brehm <frank.brehm@pixelpark.com>
Thu, 26 Nov 2020 16:30:44 +0000 (17:30 +0100)
lib/ldap_migration/__init__.py

index fad88c424b452d7e854d29bc1ffa245b3ca1b146..ae857758aa652db4cae3b3e7beaa454a347269ca 100644 (file)
@@ -45,7 +45,7 @@ from .config import LDAPMigrationConfiguration
 from .idict import CaseInsensitiveDict
 from .istringset import CaseInsensitiveStringSet
 
-__version__ = '0.7.0'
+__version__ = '0.7.1'
 
 LOG = logging.getLogger(__name__)
 CFG_BASENAME = 'ldap-migration.ini'
@@ -64,7 +64,13 @@ class CommonLDAPMigrationError(FbAppError, LDAPException):
 
 # =============================================================================
 class ReadLDAPItemError(CommonLDAPMigrationError):
-    """Error class in cae, a LDAP item could not be read."""
+    """Error class in case, a LDAP item could not be read."""
+    pass
+
+
+# =============================================================================
+class WriteLDAPItemError(CommonLDAPMigrationError):
+    """Error class in case, a LDAP item could not be written."""
     pass
 
 
@@ -1017,7 +1023,7 @@ class LDAPMigrationApplication(BaseApplication):
 
         try:
             self._migrate_entries(self.struct_dns, fh=fh, is_root=True, with_acl=False)
-        except ReadLDAPItemError as e:
+        except (ReadLDAPItemError, WriteLDAPItemError) as e:
             msg = "Abort migration: " + str(e)
             LOG.error(msg)
             return False
@@ -1037,6 +1043,7 @@ class LDAPMigrationApplication(BaseApplication):
 
         object_classes = []
         target_entry = {}
+        used_classes = CaseInsensitiveStringSet([])
 
         for attribute_name in src_entry['attributes']:
             if attribute_name.lower() == 'objectclass':
@@ -1049,6 +1056,7 @@ class LDAPMigrationApplication(BaseApplication):
                             LOG.debug(msg)
                         continue
                     tgt_oc_name = self.object_classes.get_key(src_oc_name)
+                    used_classes.add(tgt_oc_name)
                     object_classes.append(tgt_oc_name)
                 continue
             if attribute_name not in self.attribute_types:
@@ -1061,6 +1069,11 @@ class LDAPMigrationApplication(BaseApplication):
             tgt_at_name = self.attribute_types.get_key(attribute_name)
             target_entry[tgt_at_name] = copy.copy(src_entry['attributes'][attribute_name])
 
+        if ('sunservice' in used_classes) or ('sunServiceComponent' in used_classes):
+            if 'organizationalUnit' not in used_classes:
+                used_classes.add('organizationalUnit')
+                object_classes.append('organizationalUnit')
+
         return (object_classes, target_entry)
 
     # -------------------------------------------------------------------------
@@ -1187,7 +1200,19 @@ class LDAPMigrationApplication(BaseApplication):
                     LOG.debug(msg)
                 self.count_modified += 1
                 if not self.simulate:
-                    self.target.modify(tgt_dn, changes)
+                    mod_status, mod_result, mod_response, _ = self.target.modify(tgt_dn, changes)
+                    if mod_status:
+                        LOG.debug("Modifying successfull.")
+                        if self.verbose > 2:
+                            LOG.debug("Result of modifying:\n{}".format(pp(mod_result)))
+                    else:
+                        msg = "Modifying NOT successfull:\n{res}\n"
+                        msg += "Source attributes:\n{sattr}\n"
+                        msg += "Changes:\n{ch}"
+                        msg = msg.format(
+                            res=pp(mod_result), sattr=pp(src_entry['attributes']),
+                            ch=pp(changes))
+                        raise WriteLDAPItemError(msg)
                 self.migrated_entries[rev_dn] = tgt_dn
                 ts = datetime.datetime.now(self.tz).isoformat(' ', timespec='seconds')
                 line = "{dn}: {ts}".format(dn=tgt_dn, ts=ts)
@@ -1207,7 +1232,23 @@ class LDAPMigrationApplication(BaseApplication):
             LOG.debug(msg)
         self.count_added += 1
         if not self.simulate:
-            self.target.add(tgt_dn, object_class=tgt_obj_classes, attributes=tgt_entry)
+            cr_status, cr_result, cr_response, _ = self.target.add(
+                tgt_dn, object_class=tgt_obj_classes, attributes=tgt_entry)
+            if cr_status:
+                LOG.debug("Creation successfull.")
+                if self.verbose > 2:
+                    LOG.debug("Result of creation:\n{}".format(pp(cr_result)))
+            else:
+                msg = "Creation NOT successfull:\n{res}\n"
+                msg += "Source attributes:\n{sattr}\n"
+                msg += "Target-DN: {dn!r}\n"
+                msg += "Target Object classes:\n{ocs}\n"
+                msg += "Target attributes:\n{tattr}"
+                msg = msg.format(
+                    res=pp(cr_result), sattr=pp(src_entry['attributes']),
+                    dn=tgt_dn, ocs=pp(tgt_obj_classes), tattr=pp(tgt_entry))
+                raise WriteLDAPItemError(msg)
+
         self.migrated_entries[rev_dn] = tgt_dn
         ts = datetime.datetime.now(self.tz).isoformat(' ', timespec='seconds')
         line = "{dn}: {ts}".format(dn=tgt_dn, ts=ts)
@@ -1220,30 +1261,30 @@ class LDAPMigrationApplication(BaseApplication):
         if is_sequence(first) and not is_sequence(second):
             if len(first) == 1:
                 value = first[0]
-                if value.lower() == second.lower():
+                if str(value).lower() == str(second).lower():
                     return True
             return False
 
         if is_sequence(second) and not is_sequence(first):
             if len(second) == 1:
                 value = second[0]
-                if value.lower() == first.lower():
+                if str(value).lower() == str(first).lower():
                     return True
             return False
 
         if not is_sequence(first):
             # second is also not an array at this point
-            if first.lower() == second.lower():
+            if str(first).lower() == str(second).lower():
                 return True
             return False
 
         # Both parameters are values
         first_array = []
         for val in sorted(first, key=str.lower):
-            first_array.append(val.lower())
+            first_array.append(str(val).lower())
         second_array = []
         for val in sorted(second, key=str.lower):
-            second_array.append(val.lower())
+            second_array.append(str(val).lower())
 
         if first_array == second_array:
             return True