]> Frank Brehm's Git Trees - pixelpark/ldap-migration.git/commitdiff
Writing log of migrated entries
authorFrank Brehm <frank.brehm@pixelpark.com>
Thu, 26 Nov 2020 13:26:21 +0000 (14:26 +0100)
committerFrank Brehm <frank.brehm@pixelpark.com>
Thu, 26 Nov 2020 13:26:21 +0000 (14:26 +0100)
lib/ldap_migration/__init__.py
requirements.txt

index 0295c310a66ac9a7ed71547ea6667a43ddbaf3d7..fad88c424b452d7e854d29bc1ffa245b3ca1b146 100644 (file)
@@ -16,11 +16,16 @@ import os
 import time
 import re
 import argparse
+import datetime
 
 from numbers import Number
 
 # 3rd party modules
 
+import pytz
+
+from tzlocal import get_localzone
+
 from ldap3 import Server, Connection, ALL, DSA, IP_V4_PREFERRED, SAFE_SYNC
 from ldap3 import BASE, LEVEL, SUBTREE, DEREF_NEVER, DEREF_SEARCH, DEREF_BASE, DEREF_ALWAYS
 from ldap3 import ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES
@@ -40,7 +45,7 @@ from .config import LDAPMigrationConfiguration
 from .idict import CaseInsensitiveDict
 from .istringset import CaseInsensitiveStringSet
 
-__version__ = '0.6.10'
+__version__ = '0.7.0'
 
 LOG = logging.getLogger(__name__)
 CFG_BASENAME = 'ldap-migration.ini'
@@ -161,6 +166,8 @@ class LDAPMigrationApplication(BaseApplication):
     re_dn_split = re.compile(r'\s*,\s*')
     re_token_split = re.compile(r'^\s*([a-z0-9]+)\s*=\s*(\S(?:.*\S)?)\s*$', re.IGNORECASE)
 
+    tz = get_localzone()
+
     # -------------------------------------------------------------------------
     def __init__(
             self, appname=None, verbose=0, version=__version__, base_dir=None):
@@ -180,6 +187,7 @@ class LDAPMigrationApplication(BaseApplication):
         self.tmp_dir = None
         self.all_dns_file = None
         self.structural_dns_file = None
+        self.migrated_file = None
 
         self.limit = 0
 
@@ -202,6 +210,7 @@ class LDAPMigrationApplication(BaseApplication):
         self.tmp_dir = self.base_dir / 'tmp'
         self.all_dns_file = self.tmp_dir / 'all-dns.txt'
         self.structural_dns_file = self.tmp_dir / 'structural-dns.txt'
+        self.migrated_file = self.tmp_dir / 'migrated-entries.txt'
         self.initialized = True
 
     # -------------------------------------------------------------------------
@@ -982,14 +991,22 @@ class LDAPMigrationApplication(BaseApplication):
         print()
         LOG.info("Migrating all entries from source to target LDAP cluster.")
 
-        if not self.migrate_structural_entries():
-            return False
+        open_args = {
+            'encoding': 'utf-8',
+            'errors': 'surrogateescape',
+            'mode': 'w',
+        }
+
+        with self.migrated_file.open(**open_args) as fh:
+
+            if not self.migrate_structural_entries(fh):
+                return False
 
         print()
         return True
 
     # -------------------------------------------------------------------------
-    def migrate_structural_entries(self):
+    def migrate_structural_entries(self, fh):
 
         print()
         LOG.info("Migrating all structural entries from source to target LDAP cluster.")
@@ -999,7 +1016,7 @@ class LDAPMigrationApplication(BaseApplication):
         self.count_modified = 0
 
         try:
-            self._migrate_entries(self.struct_dns, is_root=True, with_acl=False)
+            self._migrate_entries(self.struct_dns, fh=fh, is_root=True, with_acl=False)
         except ReadLDAPItemError as e:
             msg = "Abort migration: " + str(e)
             LOG.error(msg)
@@ -1129,22 +1146,22 @@ class LDAPMigrationApplication(BaseApplication):
         return None
 
     # -------------------------------------------------------------------------
-    def _migrate_entries(self, cur_hash, is_root=False, with_acl=False):
+    def _migrate_entries(self, cur_hash, fh, is_root=False, with_acl=False):
 
         wait = self.config.wait_after_write
 
         if not is_root:
 
             src_dn = cur_hash['dn']
-            if self.migrate_entry(src_dn, with_acl=with_acl):
+            if self.migrate_entry(src_dn, fh=fh, with_acl=with_acl):
                 if wait:
                     time.sleep(wait)
 
         for key in cur_hash['childs'].keys():
-            self._migrate_entries(cur_hash['childs'][key], is_root=False, with_acl=with_acl)
+            self._migrate_entries(cur_hash['childs'][key], fh=fh, is_root=False, with_acl=with_acl)
 
     # -------------------------------------------------------------------------
-    def migrate_entry(self, src_dn, with_acl=False):
+    def migrate_entry(self, src_dn, fh, with_acl=False):
 
         tgt_dn = self.mangle_dn(src_dn)
         rev_dn = self.get_reverse_dn(tgt_dn)
@@ -1172,6 +1189,9 @@ class LDAPMigrationApplication(BaseApplication):
                 if not self.simulate:
                     self.target.modify(tgt_dn, changes)
                 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)
+                print(line, file=fh, flush=True)
                 return True
             else:
                 return False
@@ -1189,6 +1209,9 @@ class LDAPMigrationApplication(BaseApplication):
         if not self.simulate:
             self.target.add(tgt_dn, object_class=tgt_obj_classes, attributes=tgt_entry)
         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)
+        print(line, file=fh, flush=True)
         return True
 
     # -------------------------------------------------------------------------
index b8b7a5918664fccb52ab6ea7f2ba9be62791f104..e704b8d69c73b6044d6868c0ecbc6ceddf99c4c8 100644 (file)
@@ -2,5 +2,6 @@ git+https://git.pixelpark.com/python/python_fb_tools.git@master
 ansible
 ldap3
 PyYAML
+tzlocal
 flake8
 pylint