]> Frank Brehm's Git Trees - pixelpark/ldap-migration.git/commitdiff
Ignoring group entires on the first attempt
authorFrank Brehm <frank.brehm@pixelpark.com>
Mon, 30 Nov 2020 16:00:16 +0000 (17:00 +0100)
committerFrank Brehm <frank.brehm@pixelpark.com>
Mon, 30 Nov 2020 16:00:16 +0000 (17:00 +0100)
lib/ldap_migration/__init__.py

index 20710114ca565dda081938b20c0b6630a14f7ccb..b4726b52626f5ac89b251635e693f2e97635868d 100644 (file)
@@ -45,7 +45,7 @@ from .config import LDAPMigrationConfiguration
 from .idict import CaseInsensitiveDict
 from .istringset import CaseInsensitiveStringSet
 
-__version__ = '0.8.1'
+__version__ = '0.8.2'
 
 LOG = logging.getLogger(__name__)
 CFG_BASENAME = 'ldap-migration.ini'
@@ -209,6 +209,7 @@ class LDAPMigrationApplication(BaseApplication):
         self.struct_dns = CaseInsensitiveDict()
         self.migrated_entries = CaseInsensitiveDict()
         self.integer_attribute_types = CaseInsensitiveStringSet([])
+        self.group_entries = CaseInsensitiveDict()
 
         super(LDAPMigrationApplication, self).__init__(
             appname=appname, verbose=verbose, version=version, base_dir=base_dir,
@@ -263,6 +264,7 @@ class LDAPMigrationApplication(BaseApplication):
         res['only_struct'] = self.only_struct
         res['dns'] = self.dns.as_dict(short=short)
         res['struct_dns'] = self.struct_dns.as_dict(short=short)
+        res['group_entries'] = self.group_entries.as_dict(short=short)
         res['integer_attribute_types'] = self.integer_attribute_types.as_list()
 
         return res
@@ -1053,7 +1055,8 @@ class LDAPMigrationApplication(BaseApplication):
 
         try:
             self._migrate_entries(
-                self.struct_dns, fh=fh, force=False, is_root=True, with_acl=False)
+                self.struct_dns, fh=fh, force=False, is_root=True,
+                with_group_entries=True, with_acl=False)
         except (ReadLDAPItemError, WriteLDAPItemError) as e:
             msg = "Abort migration: " + str(e)
             LOG.error(msg)
@@ -1074,12 +1077,12 @@ class LDAPMigrationApplication(BaseApplication):
     def migrate_all_entries(self, fh):
 
         print()
-        LOG.info("Migrating all entries from source to target LDAP cluster.")
+        LOG.info("Migrating all entries without group entries from source to target LDAP cluster.")
 
         print("", file=fh, flush=True)
-        print("#############", file=fh, flush=True)
-        print("# All entries", file=fh, flush=True)
-        print("#############", file=fh, flush=True)
+        print("#######################", file=fh, flush=True)
+        print("# All non group entries", file=fh, flush=True)
+        print("#######################", file=fh, flush=True)
 
         self.count_unchanged = 0
         self.count_added = 0
@@ -1087,20 +1090,33 @@ class LDAPMigrationApplication(BaseApplication):
 
         try:
             self._migrate_entries(
-                self.dns, fh=fh, force=False, is_root=True, with_acl=False)
+                self.dns, fh=fh, force=False, is_root=True,
+                with_group_entries=False, with_acl=False)
         except (ReadLDAPItemError, WriteLDAPItemError) as e:
             msg = "Abort migration: " + str(e)
             LOG.error(msg)
             return False
 
         print()
-        total = self.count_unchanged + self.count_added + self.count_modified
+        count_groups = 0
+        if self.group_entries:
+            count_groups = len(self.group_entries)
+            if count_groups == 1:
+                msg = "The following entry is a group entry:"
+            else:
+                msg = "The following {} entries are group entries:".format(count_groups)
+            msg += "\n" + '\n'.join(map(lambda x: ' * {!r}'.format(x), self.group_entries.keys()))
+            LOG.info(msg)
+
+        print()
+        total = self.count_unchanged + self.count_added + self.count_modified + count_groups
         msg = (
             "Performed all entries: {to} total, {ad} added, {mo} modified, "
-            "{un} unchanged.").format(
+            "{un} unchanged, {g} ignored groups.").format(
                     to=total, ad=self.count_added, mo=self.count_modified,
-                    un=self.count_unchanged)
+                    un=self.count_unchanged, g=count_groups)
         LOG.info(msg)
+
         time.sleep(3)
         return True
 
@@ -1225,23 +1241,30 @@ class LDAPMigrationApplication(BaseApplication):
         return None
 
     # -------------------------------------------------------------------------
-    def _migrate_entries(self, cur_hash, fh, force=False, is_root=False, with_acl=False):
+    def _migrate_entries(
+            self, cur_hash, fh, force=False, is_root=False,
+            with_group_entries=True, with_acl=False):
 
         wait = self.config.wait_after_write
 
         if not is_root:
 
             src_dn = cur_hash['dn']
-            if self.migrate_entry(src_dn, fh=fh, force=force, with_acl=with_acl):
+            if self.migrate_entry(
+                    src_dn, fh=fh, force=force, with_acl=with_acl,
+                    migrate_if_group=with_group_entries):
                 if wait:
                     time.sleep(wait)
 
         for key in cur_hash['childs'].keys():
             self._migrate_entries(
-                cur_hash['childs'][key], fh=fh, force=force, is_root=False, with_acl=with_acl)
+                cur_hash['childs'][key], fh=fh, force=force, is_root=False,
+                with_group_entries=with_group_entries, with_acl=with_acl)
 
     # -------------------------------------------------------------------------
-    def migrate_entry(self, src_dn, fh, force=False, with_acl=False):
+    def migrate_entry(
+            self, src_dn, fh, force=False, with_acl=False,
+            migrate_if_group=True):
 
         tgt_dn = self.mangle_dn(src_dn)
         rev_dn = self.get_reverse_dn(tgt_dn)
@@ -1254,6 +1277,30 @@ class LDAPMigrationApplication(BaseApplication):
             return False
 
         src_entry = self.get_source_item(src_dn, tgt_dn, with_acl=with_acl)
+        if not migrate_if_group:
+
+            object_classes = CaseInsensitiveStringSet([])
+            for src_at_name in src_entry['attributes']:
+                if src_at_name.lower() == 'objectclass':
+                    for src_oc_name in src_entry['attributes'][src_at_name]:
+                        object_classes.add(src_oc_name)
+            is_group = False
+            if 'groupOfURLs' in object_classes:
+                is_group = True
+            elif 'groupOfNames' in object_classes:
+                is_group = True
+            elif 'groupOfUniqueNames' in object_classes:
+                is_group = True
+
+            if is_group:
+                self.group_entries[tgt_dn] = {
+                    'migrated': False,
+                    'object_classes': object_classes,
+                }
+                LOG.debug("Entry {e!r} is a group entry: {c}".format(
+                    e=tgt_dn, c=object_classes.as_list()))
+                return False
+
         tgt_entry = self.get_target_item(tgt_dn, with_acl=with_acl)
 
         if tgt_entry: