Beispiel #1
0
 def get_options(self):
     """
     Call get_options of the baseclass and add "exclude" options
     for each type of object being migrated.
     """
     for option in super(migrate_ds, self).get_options():
         yield option
     for ldap_obj_name in self.migrate_objects:
         ldap_obj = self.api.Object[ldap_obj_name]
         name = "exclude_%ss" % to_cli(ldap_obj_name)
         doc = self.exclude_doc % ldap_obj.object_name_plural
         yield Str("%s*" % name, cli_name=name, doc=doc, csv=True, default=tuple(), autofill=True)
Beispiel #2
0
 def _get_search_bases(self, options, ds_base_dn, migrate_order):
     search_bases = dict()
     for ldap_obj_name in migrate_order:
         container = options.get('%scontainer' % to_cli(ldap_obj_name))
         if container:
             # Don't append base dn if user already appended it in the container dn
             if container.endswith(ds_base_dn):
                 search_base = container
             else:
                 search_base = DN(container, ds_base_dn)
         else:
             search_base = ds_base_dn
         search_bases[ldap_obj_name] = search_base
     return search_bases
Beispiel #3
0
 def _get_search_bases(self, options, ds_base_dn, migrate_order):
     search_bases = dict()
     for ldap_obj_name in migrate_order:
         container = options.get('%scontainer' % to_cli(ldap_obj_name))
         if container:
             # Don't append base dn if user already appended it in the container dn
             if container.endswith(ds_base_dn):
                 search_base = container
             else:
                 search_base = DN(container, ds_base_dn)
         else:
             search_base = ds_base_dn
         search_bases[ldap_obj_name] = search_base
     return search_bases
Beispiel #4
0
 def get_options(self):
     """
     Call get_options of the baseclass and add "exclude" options
     for each type of object being migrated.
     """
     for option in super(migrate_ds, self).get_options():
         yield option
     for ldap_obj_name in self.migrate_objects:
         ldap_obj = self.api.Object[ldap_obj_name]
         name = 'exclude_%ss' % to_cli(ldap_obj_name)
         doc = self.exclude_doc % ldap_obj.object_name_plural
         yield Str(
             '%s*' % name, cli_name=name, doc=doc, default=tuple(),
             autofill=True
         )
Beispiel #5
0
    def normalize_options(self, options):
        """
        Convert all "exclude" option values to lower-case.

        Also, empty List parameters are converted to None, but the migration
        plugin doesn't like that - convert back to empty lists.
        """
        names = ['userobjectclass', 'groupobjectclass',
                 'userignoreobjectclass', 'userignoreattribute',
                 'groupignoreobjectclass', 'groupignoreattribute']
        names.extend('exclude_%ss' % to_cli(n) for n in self.migrate_objects)
        for name in names:
            if options[name]:
                options[name] = tuple(
                    v.lower() for v in options[name]
                )
            else:
                options[name] = tuple()
Beispiel #6
0
    def normalize_options(self, options):
        """
        Convert all "exclude" option values to lower-case.

        Also, empty List parameters are converted to None, but the migration
        plugin doesn't like that - convert back to empty lists.
        """
        names = [
            'userobjectclass', 'groupobjectclass', 'userignoreobjectclass',
            'userignoreattribute', 'groupignoreobjectclass',
            'groupignoreattribute'
        ]
        names.extend('exclude_%ss' % to_cli(n) for n in self.migrate_objects)
        for name in names:
            if options[name]:
                options[name] = tuple(v.lower() for v in options[name])
            else:
                options[name] = tuple()
Beispiel #7
0
    def migrate(self, ldap, config, ds_ldap, ds_base_dn, options):
        """
        Migrate objects from DS to LDAP.
        """
        assert isinstance(ds_base_dn, DN)
        migrated = {} # {'OBJ': ['PKEY1', 'PKEY2', ...], ...}
        failed = {} # {'OBJ': {'PKEY1': 'Failed 'cos blabla', ...}, ...}
        search_bases = self._get_search_bases(options, ds_base_dn, self.migrate_order)
        migration_start = datetime.datetime.now()

        scope = _supported_scopes[options.get('scope')]

        for ldap_obj_name in self.migrate_order:
            ldap_obj = self.api.Object[ldap_obj_name]

            template = self.migrate_objects[ldap_obj_name]['filter_template']
            oc_list = options[to_cli(self.migrate_objects[ldap_obj_name]['oc_option'])]
            search_filter = construct_filter(template, oc_list)

            exclude = options['exclude_%ss' % to_cli(ldap_obj_name)]
            context = dict(ds_ldap = ds_ldap)

            migrated[ldap_obj_name] = []
            failed[ldap_obj_name] = {}

            try:
                entries, truncated = ds_ldap.find_entries(
                    search_filter, ['*'], search_bases[ldap_obj_name],
                    scope,
                    time_limit=0, size_limit=-1
                )
            except errors.NotFound:
                if not options.get('continue',False):
                    raise errors.NotFound(
                        reason=_('%(container)s LDAP search did not return any result '
                                 '(search base: %(search_base)s, '
                                 'objectclass: %(objectclass)s)')
                                 % {'container': ldap_obj_name,
                                    'search_base': search_bases[ldap_obj_name],
                                    'objectclass': ', '.join(oc_list)}
                    )
                else:
                    truncated = False
                    entries = []
            if truncated:
                self.log.error(
                    '%s: %s' % (
                        ldap_obj.name, self.truncated_err_msg
                    )
                )

            blacklists = {}
            for blacklist in ('oc_blacklist', 'attr_blacklist'):
                blacklist_option = self.migrate_objects[ldap_obj_name][blacklist+'_option']
                if blacklist_option is not None:
                    blacklists[blacklist] = options.get(blacklist_option, tuple())
                else:
                    blacklists[blacklist] = tuple()

            # get default primary group for new users
            if 'def_group_dn' not in context and options.get('use_def_group'):
                def_group = config.get('ipadefaultprimarygroup')
                context['def_group_dn'] = api.Object.group.get_dn(def_group)
                try:
                    ldap.get_entry(context['def_group_dn'], ['gidnumber', 'cn'])
                except errors.NotFound:
                    error_msg = _('Default group for new users not found')
                    raise errors.NotFound(reason=error_msg)

            context['has_upg'] = ldap.has_upg()

            valid_gids = set()
            invalid_gids = set()
            migrate_cnt = 0
            context['migrate_cnt'] = 0
            for entry_attrs in entries:
                context['migrate_cnt'] = migrate_cnt
                s = datetime.datetime.now()

                ava = entry_attrs.dn[0][0]
                if ava.attr == ldap_obj.primary_key.name:
                    # In case if pkey attribute is in the migrated object DN
                    # and the original LDAP is multivalued, make sure that
                    # we pick the correct value (the unique one stored in DN)
                    pkey = ava.value.lower()
                else:
                    pkey = entry_attrs[ldap_obj.primary_key.name][0].lower()

                if pkey in exclude:
                    continue

                entry_attrs.dn = ldap_obj.get_dn(pkey)
                entry_attrs['objectclass'] = list(
                    set(
                        config.get(
                            ldap_obj.object_class_config, ldap_obj.object_class
                        ) + [o.lower() for o in entry_attrs['objectclass']]
                    )
                )
                entry_attrs[ldap_obj.primary_key.name][0] = entry_attrs[ldap_obj.primary_key.name][0].lower()

                callback = self.migrate_objects[ldap_obj_name]['pre_callback']
                if callable(callback):
                    try:
                        entry_attrs.dn = callback(
                            ldap, pkey, entry_attrs.dn, entry_attrs,
                            failed[ldap_obj_name], config, context,
                            schema=options['schema'],
                            search_bases=search_bases,
                            valid_gids=valid_gids,
                            invalid_gids=invalid_gids,
                            **blacklists
                        )
                        if not entry_attrs.dn:
                            continue
                    except errors.NotFound as e:
                        failed[ldap_obj_name][pkey] = unicode(e.reason)
                        continue

                try:
                    ldap.add_entry(entry_attrs)
                except errors.ExecutionError as e:
                    callback = self.migrate_objects[ldap_obj_name]['exc_callback']
                    if callable(callback):
                        try:
                            callback(
                                ldap, entry_attrs.dn, entry_attrs, e, options)
                        except errors.ExecutionError as e:
                            failed[ldap_obj_name][pkey] = unicode(e)
                            continue
                    else:
                        failed[ldap_obj_name][pkey] = unicode(e)
                        continue

                migrated[ldap_obj_name].append(pkey)

                callback = self.migrate_objects[ldap_obj_name]['post_callback']
                if callable(callback):
                    callback(
                        ldap, pkey, entry_attrs.dn, entry_attrs,
                        failed[ldap_obj_name], config, context)
                e = datetime.datetime.now()
                d = e - s
                total_dur = e - migration_start
                migrate_cnt += 1
                if migrate_cnt > 0 and migrate_cnt % 100 == 0:
                    api.log.info("%d %ss migrated. %s elapsed." % (migrate_cnt, ldap_obj_name, total_dur))
                api.log.debug("%d %ss migrated, duration: %s (total %s)" % (migrate_cnt, ldap_obj_name, d, total_dur))

        if 'def_group_dn' in context:
            _update_default_group(ldap, context, True)

        return (migrated, failed)
