from .config import LDAPMigrationConfiguration
-__version__ = '0.9.12'
+__version__ = '0.10.0'
LOG = logging.getLogger(__name__)
CFG_BASENAME = 'ldap-migration.ini'
# =============================================================================
-class WriteLDAPItemError(CommonLDAPMigrationError):
+class FatalLDAPMigrationError(CommonLDAPMigrationError):
+ """Fatal errors leading to interrupt the migration process."""
+ pass
+
+
+# =============================================================================
+class WriteLDAPItemError(FatalLDAPMigrationError):
"""Error class in case, a LDAP item could not be written."""
pass
self.struct_entries = []
self.all_entries = []
self.group_entries = CIDict()
+ self.migrated_group_entries = CIDict()
self.ignored_entries = CIStringSet()
self.limit = 0
"""
res = super(LDAPMigrationApplication, self).as_dict(short=short)
- res['object_classes'] = self.object_classes.as_dict(short=short)
- res['attribute_types'] = self.attribute_types.as_dict(short=short)
+ # res['object_classes'] = self.object_classes.as_dict(short=short)
+ # res['attribute_types'] = self.attribute_types.as_dict(short=short)
res['cfg_dir'] = self.cfg_dir
res['cfg_file'] = self.cfg_file
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['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['migrated_group_entries'] = self.migrated_group_entries.as_dict(short=short)
res['integer_attribute_types'] = self.integer_attribute_types.as_list()
res['pure_binary_attr_types'] = self.pure_binary_attr_types.as_list()
res['dn_attr_types'] = self.dn_attr_types.as_list()
res['boolean_attr_types'] = self.boolean_attr_types.as_list()
+ res['ignored_entries'] = self.ignored_entries.as_list()
return res
self._migrate_entries(
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)
+ except CommonLDAPMigrationError as e:
+ msg = "Abort migration by {c}: {e}".format(c=e.__class__.__name__, e=e)
LOG.error(msg)
return False
src_dn, fh=fh, force=False, with_acl=False, migrate_if_group=False):
if wait:
time.sleep(wait)
- except WriteLDAPItemError as e:
- msg = "Abort migration: " + str(e)
+ except FatalLDAPMigrationError as e:
+ msg = "Abort migration by {c}: {e}".format(c=e.__class__.__name__, e=e)
LOG.error(msg)
return False
except ReadLDAPItemError as e:
continue
print()
- 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)
+ if self.verbose > 1:
+ 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)
LOG.info("Performed all entries.")
time.sleep(3)
if is_group:
self.group_entries[tgt_dn] = {
'migrated': False,
+ 'src_dn': src_dn,
'object_classes': object_classes,
}
LOG.debug("Entry {e!r} is a group entry: {c}".format(
LOG.debug(msg)
msg = "UnicodeDecodeError on generating changes for source DN {s!r}: {e}".format(
s=src_dn, e=e)
- raise WriteLDAPItemError(msg)
+ raise FatalLDAPMigrationError(msg)
if changes:
if self.verbose:
LOG.info("Updating target entry {!r} ...".format(tgt_dn))
return False
+ # -------------------------------------------------------------------------
+ def migrate_group_entries(self):
+
+ print()
+ LOG.info("Next lap - migration af all group entries ...")
+
+ lap = 0
+ while len(self.group_entries):
+
+ lap += 1
+ print()
+ LOG.info("Lap {} on migrating of group entries.".format(lap))
+ migrated_dns = CIStringSet()
+ count_groups_before = len(self.group_entries)
+
+ for tgt_dn in self.group_entries:
+
+ if self.migrate_group_entry(tgt_dn):
+
+ src_dn = self.group_entries[tgt_dn]['src_dn']
+ migrated_dns.add(tgt_dn)
+ self.group_entries[tgt_dn]['migrated'] = True
+ self.migrated_group_entries[tgt_dn] = {
+ 'migrated_at': datetime.datetime.now(),
+ 'src_dn': src_dn,
+ 'object_classes': self.group_entries[tgt_dn]['object_classes'],
+ }
+ LOG.info("Group entry {src!} -> {tgt!r} successful migrated.".format(
+ src=src_dn, tgt=tgt_dn))
+ else:
+ LOG.info((
+ "Group entry {src!} -> {tgt!r} could not migrated "
+ "in lap {lap}.").format(src=src_dn, tgt=tgt_dn, lap=lap))
+
+ for tgt_dn in migrated_dns:
+ del self.group_entries[tgt_dn]
+ migrated_dns = None
+
+ count_groups_after = len(self.group_entries)
+ if (count_groups_after > 0 and
+ count_groups_aftercount_groups_after == count_groups_before):
+
+ msg = (
+ "No change in the list of group items to migrate, there "
+ "are {} group entries left.").format(count_groups_after)
+ raise FatalLDAPMigrationError(msg)
+
+ print()
+ LOG.info("Performed all group entries.")
+ time.sleep(3)
+ return True
+
+ # -------------------------------------------------------------------------
+ def migrate_group_entry(self, tgt_dn):
+
+ src_dn = self.group_entries[tgt_dn]['src_dn']
+ object_classes = self.group_entries[tgt_dn]['object_classes']
+
+ msg = "Trying to migrate group entry {src!} -> {tgt!r} ...".format(src=src_dn, tgt=tgt_dn)
+ LOG.debug(msg)
+
+ return True
+
# -------------------------------------------------------------------------
def detailled_summary(self):
self.get_all_dns()
self.get_structural_dns()
self.migrate_entries()
+ self.migrate_group_entries()
self.detailled_summary()
finally: