summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Kosek <mkosek@redhat.com>2011-10-03 16:01:01 +0200
committerRob Crittenden <rcritten@redhat.com>2011-10-11 23:24:00 -0400
commit2aa63fe4a98f6bae755b4ede607adc2068103c42 (patch)
tree7f107f01212aeb89c4ae409ae94d8f479288d87b
parent97fc2ed0ef401f2352e43f065d0bdf76f5c7521e (diff)
downloadfreeipa-2aa63fe4a98f6bae755b4ede607adc2068103c42.zip
freeipa-2aa63fe4a98f6bae755b4ede607adc2068103c42.tar.gz
freeipa-2aa63fe4a98f6bae755b4ede607adc2068103c42.tar.xz
Improve handling of GIDs when migrating groups
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. Implement --group-overwrite-gid option to overwrite GID of already existing groups to prevent this issue. https://fedorahosted.org/freeipa/ticket/1866
-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 10b3f86..77ff362 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 51711ef..024fd8e 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 93ac114..852cc9d 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)