Beispiel #8
0
    def migrate(self, ldap, config, ds_ldap, ds_base_dn, options):
        """
        Migrate objects from DS to LDAP.
        """
        assert isinstance(ds_base_dn, DN)
        migrated = {}  # {'OBJ': ['PKEY1', 'PKEY2', ...], ...}
        failed = {}  # {'OBJ': {'PKEY1': 'Failed 'cos blabla', ...}, ...}
        search_bases = self._get_search_bases(options, ds_base_dn, self.migrate_order)
        migration_start = datetime.datetime.now()

        scope = _supported_scopes[options.get("scope")]

        for ldap_obj_name in self.migrate_order:
            ldap_obj = self.api.Object[ldap_obj_name]

            template = self.migrate_objects[ldap_obj_name]["filter_template"]
            oc_list = options[to_cli(self.migrate_objects[ldap_obj_name]["oc_option"])]
            search_filter = construct_filter(template, oc_list)

            exclude = options["exclude_%ss" % to_cli(ldap_obj_name)]
            context = dict(ds_ldap=ds_ldap)

            migrated[ldap_obj_name] = []
            failed[ldap_obj_name] = {}

            try:
                entries, truncated = ds_ldap.find_entries(
                    search_filter,
                    ["*"],
                    search_bases[ldap_obj_name],
                    scope,
                    time_limit=0,
                    size_limit=-1,
                    search_refs=True,  # migrated DS may contain search references
                )
            except errors.NotFound:
                if not options.get("continue", False):
                    raise errors.NotFound(
                        reason=_(
                            "%(container)s LDAP search did not return any result "
                            "(search base: %(search_base)s, "
                            "objectclass: %(objectclass)s)"
                        )
                        % {
                            "container": ldap_obj_name,
                            "search_base": search_bases[ldap_obj_name],
                            "objectclass": ", ".join(oc_list),
                        }
                    )
                else:
                    truncated = False
                    entries = []
            if truncated:
                self.log.error("%s: %s" % (ldap_obj.name, self.truncated_err_msg))

            blacklists = {}
            for blacklist in ("oc_blacklist", "attr_blacklist"):
                blacklist_option = self.migrate_objects[ldap_obj_name][blacklist + "_option"]
                if blacklist_option is not None:
                    blacklists[blacklist] = options.get(blacklist_option, tuple())
                else:
                    blacklists[blacklist] = tuple()

            # get default primary group for new users
            if "def_group_dn" not in context and options.get("use_def_group"):
                def_group = config.get("ipadefaultprimarygroup")
                context["def_group_dn"] = api.Object.group.get_dn(def_group)
                try:
                    ldap.get_entry(context["def_group_dn"], ["gidnumber", "cn"])
                except errors.NotFound:
                    error_msg = _("Default group for new users not found")
                    raise errors.NotFound(reason=error_msg)

            context["has_upg"] = ldap.has_upg()

            valid_gids = set()
            invalid_gids = set()
            migrate_cnt = 0
            context["migrate_cnt"] = 0
            for entry_attrs in entries:
                context["migrate_cnt"] = migrate_cnt
                s = datetime.datetime.now()

                ava = entry_attrs.dn[0][0]
                if ava.attr == ldap_obj.primary_key.name:
                    # In case if pkey attribute is in the migrated object DN
                    # and the original LDAP is multivalued, make sure that
                    # we pick the correct value (the unique one stored in DN)
                    pkey = ava.value.lower()
                else:
                    pkey = entry_attrs[ldap_obj.primary_key.name][0].lower()

                if pkey in exclude:
                    continue

                entry_attrs.dn = ldap_obj.get_dn(pkey)
                entry_attrs["objectclass"] = list(
                    set(
                        config.get(ldap_obj.object_class_config, ldap_obj.object_class)
                        + [o.lower() for o in entry_attrs["objectclass"]]
                    )
                )
                entry_attrs[ldap_obj.primary_key.name][0] = entry_attrs[ldap_obj.primary_key.name][0].lower()

                callback = self.migrate_objects[ldap_obj_name]["pre_callback"]
                if callable(callback):
                    try:
                        entry_attrs.dn = callback(
                            ldap,
                            pkey,
                            entry_attrs.dn,
                            entry_attrs,
                            failed[ldap_obj_name],
                            config,
                            context,
                            schema=options["schema"],
                            search_bases=search_bases,
                            valid_gids=valid_gids,
                            invalid_gids=invalid_gids,
                            **blacklists
                        )
                        if not entry_attrs.dn:
                            continue
                    except errors.NotFound, e:
                        failed[ldap_obj_name][pkey] = unicode(e.reason)
                        continue

                try:
                    ldap.add_entry(entry_attrs)
                except errors.ExecutionError, e:
                    callback = self.migrate_objects[ldap_obj_name]["exc_callback"]
                    if callable(callback):
                        try:
                            callback(ldap, entry_attrs.dn, entry_attrs, e, options)
                        except errors.ExecutionError, e:
                            failed[ldap_obj_name][pkey] = unicode(e)
                            continue
                    else:
                        failed[ldap_obj_name][pkey] = unicode(e)
                        continue
