How to test:
1) Create a custom DS instance with for example 60radius.ldif schema
present (as in the original report in ticket #1266)
2) Populate DS with users/groups with custom unsupported object
class/attribute
3) Try to migrate these users and groups to IPAv2. Only the enhanced
migrate-ds command should be successful:

# ipa migrate-ds ldap://vm-102.idm.lab.bos.redhat.com:389
--schema=RFC2307 --user-objectclass=posixAccount
--group-objectclass=posixgroup --user-container='ou=People'
--group-container='cn=Accounting Managers,ou=Groups'
--user-ignore-objectclass=radiusprofile,radiusclientprofile
--user-ignore-attribute=radiusclientsecret,radiusclientipaddress

---
When user migrates users/groups from an old DS instance, the
migration may fail on unsupported object classes and/or
relevant LDAP object attributes.

This patch implements a support for object class and attribute
ignore lists that can be used to suppress these migration issues.

Additionally, a redundant "dev/null" file is removed from git repo
(originally added in 26b0e8fc9809a4cd9f2f9a2281f0894e2e0f8db2).

https://fedorahosted.org/freeipa/ticket/1266

>From faf0a724880309c04ea1bc0d926e326ac46b1563 Mon Sep 17 00:00:00 2001
From: Martin Kosek <mko...@redhat.com>
Date: Fri, 3 Jun 2011 14:21:43 +0200
Subject: [PATCH] Add ignore lists to migrate-ds command

When user migrates users/groups from an old DS instance, the
migration may fail on unsupported object classes and/or
relevant LDAP object attributes.

This patch implements a support for object class and attribute
ignore lists that can be used to suppress these migration issues.

Additionally, a redundant "dev/null" file is removed from git repo
(originally added in 26b0e8fc9809a4cd9f2f9a2281f0894e2e0f8db2).

https://fedorahosted.org/freeipa/ticket/1266
---
 API.txt                     |    6 +++-
 VERSION                     |    2 +-
 ipalib/plugins/migration.py |   66 +++++++++++++++++++++++++++++++++++++++---
 3 files changed, 67 insertions(+), 7 deletions(-)
 delete mode 100644 dev/null

diff --git a/API.txt b/API.txt
index 67245c568b8421be54b3f2ad00afa9d749486db4..6e1ce2936fa390697e1cec928517cdf25a2e96d4 100644
--- a/API.txt
+++ b/API.txt
@@ -1511,7 +1511,7 @@ output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), 'User-friendly
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
 output: Output('value', <type 'unicode'>, "The primary_key value of the entry, e.g. 'jdoe' for a user")
 command: migrate_ds
-args: 2,9,3
+args: 2,13,3
 arg: Str('ldapuri', validate_ldapuri, cli_name='ldap_uri', label=Gettext('LDAP URI', domain='ipa', localedir=None))
 arg: Password('bindpw', cli_name='password', label=Gettext('Password', domain='ipa', localedir=None))
 option: Str('binddn?', autofill=True, cli_name='bind_dn', default=u'cn=directory manager', label=Gettext('Bind DN', domain='ipa', localedir=None))
