summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--API.txt7
-rw-r--r--VERSION2
-rw-r--r--ipalib/plugins/migration.py73
3 files changed, 67 insertions, 15 deletions
diff --git a/API.txt b/API.txt
index 10b3f86a8..77ff362f9 100644
--- a/API.txt
+++ b/API.txt
@@ -1701,9 +1701,9 @@ 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,13,3
+args: 2,14,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))
+arg: Password('bindpw', cli_name='password', confirm=False, 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))
option: Str('usercontainer?', autofill=True, cli_name='user_container', default=u'ou=people', label=Gettext('User container', domain='ipa', localedir=None))
option: Str('groupcontainer?', autofill=True, cli_name='group_container', default=u'ou=groups', label=Gettext('Group container', domain='ipa', localedir=None))
@@ -1713,8 +1713,9 @@ option: List('userignoreobjectclass?', autofill=True, cli_name='user_ignore_obje
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: Flag('groupoverwritegid', autofill=True, cli_name='group_overwrite_gid', default=False, label=Gettext('Overwrite GID', domain='ipa', localedir=None))
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: Flag('continue?', autofill=True, default=False, label=Gettext('Continue', domain='ipa', localedir=None))
option: List('exclude_groups?', autofill=True, cli_name='exclude_groups', default=(), multivalue=True)
option: List('exclude_users?', autofill=True, cli_name='exclude_users', default=(), multivalue=True)
output: Output('result', <type 'dict'>, Gettext('Lists of objects migrated; categorized by type.', domain='ipa', localedir=None))
diff --git a/VERSION b/VERSION
index 51711efe3..024fd8ebc 100644
--- a/VERSION
+++ b/VERSION
@@ -79,4 +79,4 @@ IPA_DATA_VERSION=20100614120000
# #
########################################################
IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=12
+IPA_API_VERSION_MINOR=13
diff --git a/ipalib/plugins/migration.py b/ipalib/plugins/migration.py
index 93ac114d8..852cc9d64 100644
--- a/ipalib/plugins/migration.py
+++ b/ipalib/plugins/migration.py
@@ -71,6 +71,15 @@ EXAMPLES:
Specify the user and group container. This can be used to migrate user and
group data from an IPA v1 server:
ipa migrate-ds --user-container='cn=users,cn=accounts' --group-container='cn=groups,cn=accounts' ldap://ds.example.com:389
+
+ Since IPA v2 server already contain predefined groups that may collide with
+ groups in migrated (IPA v1) server (for example admins, ipausers), users having
+ colliding group as their primary group may happen to belong to an unknown group
+ on new IPA v2 server.
+ Use --group-overwrite-gid option to overwrite GID of already existing groups
+ to prevent this issue:
+ ipa migrate-ds --group-overwrite-gid --user-container='cn=users,cn=accounts' --group-container='cn=groups,cn=accounts' ldap://ds.example.com:389
+
""")
# USER MIGRATION CALLBACKS AND VARS
@@ -228,6 +237,28 @@ def _pre_migrate_group(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwarg
return dn
+def _group_exc_callback(ldap, dn, entry_attrs, exc, options):
+ if isinstance(exc, errors.DuplicateEntry):
+ if options.get('groupoverwritegid', False) and \
+ entry_attrs.get('gidnumber') is not None:
+ try:
+ new_entry_attrs = {'gidnumber':entry_attrs['gidnumber']}
+ ldap.update_entry(dn, new_entry_attrs)
+ except errors.EmptyModlist:
+ # no change to the GID
+ pass
+ # mark as success
+ return
+ elif not options.get('groupoverwritegid', False) and \
+ entry_attrs.get('gidnumber') is not None:
+ msg = unicode(exc)
+ # add information about possibility to overwrite GID
+ msg = msg + unicode(_('. Check GID of the existing group. ' \
+ 'Use --group-overwrite-gid option to overwrite the GID'))
+ raise errors.DuplicateEntry(message=msg)
+
+ raise exc
+
# DS MIGRATION PLUGIN
def construct_filter(template, oc_list):
@@ -252,6 +283,7 @@ class migrate_ds(Command):
# pre_callback - is called for each object just after it was
# retrieved from DS and before being added to IPA
# post_callback - is called for each object after it was added to IPA
+ # exc_callback - is called when adding entry to IPA raises an exception
#
# {pre, post}_callback parameters:
# ldap - ldap2 instance connected to IPA
@@ -270,7 +302,8 @@ class migrate_ds(Command):
'oc_blacklist_option' : 'userignoreobjectclass',
'attr_blacklist_option' : 'userignoreattribute',
'pre_callback' : _pre_migrate_user,
- 'post_callback' : _post_migrate_user
+ 'post_callback' : _post_migrate_user,
+ 'exc_callback' : None
},
'group': {
'filter_template' : '(&(|%s)(cn=*))',
@@ -278,7 +311,8 @@ class migrate_ds(Command):
'oc_blacklist_option' : 'groupignoreobjectclass',
'attr_blacklist_option' : 'groupignoreattribute',
'pre_callback' : _pre_migrate_group,
- 'post_callback' : None
+ 'post_callback' : None,
+ 'exc_callback' : _group_exc_callback,
},
}
migrate_order = ('user', 'group')
@@ -292,6 +326,7 @@ class migrate_ds(Command):
Password('bindpw',
cli_name='password',
label=_('Password'),
+ confirm=False,
doc=_('bind password'),
),
)
@@ -359,6 +394,12 @@ class migrate_ds(Command):
default=tuple(),
autofill=True,
),
+ Flag('groupoverwritegid',
+ cli_name='group_overwrite_gid',
+ label=_('Overwrite GID'),
+ doc=_('When migrating a group already existing in IPA domain overwrite the '\
+ 'group GID and report as success'),
+ ),
StrEnum('schema?',
cli_name='schema',
label=_('LDAP schema'),
@@ -368,6 +409,7 @@ class migrate_ds(Command):
autofill=True,
),
Flag('continue?',
+ label=_('Continue'),
doc=_('Continuous operation mode. Errors are reported but the process continues'),
default=False,
),
@@ -539,16 +581,25 @@ can use their Kerberos accounts.''')
try:
ldap.add_entry(dn, entry_attrs)
except errors.ExecutionError, e:
- failed[ldap_obj_name][pkey] = unicode(e)
- else:
- migrated[ldap_obj_name].append(pkey)
-
- callback = self.migrate_objects[ldap_obj_name]['post_callback']
+ callback = self.migrate_objects[ldap_obj_name]['exc_callback']
if callable(callback):
- callback(
- ldap, pkey, dn, entry_attrs, failed[ldap_obj_name],
- config, context
- )
+ 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
+
+ migrated[ldap_obj_name].append(pkey)
+
+ callback = self.migrate_objects[ldap_obj_name]['post_callback']
+ if callable(callback):
+ callback(
+ ldap, pkey, dn, entry_attrs, failed[ldap_obj_name],
+ config, context,
+ )
return (migrated, failed)