Beispiel #9
0
    def migrate(self, ldap, config, ds_ldap, ds_base_dn, options):
        """
        Migrate objects from DS to LDAP.
        """
        assert isinstance(ds_base_dn, DN)
        migrated = {}  # {'OBJ': ['PKEY1', 'PKEY2', ...], ...}
        failed = {}  # {'OBJ': {'PKEY1': 'Failed 'cos blabla', ...}, ...}
        search_bases = self._get_search_bases(options, ds_base_dn,
                                              self.migrate_order)
        migration_start = datetime.datetime.now()

        scope = _supported_scopes[options.get('scope')]

        for ldap_obj_name in self.migrate_order:
            ldap_obj = self.api.Object[ldap_obj_name]

            template = self.migrate_objects[ldap_obj_name]['filter_template']
            oc_list = options[to_cli(
                self.migrate_objects[ldap_obj_name]['oc_option'])]
            search_filter = construct_filter(template, oc_list)

            exclude = options['exclude_%ss' % to_cli(ldap_obj_name)]
            context = dict(ds_ldap=ds_ldap)

            migrated[ldap_obj_name] = []
            failed[ldap_obj_name] = {}

            try:
                entries, truncated = ds_ldap.find_entries(
                    search_filter, ['*'],
                    search_bases[ldap_obj_name],
                    scope,
                    time_limit=0,
                    size_limit=-1)
            except errors.NotFound:
                if not options.get('continue', False):
                    raise errors.NotFound(
                        reason=
                        _('%(container)s LDAP search did not return any result '
                          '(search base: %(search_base)s, '
                          'objectclass: %(objectclass)s)') % {
                              'container': ldap_obj_name,
                              'search_base': search_bases[ldap_obj_name],
                              'objectclass': ', '.join(oc_list)
                          })
                else:
                    truncated = False
                    entries = []
            if truncated:
                logger.error('%s: %s', ldap_obj.name, self.truncated_err_msg)

            blocklists = {}
            for blocklist in ('oc_blocklist', 'attr_blocklist'):
                blocklist_option = (
                    self.migrate_objects[ldap_obj_name][blocklist + '_option'])
                if blocklist_option is not None:
                    blocklists[blocklist] = options.get(
                        blocklist_option, tuple())
                else:
                    blocklists[blocklist] = tuple()

            # get default primary group for new users
            if 'def_group_dn' not in context and options.get('use_def_group'):
                def_group = config.get('ipadefaultprimarygroup')
                context['def_group_dn'] = api.Object.group.get_dn(def_group)
                try:
                    ldap.get_entry(context['def_group_dn'],
                                   ['gidnumber', 'cn'])
                except errors.NotFound:
                    error_msg = _('Default group for new users not found')
                    raise errors.NotFound(reason=error_msg)

            context['has_upg'] = ldap.has_upg()

            valid_gids = set()
            invalid_gids = set()
            migrate_cnt = 0
            context['migrate_cnt'] = 0
            for entry_attrs in entries:
                context['migrate_cnt'] = migrate_cnt
                s = datetime.datetime.now()

                ava = entry_attrs.dn[0][0]
                if ava.attr == ldap_obj.primary_key.name:
                    # In case if pkey attribute is in the migrated object DN
                    # and the original LDAP is multivalued, make sure that
                    # we pick the correct value (the unique one stored in DN)
                    pkey = ava.value.lower()
                else:
                    pkey = entry_attrs[ldap_obj.primary_key.name][0].lower()

                if pkey in exclude:
                    continue

                entry_attrs.dn = ldap_obj.get_dn(pkey)
                entry_attrs['objectclass'] = list(
                    set(
                        config.get(ldap_obj.object_class_config,
                                   ldap_obj.object_class) +
                        [o.lower() for o in entry_attrs['objectclass']]))
                entry_attrs[ldap_obj.primary_key.name][0] = entry_attrs[
                    ldap_obj.primary_key.name][0].lower()

                callback = self.migrate_objects[ldap_obj_name]['pre_callback']
                if callable(callback):
                    try:
                        entry_attrs.dn = callback(ldap,
                                                  pkey,
                                                  entry_attrs.dn,
                                                  entry_attrs,
                                                  failed[ldap_obj_name],
                                                  config,
                                                  context,
                                                  schema=options['schema'],
                                                  search_bases=search_bases,
                                                  valid_gids=valid_gids,
                                                  invalid_gids=invalid_gids,
                                                  **blocklists)
                        if not entry_attrs.dn:
                            continue
                    except errors.NotFound as e:
                        failed[ldap_obj_name][pkey] = unicode(e.reason)
                        continue

                try:
                    ldap.add_entry(entry_attrs)
                except errors.ExecutionError as e:
                    callback = self.migrate_objects[ldap_obj_name][
                        'exc_callback']
                    if callable(callback):
                        try:
                            callback(ldap, entry_attrs.dn, entry_attrs, e,
                                     options)
                        except errors.ExecutionError as e2:
                            failed[ldap_obj_name][pkey] = unicode(e2)
                            continue
                    else:
                        failed[ldap_obj_name][pkey] = unicode(e)
                        continue

                migrated[ldap_obj_name].append(pkey)

                callback = self.migrate_objects[ldap_obj_name]['post_callback']
                if callable(callback):
                    callback(ldap, pkey, entry_attrs.dn, entry_attrs,
                             failed[ldap_obj_name], config, context)
                e = datetime.datetime.now()
                d = e - s
                total_dur = e - migration_start
                migrate_cnt += 1
                if migrate_cnt > 0 and migrate_cnt % 100 == 0:
                    logger.info("%d %ss migrated. %s elapsed.", migrate_cnt,
                                ldap_obj_name, total_dur)
                logger.debug("%d %ss migrated, duration: %s (total %s)",
                             migrate_cnt, ldap_obj_name, d, total_dur)

        if 'def_group_dn' in context:
            _update_default_group(ldap, context, True)

        return (migrated, failed)