@@ -1519,6 +1519,10 @@ option: Str('usercontainer?', autofill=True, cli_name='user_container', default=
 option: Str('groupcontainer?', autofill=True, cli_name='group_container', default=u'ou=groups', label=Gettext('Group container', domain='ipa', localedir=None))
 option: List('userobjectclass?', autofill=True, cli_name='user_objectclass', default=(u'person',), label=Gettext('User object class', domain='ipa', localedir=None), multivalue=True)
 option: List('groupobjectclass?', autofill=True, cli_name='group_objectclass', default=(u'groupOfUniqueNames', u'groupOfNames'), label=Gettext('Group object class', domain='ipa', localedir=None), multivalue=True)
+option: List('userignoreobjectclass?', autofill=True, cli_name='user_ignore_objectclass', default=(), label=Gettext('Ignore user object class', domain='ipa', localedir=None), multivalue=True)
+option: List('userignoreattribute?', autofill=True, cli_name='user_ignore_attribute', default=(), label=Gettext('Ignore user attribute', domain='ipa', localedir=None), multivalue=True)
+option: List('groupignoreobjectclass?', autofill=True, cli_name='group_ignore_objectclass', default=(), label=Gettext('Ignore group object class', domain='ipa', localedir=None), multivalue=True)
+option: List('groupignoreattribute?', autofill=True, cli_name='group_ignore_attribute', default=(), label=Gettext('Ignore group attribute', domain='ipa', localedir=None), multivalue=True)
 option: StrEnum('schema?', autofill=True, cli_name='schema', default=u'RFC2307bis', label=Gettext('LDAP schema', domain='ipa', localedir=None), values=(u'RFC2307bis', u'RFC2307'))
 option: Flag('continue?', autofill=True, default=False)
 option: List('exclude_groups?', autofill=True, cli_name='exclude_groups', default=(), multivalue=True)
diff --git a/VERSION b/VERSION
index 44de4f5f575f96b6ce4346000ec7627afa24d354..762c7e53a058721cb0df21916c0f77119c3015d9 100644
--- a/VERSION
+++ b/VERSION
@@ -79,4 +79,4 @@ IPA_DATA_VERSION=20100614120000
 #                                                      #
 ########################################################
 IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=2
+IPA_API_VERSION_MINOR=3
diff --git a/dev/null b/dev/null
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/ipalib/plugins/migration.py b/ipalib/plugins/migration.py
index ea591d31ee5af2e167866dcc31aa59d0e95caa94..4b636b1a3f3361c15ac4a7231c2458c058b3bef4 100644
--- a/ipalib/plugins/migration.py
+++ b/ipalib/plugins/migration.py
@@ -70,8 +70,6 @@ if api.env.in_server and api.env.context in ['lite', 'server']:
     except StandardError, e:
         raise e
 from ipalib import _
-from ipalib.text import Gettext # FIXME: remove once the other Gettext FIXME is removed
-
 
 # USER MIGRATION CALLBACKS AND VARS
 
@@ -83,6 +81,7 @@ _supported_schemas = (u'RFC2307bis', u'RFC2307')
 
 def _pre_migrate_user(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwargs):
     attr_blacklist = ['krbprincipalkey','memberofindirect','memberindirect']
+    attr_blacklist.extend(kwargs.get('attr_blacklist', []))
 
     # get default primary group for new users
     if 'def_group_dn' not in ctx:
@@ -109,6 +108,14 @@ def _pre_migrate_user(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwargs
         if attr in attr_blacklist:
             del entry_attrs[attr]
 
+    # do not migrate all object classes
+    if 'objectclass' in entry_attrs:
+        for object_class in kwargs.get('oc_blacklist', []):
+            try:
+                entry_attrs['objectclass'].remove(object_class)
+            except ValueError:  # object class not present
+                pass
+
     # generate a principal name and check if it isn't already taken
     principal = u'%s@%s' % (pkey, api.env.realm)
     try:
@@ -185,6 +192,7 @@ def _pre_migrate_group(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwarg
         entry_attrs['member'] = new_members
 
     attr_blacklist = ['memberofindirect','memberindirect']
+    attr_blacklist.extend(kwargs.get('attr_blacklist', []))
 
     schema = kwargs.get('schema', None)
     entry_attrs['ipauniqueid'] = 'autogenerate'
@@ -205,6 +213,14 @@ def _pre_migrate_group(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwarg
         if attr in attr_blacklist:
             del entry_attrs[attr]
 
+    # do not migrate all object classes
+    if 'objectclass' in entry_attrs:
+        for object_class in kwargs.get('oc_blacklist', []):
+            try:
+                entry_attrs['objectclass'].remove(object_class)
+            except ValueError:  # object class not present
+                pass
+
     return dn
 
 
@@ -248,12 +264,16 @@ class migrate_ds(Command):
         'user': {
             'filter_template' : '(&(|%s)(uid=*))',
             'oc_option' : 'userobjectclass',
+            'oc_blacklist_option' : 'userignoreobjectclass',
+            'attr_blacklist_option' : 'userignoreattribute',
             'pre_callback' : _pre_migrate_user,
             'post_callback' : _post_migrate_user
         },
         'group': {
             'filter_template' : '(&(|%s)(cn=*))',
             'oc_option' : 'groupobjectclass',
+            'oc_blacklist_option' : 'groupignoreobjectclass',
+            'attr_blacklist_option' : 'groupignoreattribute',
             'pre_callback' : _pre_migrate_group,
             'post_callback' : None
         },
@@ -308,6 +328,34 @@ class migrate_ds(Command):
             default=(u'groupOfUniqueNames', u'groupOfNames'),
             autofill=True,
         ),
+        List('userignoreobjectclass?',
+            cli_name='user_ignore_objectclass',
+            label=_('Ignore user object class'),
+            doc=_('Comma-separated list of objectclasses to be ignored for user entries in DS'),
+            default=tuple(),
+            autofill=True,
+        ),
+        List('userignoreattribute?',
+            cli_name='user_ignore_attribute',
+            label=_('Ignore user attribute'),
+            doc=_('Comma-separated list of attributes to be ignored for user entries in DS'),
+            default=tuple(),
+            autofill=True,
+        ),
+        List('groupignoreobjectclass?',
+            cli_name='group_ignore_objectclass',
+            label=_('Ignore group object class'),
+            doc=_('Comma-separated list of objectclasses to be ignored for group entries in DS'),
+            default=tuple(),
+            autofill=True,
+        ),
+        List('groupignoreattribute?',
+            cli_name='group_ignore_attribute',
+            label=_('Ignore group attribute'),
+            doc=_('Comma-separated list of attributes to be ignored for group entries in DS'),
+            default=tuple(),
+            autofill=True,
+        ),
         StrEnum('schema?',
             cli_name='schema',
             label=_('LDAP schema'),
@@ -364,8 +412,7 @@ can use their Kerberos accounts.''')
         for ldap_obj_name in self.migrate_objects:
             ldap_obj = self.api.Object[ldap_obj_name]
             name = 'exclude_%ss' % to_cli(ldap_obj_name)
-            # FIXME: can't substitute strings static Gettext instance
-            doc = Gettext(self.exclude_doc % ldap_obj.object_name_plural)
+            doc = self.exclude_doc % ldap_obj.object_name_plural
             yield List(
                 '%s?' % name, cli_name=name, doc=doc, default=tuple(),
                 autofill=True
@@ -434,6 +481,14 @@ can use their Kerberos accounts.''')
                     )
                 )
 
+            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()
+
             for (dn, entry_attrs) in entries:
                 pkey = entry_attrs[ldap_obj.primary_key.name][0].lower()
                 if pkey in exclude:
@@ -453,7 +508,8 @@ can use their Kerberos accounts.''')
                     dn = callback(
                         ldap, pkey, dn, entry_attrs, failed[ldap_obj_name],
                         config, context, schema = options['schema'],
-                        search_bases = search_bases
+                        search_bases = search_bases,
+                        **blacklists
                     )
                     if not dn:
                         continue
-- 
1.7.5.2

dn: ou=Groups,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com
objectClass: top
objectClass: organizationalunit
ou: Groups

dn: ou=People,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com
objectClass: top
objectClass: organizationalunit
ou: People

dn: cn=ipatest1002,ou=People,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com
cn: ipatest1002
gecos: IPA 1 test user
gidNumber: 15000
givenName: ipatest1002
homeDirectory: /networld/ipatest1002
loginShell: /bin/bash
objectClass: posixAccount
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: top
sn: ipatest1002
uid: ipatest1002
uidNumber: 1002
userPassword: {SSHA}k6VZJSvhh8lg5m/yCQybvHPKP1PRwngxX0OIMw==

dn: cn=HR Managers,ou=Groups,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com
cn: HR Managers
description: People who can manage HR entries
objectClass: top
objectClass: groupOfUniqueNames
ou: groups
uniqueMember: cn=Directory Manager

dn: cn=Accounting Managers,ou=Groups,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com
cn: Accounting Managers
description: People who can manage accounting entries
objectClass: top
objectClass: groupOfUniqueNames
ou: groups
uniqueMember: cn=Directory Manager

dn: cn=ipatest1004,ou=People,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com
cn: ipatest1004
gecos: IPA 1 test user
gidNumber: 15000
givenName: ipatest1004
homeDirectory: /networld/ipatest1004
loginShell: /bin/bash
objectClass: posixAccount
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: radiusprofile
objectClass: radiusClientProfile
objectClass: top
radiusClientIPAddress: 10.0.0.4
radiusClientSecret: ipatest
sn: ipatest1004
uid: ipatest1004
uidNumber: 1004
userPassword: {SSHA}k+x+bIh0NA1r3bdFUirnjtRGaIBUcCcsClP9Ew==

dn: cn=QA Managers,ou=Groups,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com
cn: QA Managers
description: People who can manage QA entries
objectClass: top
objectClass: groupOfUniqueNames
ou: groups
uniqueMember: cn=Directory Manager

dn: cn=ipatest1003,ou=People,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com
cn: ipatest1003
gecos: IPA 1 test user
gidNumber: 15000
givenName: ipatest1003
homeDirectory: /networld/ipatest1003
loginShell: /bin/bash
objectClass: posixAccount
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: radiusprofile
objectClass: radiusClientProfile
objectClass: top
radiusClientIPAddress: 10.0.0.3
radiusClientSecret: ipatest
sn: ipatest1003
uid: ipatest1003
uidNumber: 1003
userPassword: {SSHA}VAKXUBXXqANutad9VCosfCvCqG0JfCC/JAGlRQ==

dn: cn=PD Managers,ou=Groups,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com
cn: PD Managers
description: People who can manage engineer entries
objectClass: top
objectClass: groupOfUniqueNames
ou: groups
uniqueMember: cn=Directory Manager

dn: cn=ipatest1001,ou=People,dc=idm,dc=lab,dc=bos,dc=redhat,dc=com
cn: ipatest1001
gecos: IPA 1 test user
gidNumber: 15000
givenName: ipatest1001
homeDirectory: /networld/ipatest1001
loginShell: /bin/bash
objectClass: posixAccount
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: top
sn: ipatest1001
uid: ipatest1001
uidNumber: 1001
userPassword: {SSHA}fhOwJEuAT/cXLnOCp7uTSOI5yKMb1JAtYJF6Sg==

dn: cn=ipausergroup,cn=Accounting Managers,ou=Groups,dc=idm,dc=lab,dc=bos,dc
 =redhat,dc=com
cn: ipausergroup
description: IPA 15000 Test Group
gidNumber: 15000
memberUid: ipatest1001
memberUid: ipatest1002
objectClass: posixGroup
objectClass: top

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to