Beispiel #10
0
    def migrate(self, ldap, config, ds_ldap, ds_base_dn, options):
        """
        Migrate objects from DS to LDAP.
        """
        assert isinstance(ds_base_dn, DN)
        migrated = {}  # {'OBJ': ['PKEY1', 'PKEY2', ...], ...}
        failed = {}  # {'OBJ': {'PKEY1': 'Failed 'cos blabla', ...}, ...}
        search_bases = self._get_search_bases(options, ds_base_dn,
                                              self.migrate_order)
        migration_start = datetime.datetime.now()
        for ldap_obj_name in self.migrate_order:
            ldap_obj = self.api.Object[ldap_obj_name]

            template = self.migrate_objects[ldap_obj_name]['filter_template']
            oc_list = options[to_cli(
                self.migrate_objects[ldap_obj_name]['oc_option'])]
            search_filter = construct_filter(template, oc_list)

            exclude = options['exclude_%ss' % to_cli(ldap_obj_name)]
            context = dict(ds_ldap=ds_ldap)

            migrated[ldap_obj_name] = []
            failed[ldap_obj_name] = {}

            try:
                (entries, truncated) = ds_ldap.find_entries(
                    search_filter,
                    ['*'],
                    search_bases[ldap_obj_name],
                    _ldap.SCOPE_ONELEVEL,
                    time_limit=0,
                    size_limit=-1,
                    search_refs=True  # migrated DS may contain search references
                )
            except errors.NotFound:
                if not options.get('continue', False):
                    raise errors.NotFound(
                        reason=
                        _('%(container)s LDAP search did not return any result '
                          '(search base: %(search_base)s, '
                          'objectclass: %(objectclass)s)') % {
                              'container': ldap_obj_name,
                              'search_base': search_bases[ldap_obj_name],
                              'objectclass': ', '.join(oc_list)
                          })
                else:
                    truncated = False
                    entries = []
            if truncated:
                self.log.error('%s: %s' %
                               (ldap_obj.name, self.truncated_err_msg))

            blacklists = {}
            for blacklist in ('oc_blacklist', 'attr_blacklist'):
                blacklist_option = self.migrate_objects[ldap_obj_name][
                    blacklist + '_option']
                if blacklist_option is not None:
                    blacklists[blacklist] = options.get(
                        blacklist_option, tuple())
                else:
                    blacklists[blacklist] = tuple()

            # get default primary group for new users
            if 'def_group_dn' not in context:
                def_group = config.get('ipadefaultprimarygroup')
                context['def_group_dn'] = api.Object.group.get_dn(def_group)
                try:
                    (g_dn, g_attrs) = ldap.get_entry(context['def_group_dn'],
                                                     ['gidnumber', 'cn'])
                except errors.NotFound:
                    error_msg = _('Default group for new users not found')
                    raise errors.NotFound(reason=error_msg)
                if 'gidnumber' in g_attrs:
                    context['def_group_gid'] = g_attrs['gidnumber'][0]

            context['has_upg'] = ldap.has_upg()

            valid_gids = []
            invalid_gids = []
            context['migrate_cnt'] = 0
            migrate_cnt = 0
            for (dn, entry_attrs) in entries:
                context['migrate_cnt'] = migrate_cnt
                s = datetime.datetime.now()
                if dn is None:  # LDAP search reference
                    failed[ldap_obj_name][entry_attrs[0]] = unicode(
                        _ref_err_msg)
                    continue

                try:
                    dn = DN(dn)
                except ValueError:
                    failed[ldap_obj_name][dn] = unicode(_dn_err_msg)
                    continue

                ava = dn[0][0]
                if ava.attr == ldap_obj.primary_key.name:
                    # In case if pkey attribute is in the migrated object DN
                    # and the original LDAP is multivalued, make sure that
                    # we pick the correct value (the unique one stored in DN)
                    pkey = ava.value.lower()
                else:
                    pkey = entry_attrs[ldap_obj.primary_key.name][0].lower()

                if pkey in exclude:
                    continue

                dn = ldap_obj.get_dn(pkey)
                assert isinstance(dn, DN)
                entry_attrs['objectclass'] = list(
                    set(
                        config.get(ldap_obj.object_class_config,
                                   ldap_obj.object_class) +
                        [o.lower() for o in entry_attrs['objectclass']]))
                entry_attrs[ldap_obj.primary_key.name][0] = entry_attrs[
                    ldap_obj.primary_key.name][0].lower()

                callback = self.migrate_objects[ldap_obj_name]['pre_callback']
                if callable(callback):
                    try:
                        dn = callback(ldap,
                                      pkey,
                                      dn,
                                      entry_attrs,
                                      failed[ldap_obj_name],
                                      config,
                                      context,
                                      schema=options['schema'],
                                      search_bases=search_bases,
                                      valid_gids=valid_gids,
                                      invalid_gids=invalid_gids,
                                      **blacklists)
                        assert isinstance(dn, DN)
                        if not dn:
                            continue
                    except errors.NotFound, e:
                        failed[ldap_obj_name][pkey] = unicode(e.reason)
                        continue

                try:
                    ldap.add_entry(dn, entry_attrs)
                except errors.ExecutionError, e:
                    callback = self.migrate_objects[ldap_obj_name][
                        'exc_callback']
                    if callable(callback):
                        try:
                            callback(ldap, dn, entry_attrs, e, options)
                        except errors.ExecutionError, e:
                            failed[ldap_obj_name][pkey] = unicode(e)
                            continue
                    else:
                        failed[ldap_obj_name][pkey] = unicode(e)
                        continue
Beispiel #11
0
    def migrate(self, ldap, config, ds_ldap, ds_base_dn, options):
        """
        Migrate objects from DS to LDAP.
        """
        assert isinstance(ds_base_dn, DN)
        migrated = {} # {'OBJ': ['PKEY1', 'PKEY2', ...], ...}
        failed = {} # {'OBJ': {'PKEY1': 'Failed 'cos blabla', ...}, ...}
        search_bases = self._get_search_bases(options, ds_base_dn, self.migrate_order)
        migration_start = datetime.datetime.now()
        for ldap_obj_name in self.migrate_order:
            ldap_obj = self.api.Object[ldap_obj_name]

            template = self.migrate_objects[ldap_obj_name]['filter_template']
            oc_list = options[to_cli(self.migrate_objects[ldap_obj_name]['oc_option'])]
            search_filter = construct_filter(template, oc_list)

            exclude = options['exclude_%ss' % to_cli(ldap_obj_name)]
            context = dict(ds_ldap = ds_ldap)

            migrated[ldap_obj_name] = []
            failed[ldap_obj_name] = {}

            try:
                (entries, truncated) = ds_ldap.find_entries(
                    search_filter, ['*'], search_bases[ldap_obj_name],
                    _ldap.SCOPE_ONELEVEL,
                    time_limit=0, size_limit=-1,
                    search_refs=True    # migrated DS may contain search references
                )
            except errors.NotFound:
                if not options.get('continue',False):
                    raise errors.NotFound(
                        reason=_('%(container)s LDAP search did not return any result '
                                 '(search base: %(search_base)s, '
                                 'objectclass: %(objectclass)s)')
                                 % {'container': ldap_obj_name,
                                    'search_base': search_bases[ldap_obj_name],
                                    'objectclass': ', '.join(oc_list)}
                    )
                else:
                    truncated = False
                    entries = []
            if truncated:
                self.log.error(
                    '%s: %s' % (
                        ldap_obj.name, self.truncated_err_msg
                    )
                )

            blacklists = {}
            for blacklist in ('oc_blacklist', 'attr_blacklist'):
                blacklist_option = self.migrate_objects[ldap_obj_name][blacklist+'_option']
                if blacklist_option is not None:
                    blacklists[blacklist] = options.get(blacklist_option, tuple())
                else:
                    blacklists[blacklist] = tuple()

            # get default primary group for new users
            if 'def_group_dn' not in context:
                def_group = config.get('ipadefaultprimarygroup')
                context['def_group_dn'] = api.Object.group.get_dn(def_group)
                try:
                    (g_dn, g_attrs) = ldap.get_entry(context['def_group_dn'], ['gidnumber', 'cn'])
                except errors.NotFound:
                    error_msg = _('Default group for new users not found')
                    raise errors.NotFound(reason=error_msg)
                if 'gidnumber' in g_attrs:
                    context['def_group_gid'] = g_attrs['gidnumber'][0]

            context['has_upg'] = ldap.has_upg()

            valid_gids = []
            invalid_gids = []
            context['migrate_cnt'] = 0
            migrate_cnt = 0
            for (dn, entry_attrs) in entries:
                context['migrate_cnt'] = migrate_cnt
                s = datetime.datetime.now()
                if dn is None:  # LDAP search reference
                    failed[ldap_obj_name][entry_attrs[0]] = unicode(_ref_err_msg)
                    continue

                try:
                    dn = DN(dn)
                except ValueError:
                    failed[ldap_obj_name][dn] = unicode(_dn_err_msg)
                    continue

                ava = dn[0][0]
                if ava.attr == ldap_obj.primary_key.name:
                    # In case if pkey attribute is in the migrated object DN
                    # and the original LDAP is multivalued, make sure that
                    # we pick the correct value (the unique one stored in DN)
                    pkey = ava.value.lower()
                else:
                    pkey = entry_attrs[ldap_obj.primary_key.name][0].lower()

                if pkey in exclude:
                    continue

                dn = ldap_obj.get_dn(pkey)
                assert isinstance(dn, DN)
                entry_attrs['objectclass'] = list(
                    set(
                        config.get(
                            ldap_obj.object_class_config, ldap_obj.object_class
                        ) + [o.lower() for o in entry_attrs['objectclass']]
                    )
                )
                entry_attrs[ldap_obj.primary_key.name][0] = entry_attrs[ldap_obj.primary_key.name][0].lower()

                callback = self.migrate_objects[ldap_obj_name]['pre_callback']
                if callable(callback):
                    try:
                        dn = callback(
                            ldap, pkey, dn, entry_attrs, failed[ldap_obj_name],
                            config, context, schema = options['schema'],
                            search_bases = search_bases,
                            valid_gids = valid_gids,
                            invalid_gids = invalid_gids,
                            **blacklists
                        )
                        assert isinstance(dn, DN)
                        if not dn:
                            continue
                    except errors.NotFound, e:
                        failed[ldap_obj_name][pkey] = unicode(e.reason)
                        continue

                try:
                    ldap.add_entry(dn, entry_attrs)
                except errors.ExecutionError, e:
                    callback = self.migrate_objects[ldap_obj_name]['exc_callback']
                    if callable(callback):
                        try:
                            callback(ldap, dn, entry_attrs, e, options)
                        except errors.ExecutionError, e:
                            failed[ldap_obj_name][pkey] = unicode(e)
                            continue
                    else:
                        failed[ldap_obj_name][pkey] = unicode(e)
                        continue