From f1f1b4e7f2e9c1838ad7ec76002b78ca0c2a3c46 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Nov 21 2012 13:55:12 +0000 Subject: Enable transactions by default, make password and modrdn TXN-aware The password and modrdn plugins needed to be made transaction aware for the pre and post operations. Remove the reverse member hoop jumping. Just fetch the entry once and all the memberof data is there (plus objectclass). Fix some unit tests that are failing because we actually get the data now due to transactions. Add small bit of code in user plugin to retrieve the user again ala wait_for_attr but in the case of transactions we need do it only once. Deprecate wait_for_attr code. Add a memberof fixup task for roles. https://fedorahosted.org/freeipa/ticket/1263 https://fedorahosted.org/freeipa/ticket/1891 https://fedorahosted.org/freeipa/ticket/2056 https://fedorahosted.org/freeipa/ticket/3043 https://fedorahosted.org/freeipa/ticket/3191 https://fedorahosted.org/freeipa/ticket/3046 --- diff --git a/daemons/ipa-slapi-plugins/ipa-modrdn/ipa_modrdn.c b/daemons/ipa-slapi-plugins/ipa-modrdn/ipa_modrdn.c index 70a4ea8..6cec5f2 100644 --- a/daemons/ipa-slapi-plugins/ipa-modrdn/ipa_modrdn.c +++ b/daemons/ipa-slapi-plugins/ipa-modrdn/ipa_modrdn.c @@ -201,6 +201,12 @@ ipamodrdn_init(Slapi_PBlock *pb) { int status = EOK; char *plugin_identity = NULL; + Slapi_Entry *plugin_entry = NULL; + char *plugin_type = NULL; + int delfn = SLAPI_PLUGIN_POST_DELETE_FN; + int mdnfn = SLAPI_PLUGIN_POST_MODRDN_FN; + int modfn = SLAPI_PLUGIN_POST_MODIFY_FN; + int addfn = SLAPI_PLUGIN_POST_ADD_FN; LOG_TRACE("--in-->\n"); @@ -213,6 +219,18 @@ ipamodrdn_init(Slapi_PBlock *pb) PR_ASSERT(plugin_identity); setPluginID(plugin_identity); + if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) && + plugin_entry && + (plugin_type = slapi_entry_attr_get_charptr(plugin_entry, "nsslapd-plugintype")) && + plugin_type && strstr(plugin_type, "betxn")) + { + addfn = SLAPI_PLUGIN_BE_TXN_POST_ADD_FN; + mdnfn = SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN; + delfn = SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN; + modfn = SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN; + } + slapi_ch_free_string(&plugin_type); + if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01) != 0 || slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, @@ -221,13 +239,13 @@ ipamodrdn_init(Slapi_PBlock *pb) (void *) ipamodrdn_start) != 0 || slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN, (void *) ipamodrdn_close) != 0 || - slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN, + slapi_pblock_set(pb, addfn, (void *) ipamodrdn_config_check_post_op) != 0 || - slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODRDN_FN, + slapi_pblock_set(pb, mdnfn, (void *) ipamodrdn_post_op) != 0 || - slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN, + slapi_pblock_set(pb, delfn, (void *) ipamodrdn_config_check_post_op) != 0 || - slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN, + slapi_pblock_set(pb, modfn, (void *) ipamodrdn_config_check_post_op) != 0) { LOG_FATAL("failed to register plugin\n"); status = EFAIL; diff --git a/daemons/ipa-slapi-plugins/ipa-modrdn/modrdn-conf.ldif b/daemons/ipa-slapi-plugins/ipa-modrdn/modrdn-conf.ldif index 176f8be..3ae1ee2 100644 --- a/daemons/ipa-slapi-plugins/ipa-modrdn/modrdn-conf.ldif +++ b/daemons/ipa-slapi-plugins/ipa-modrdn/modrdn-conf.ldif @@ -6,7 +6,7 @@ objectclass: extensibleObject cn: IPA MODRDN nsslapd-pluginpath: libipa_modrdn nsslapd-plugininitfunc: ipamodrdn_init -nsslapd-plugintype: postoperation +nsslapd-plugintype: betxnpostoperation nsslapd-pluginenabled: on nsslapd-pluginid: ipamodrdn_version nsslapd-pluginversion: 1.0 diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c index f9cff70..425b1c0 100644 --- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c +++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c @@ -1270,6 +1270,15 @@ static char *ipapwd_name_list[] = { int ipapwd_init( Slapi_PBlock *pb ) { int ret; + Slapi_Entry *plugin_entry = NULL; + int is_betxn = 0; + + /* get args */ + if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) && + plugin_entry) { + is_betxn = slapi_entry_attr_get_bool(plugin_entry, + "nsslapd-pluginbetxn"); + } /* Get the arguments appended to the plugin extendedop directive. The first argument * (after the standard arguments for the directive) should contain the OID of the @@ -1301,6 +1310,18 @@ int ipapwd_init( Slapi_PBlock *pb ) return -1; } + if (is_betxn) { + slapi_register_plugin("betxnpreoperation", 1, + "ipapwd_pre_init_betxn", ipapwd_pre_init_betxn, + "IPA pwd pre ops betxn", NULL, + ipapwd_plugin_id); + + slapi_register_plugin("betxnpostoperation", 1, + "ipapwd_post_init_betxn", ipapwd_post_init_betxn, + "IPA pwd post ops betxn", NULL, + ipapwd_plugin_id); + } + slapi_register_plugin("preoperation", 1, "ipapwd_pre_init", ipapwd_pre_init, "IPA pwd pre ops", NULL, diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h index 0edd2dc..3689783 100644 --- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h +++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h @@ -152,4 +152,6 @@ int ipapwd_gen_hashes(struct ipapwd_krbcfg *krbcfg, int ipapwd_ext_init(void); int ipapwd_pre_init(Slapi_PBlock *pb); int ipapwd_post_init(Slapi_PBlock *pb); +int ipapwd_pre_init_betxn(Slapi_PBlock *pb); +int ipapwd_post_init_betxn(Slapi_PBlock *pb); diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_prepost.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_prepost.c index e4909c9..0e4a63b 100644 --- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_prepost.c +++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_prepost.c @@ -1307,6 +1307,19 @@ int ipapwd_pre_init(Slapi_PBlock *pb) return ret; } +int ipapwd_pre_init_betxn(Slapi_PBlock *pb) +{ + int ret; + + ret = slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01); + if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&ipapwd_plugin_desc); + if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_BIND_FN, (void *)ipapwd_pre_bind); + if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN, (void *)ipapwd_pre_add); + if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN, (void *)ipapwd_pre_mod); + + return ret; +} + /* Init post ops */ int ipapwd_post_init(Slapi_PBlock *pb) { @@ -1320,3 +1333,14 @@ int ipapwd_post_init(Slapi_PBlock *pb) return ret; } +int ipapwd_post_init_betxn(Slapi_PBlock *pb) +{ + int ret; + + ret = slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01); + if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&ipapwd_plugin_desc); + if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_POST_ADD_FN, (void *)ipapwd_post_op); + if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN, (void *)ipapwd_post_op); + + return ret; +} diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/pwd-extop-conf.ldif b/daemons/ipa-slapi-plugins/ipa-pwd-extop/pwd-extop-conf.ldif index e31a8e7..4d4e6e6 100644 --- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/pwd-extop-conf.ldif +++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/pwd-extop-conf.ldif @@ -7,6 +7,7 @@ cn: ipa_pwd_extop nsslapd-pluginpath: libipa_pwd_extop nsslapd-plugininitfunc: ipapwd_init nsslapd-plugintype: extendedop +nsslapd-pluginbetxn: on nsslapd-pluginenabled: on nsslapd-pluginid: ipa_pwd_extop nsslapd-pluginversion: 1.0 diff --git a/freeipa.spec.in b/freeipa.spec.in index 3ab0e3d..50e743d 100644 --- a/freeipa.spec.in +++ b/freeipa.spec.in @@ -113,7 +113,7 @@ Requires(pre): systemd-units Requires(post): systemd-units Requires: selinux-policy >= 3.10.0-110 Requires(post): selinux-policy-base -Requires: slapi-nis >= 0.40 +Requires: slapi-nis >= 0.44 %if 0%{?fedora} >= 18 Requires: pki-ca >= 10.0.0-0.52.b3 Requires: dogtag-pki-server-theme @@ -733,6 +733,9 @@ fi %ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/ipa/ca.crt %changelog +* Fri Nov 16 2012 Rob Crittenden - 3.0.99-5 +- Bump minimum version of slapi-nis to 0.44 + * Wed Nov 14 2012 Martin Kosek - 3.0.99-4 - Remove compatibility definitions for unsupported Fedora versions (Fedora 16 and lower) - Do not require specific package version when the package was available in Fedora 17 diff --git a/install/share/nis.uldif b/install/share/nis.uldif index 1e54828..1735fb5 100644 --- a/install/share/nis.uldif +++ b/install/share/nis.uldif @@ -6,6 +6,7 @@ default:cn: NIS Server default:nsslapd-pluginpath: /usr/lib$LIBARCH/dirsrv/plugins/nisserver-plugin.so default:nsslapd-plugininitfunc: nis_plugin_init default:nsslapd-plugintype: object +default:nsslapd-pluginbetxn: on default:nsslapd-pluginenabled: on default:nsslapd-pluginid: nis-server default:nsslapd-pluginversion: 0.10 diff --git a/install/share/schema_compat.uldif b/install/share/schema_compat.uldif index deca1bb..a93b327 100644 --- a/install/share/schema_compat.uldif +++ b/install/share/schema_compat.uldif @@ -14,6 +14,7 @@ default:nsslapd-plugintype: object default:nsslapd-pluginenabled: on default:nsslapd-pluginid: schema-compat-plugin default:nsslapd-pluginversion: 0.8 +default:nsslapd-pluginbetxn: on default:nsslapd-pluginvendor: redhat.com default:nsslapd-plugindescription: Schema Compatibility Plugin diff --git a/install/tools/man/ipa-ldap-updater.1 b/install/tools/man/ipa-ldap-updater.1 index df8dfe6..37e200f 100644 --- a/install/tools/man/ipa-ldap-updater.1 +++ b/install/tools/man/ipa-ldap-updater.1 @@ -37,6 +37,7 @@ There are 7 keywords: * add: add a value (or values) to an attribute * remove: remove a value (or values) from an attribute * only: set an attribute to this + * onlyifexist: set an attribute to this only if the entry exists * deleteentry: remove the entry * replace: replace an existing value, format is old: new * addifnew: add a new attribute and value only if the attribute doesn't already exist. Only works with single\-value attributes. diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json index 41f2c62..44484a9 100644 --- a/install/ui/test/data/ipa_init.json +++ b/install/ui/test/data/ipa_init.json @@ -738,7 +738,6 @@ "startup_traceback": false, "validate_api": false, "verbose": 0, - "wait_for_attr": false, "webui_assets_dir": null, "webui_prod": true, "xmlrpc_uri": "https://dev.example.com/ipa/xml" diff --git a/install/updates/10-disable-betxn.update b/install/updates/10-disable-betxn.update deleted file mode 100644 index 8fca4a5..0000000 --- a/install/updates/10-disable-betxn.update +++ /dev/null @@ -1,37 +0,0 @@ -# Disable transactions in 389-ds-base - -dn: cn=7-bit check,cn=plugins,cn=config -only: nsslapd-pluginType: preoperation - -dn: cn=attribute uniqueness,cn=plugins,cn=config -only: nsslapd-pluginType: preoperation - -dn: cn=Auto Membership Plugin,cn=plugins,cn=config -only: nsslapd-pluginType: preoperation - -dn: cn=Linked Attributes,cn=plugins,cn=config -only: nsslapd-pluginType: preoperation - -dn: cn=Managed Entries,cn=plugins,cn=config -only: nsslapd-pluginType: preoperation - -dn: cn=MemberOf Plugin,cn=plugins,cn=config -only: nsslapd-pluginType: postoperation - -dn: cn=Multimaster Replication Plugin,cn=plugins,cn=config -only: nsslapd-pluginbetxn: off - -dn: cn=PAM Pass Through Auth,cn=plugins,cn=config -only: nsslapd-pluginType: preoperation - -dn: cn=referential integrity postoperation,cn=plugins,cn=config -only: nsslapd-pluginType: postoperation - -dn: cn=Roles Plugin,cn=plugins,cn=config -only: nsslapd-pluginbetxn: off - -dn: cn=State Change Plugin,cn=plugins,cn=config -only: nsslapd-pluginType: postoperation - -dn: cn=USN,cn=plugins,cn=config -only: nsslapd-pluginbetxn: off diff --git a/install/updates/10-enable-betxn.update b/install/updates/10-enable-betxn.update new file mode 100644 index 0000000..88f584c --- /dev/null +++ b/install/updates/10-enable-betxn.update @@ -0,0 +1,49 @@ +# Enable transactions in 389-ds-base + +dn: cn=7-bit check,cn=plugins,cn=config +only: nsslapd-pluginType: betxnpreoperation + +dn: cn=attribute uniqueness,cn=plugins,cn=config +only: nsslapd-pluginType: betxnpreoperation + +dn: cn=Auto Membership Plugin,cn=plugins,cn=config +only: nsslapd-pluginType: betxnpreoperation + +dn: cn=Linked Attributes,cn=plugins,cn=config +only: nsslapd-pluginType: betxnpreoperation + +dn: cn=Managed Entries,cn=plugins,cn=config +only: nsslapd-pluginType: betxnpreoperation + +dn: cn=MemberOf Plugin,cn=plugins,cn=config +only: nsslapd-pluginType: betxnpostoperation + +dn: cn=Multimaster Replication Plugin,cn=plugins,cn=config +only: nsslapd-pluginbetxn: on + +dn: cn=PAM Pass Through Auth,cn=plugins,cn=config +only: nsslapd-pluginType: betxnpreoperation + +dn: cn=referential integrity postoperation,cn=plugins,cn=config +only: nsslapd-pluginType: betxnpostoperation + +dn: cn=Roles Plugin,cn=plugins,cn=config +only: nsslapd-pluginbetxn: on + +dn: cn=State Change Plugin,cn=plugins,cn=config +only: nsslapd-pluginType: betxnpostoperation + +dn: cn=USN,cn=plugins,cn=config +only: nsslapd-pluginbetxn: on + +dn: cn=IPA MODRDN,cn=plugins,cn=config +only: nsslapd-plugintype: betxnpostoperation + +dn: cn=ipa_pwd_extop,cn=plugins,cn=config +only: nsslapd-pluginbetxn: on + +dn: cn=Schema Compatibility, cn=plugins, cn=config +onlyifexist: nsslapd-pluginbetxn: on + +dn: cn=NIS Server, cn=plugins, cn=config +onlyifexist: nsslapd-pluginbetxn: on diff --git a/install/updates/55-pbacmemberof.update b/install/updates/55-pbacmemberof.update index bc17f56..f02b4f8 100644 --- a/install/updates/55-pbacmemberof.update +++ b/install/updates/55-pbacmemberof.update @@ -8,3 +8,11 @@ add: cn: IPA PBAC memberOf $TIME add: basedn: 'cn=privileges,cn=pbac,$SUFFIX' add: filter: (objectclass=*) add: ttl: 10 + +dn: cn=Update Role memberOf $TIME, cn=memberof task, cn=tasks, cn=config +add: objectClass: top +add: objectClass: extensibleObject +add: cn: Update Role memberOf $TIME +add: basedn: 'cn=roles,cn=accounts,$SUFFIX' +add: filter: (objectclass=*) +add: ttl: 10 diff --git a/install/updates/Makefile.am b/install/updates/Makefile.am index a675af8..2e4f0a2 100644 --- a/install/updates/Makefile.am +++ b/install/updates/Makefile.am @@ -7,7 +7,7 @@ app_DATA = \ 10-RFC2307bis.update \ 10-RFC4876.update \ 10-config.update \ - 10-disable-betxn.update \ + 10-enable-betxn.update \ 10-selinuxusermap.update \ 10-sudo.update \ 10-ssh.update \ diff --git a/ipa-client/man/default.conf.5 b/ipa-client/man/default.conf.5 index f779b51..a0804e3 100644 --- a/ipa-client/man/default.conf.5 +++ b/ipa-client/man/default.conf.5 @@ -178,9 +178,6 @@ Used internally in the IPA source package to verify that the API has not changed .B verbose When True provides more information. Specifically this sets the global log level to "info". .TP -.B wait_for_attr -Debug option. Waits for asynchronous execution of 389-ds postoperation plugins before returning data to the client, therefore data added by postoperation plugins is included in the result. Increases execution time. -.TP .B xmlrpc_uri Specifies the URI of the XML\-RPC server for a client. This is used by IPA and some external tools as well, such as ipa\-getcert. e.g. https://ipa.example.com/ipa/xml .TP diff --git a/ipalib/constants.py b/ipalib/constants.py index 81db020..bf49375 100644 --- a/ipalib/constants.py +++ b/ipalib/constants.py @@ -157,7 +157,6 @@ DEFAULT_CONFIG = ( # Enable certain optional plugins: ('enable_ra', False), ('ra_plugin', 'selfsign'), - ('wait_for_attr', False), ('dogtag_version', 9), # Used when verifying that the API hasn't changed. Not for production. diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py index a55a232..85e2bec 100644 --- a/ipalib/plugins/baseldap.py +++ b/ipalib/plugins/baseldap.py @@ -231,50 +231,6 @@ def entry_from_entry(entry, newentry): for e in newentry: entry[e] = newentry[e] -def wait_for_memberof(keys, entry_start, completed, show_command, adding=True): - """ - When adding or removing reverse members we are faking an update to - object A by updating the member attribute in object B. The memberof - plugin makes this work by adding or removing the memberof attribute - to/from object A, it just takes a little bit of time. - - This will loop for 6+ seconds, retrieving object A so we can see - if all the memberof attributes have been updated. - """ - if completed == 0: - # nothing to do - return api.Command[show_command](keys[-1])['result'] - - if 'memberof' in entry_start: - starting_memberof = len(entry_start['memberof']) - else: - starting_memberof = 0 - - # Loop a few times to give the memberof plugin a chance to add the - # entries. Don't sleep for more than 6 seconds. - memberof = 0 - x = 0 - while x < 20: - # sleep first because the first search, even on a quiet system, - # almost always fails to have memberof set. - time.sleep(.3) - x = x + 1 - - # FIXME: put a try/except around here? I think it is probably better - # to just let the exception filter up to the caller. - entry_attrs = api.Command[show_command](keys[-1])['result'] - if 'memberof' in entry_attrs: - memberof = len(entry_attrs['memberof']) - - if adding: - if starting_memberof + completed >= memberof: - break - else: - if starting_memberof + completed <= memberof: - break - - return entry_attrs - def wait_for_value(ldap, dn, attr, value): """ 389-ds postoperation plugins are executed after the data has been @@ -2029,11 +1985,9 @@ class LDAPAddReverseMember(LDAPModReverseMember): except errors.PublicError, e: failed['member'][self.reverse_attr].append((attr, unicode(msg))) - # Wait for the memberof plugin to update the entry - try: - entry_attrs = wait_for_memberof(keys, entry_start, completed, self.show_command, adding=True) - except Exception, e: - raise errors.ReverseMemberError(verb=_('added'), exc=str(e)) + # Update the member data. + (dn, entry_attrs) = ldap.get_entry(dn, ['*']) + self.obj.convert_attribute_members(entry_attrs, *keys, **options) for callback in self.get_callbacks('post'): (completed, dn) = callback( @@ -2131,11 +2085,9 @@ class LDAPRemoveReverseMember(LDAPModReverseMember): except errors.PublicError, e: failed['member'][self.reverse_attr].append((attr, unicode(msg))) - # Wait for the memberof plugin to update the entry - try: - entry_attrs = wait_for_memberof(keys, entry_start, completed, self.show_command, adding=False) - except Exception, e: - raise errors.ReverseMemberError(verb=_('removed'), exc=str(e)) + # Update the member data. + (dn, entry_attrs) = ldap.get_entry(dn, ['*']) + self.obj.convert_attribute_members(entry_attrs, *keys, **options) for callback in self.get_callbacks('post'): (completed, dn) = callback( diff --git a/ipalib/plugins/permission.py b/ipalib/plugins/permission.py index 80c6bc0..1fbf9e0 100644 --- a/ipalib/plugins/permission.py +++ b/ipalib/plugins/permission.py @@ -115,6 +115,7 @@ class permission(LDAPObject): ] attribute_members = { 'member': ['privilege'], + 'memberindirect': ['role'], } rdn_is_primary_key = True diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py index 5d667dc..80bdc39 100644 --- a/ipalib/plugins/user.py +++ b/ipalib/plugins/user.py @@ -547,9 +547,6 @@ class user_add(LDAPCreate): except errors.AlreadyGroupMember: pass - if self.api.env.wait_for_attr: - newentry = wait_for_value(ldap, dn, 'memberOf', def_primary_group) - entry_from_entry(entry_attrs, newentry) self.obj._convert_manager(entry_attrs, **options) # delete description attribute NO_UPG_MAGIC if present if options.get('noprivate', False): @@ -563,10 +560,11 @@ class user_add(LDAPCreate): self.api.Command['user_mod'](keys[-1], **kw) except (errors.EmptyModlist, errors.NotFound): pass - else: - if self.api.env.wait_for_attr: - newentry = wait_for_value(ldap, dn, 'objectclass', 'mepOriginEntry') - entry_from_entry(entry_attrs, newentry) + + # Fetch the entry again to update memberof, mep data, etc updated + # at the end of the transaction. + (newdn, newentry) = ldap.get_entry(dn, ['*']) + entry_attrs.update(newentry) if options.get('random', False): try: diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index b48e7d7..fe42282 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -202,7 +202,6 @@ class DsInstance(service.Service): self.step("configuring replication version plugin", self.__config_version_module) self.step("enabling IPA enrollment plugin", self.__add_enrollment_module) self.step("enabling ldapi", self.__enable_ldapi) - self.step("disabling betxn plugins", self.__disable_betxn) self.step("configuring uniqueness plugin", self.__set_unique_attrs) self.step("configuring uuid plugin", self.__config_uuid_module) self.step("configuring modrdn plugin", self.__config_modrdn_module) @@ -476,9 +475,6 @@ class DsInstance(service.Service): def __add_referint_module(self): self._ldap_mod("referint-conf.ldif") - def __disable_betxn(self): - self._ldap_mod("disable-betxn.ldif", self.sub_dict) - def __set_unique_attrs(self): self._ldap_mod("unique-attributes.ldif", self.sub_dict) diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py index eb95858..f7261ad 100644 --- a/ipaserver/install/ldapupdate.py +++ b/ipaserver/install/ldapupdate.py @@ -59,7 +59,7 @@ class BadSyntax(installutils.ScriptError): return repr(self.value) class LDAPUpdate: - action_keywords = ["default", "add", "remove", "only", "deleteentry", "replace", "addifnew", "addifexist"] + action_keywords = ["default", "add", "remove", "only", "onlyifexist", "deleteentry", "replace", "addifnew", "addifexist"] def __init__(self, dm_password, sub_dict={}, live_run=True, online=True, ldapi=False, plugins=False): @@ -623,6 +623,18 @@ class LDAPUpdate: only[attr] = True entry.setValues(attr, entry_values) self.debug('only: updated value %s', entry_values) + elif action == 'onlyifexist': + self.debug("onlyifexist: '%s' to %s, current value %s", update_value, attr, entry_values) + # Only set the attribute if the entry exist's. We + # determine this based on whether it has an objectclass + if entry.getValues('objectclass'): + if only.get(attr): + entry_values.append(update_value) + else: + entry_values = [update_value] + only[attr] = True + self.debug('onlyifexist: set %s to %s', attr, entry_values) + entry.setValues(attr, entry_values) elif action == 'deleteentry': # skip this update type, it occurs in __delete_entries() return None diff --git a/tests/test_xmlrpc/test_automember_plugin.py b/tests/test_xmlrpc/test_automember_plugin.py index fcd9fac..fdf3c73 100644 --- a/tests/test_xmlrpc/test_automember_plugin.py +++ b/tests/test_xmlrpc/test_automember_plugin.py @@ -886,6 +886,8 @@ class test_automember(Declarative): objectclass=objectclasses.host, ipauniqueid=[fuzzy_uuid], managedby_host=[fqdn1], + memberof_hostgroup=[hostgroup1], + memberofindirect_netgroup=[hostgroup1], ), ), ), @@ -914,6 +916,8 @@ class test_automember(Declarative): objectclass=objectclasses.host, ipauniqueid=[fuzzy_uuid], managedby_host=[fqdn2], + memberof_hostgroup=[defaulthostgroup1], + memberofindirect_netgroup=[defaulthostgroup1], ), ), ), @@ -942,6 +946,8 @@ class test_automember(Declarative): objectclass=objectclasses.host, ipauniqueid=[fuzzy_uuid], managedby_host=[fqdn3], + memberof_hostgroup=[hostgroup2], + memberofindirect_netgroup=[hostgroup2], ), ), ), @@ -970,6 +976,8 @@ class test_automember(Declarative): objectclass=objectclasses.host, ipauniqueid=[fuzzy_uuid], managedby_host=[fqdn4], + memberof_hostgroup=[hostgroup3], + memberofindirect_netgroup=[hostgroup3], ), ), ), @@ -998,6 +1006,8 @@ class test_automember(Declarative): objectclass=objectclasses.host, ipauniqueid=[fuzzy_uuid], managedby_host=[fqdn5], + memberof_hostgroup=[hostgroup4], + memberofindirect_netgroup=[hostgroup4], ), ), ), diff --git a/tests/test_xmlrpc/test_nesting.py b/tests/test_xmlrpc/test_nesting.py index 6af9c9d..a09a798 100644 --- a/tests/test_xmlrpc/test_nesting.py +++ b/tests/test_xmlrpc/test_nesting.py @@ -750,6 +750,7 @@ class test_nesting(Declarative): 'cn': [hostgroup1], 'description': [u'Test hostgroup 1'], 'member_hostgroup': [hostgroup2], + 'memberindirect_host': [fqdn1], }, ), ), diff --git a/tests/test_xmlrpc/test_permission_plugin.py b/tests/test_xmlrpc/test_permission_plugin.py index eda96d0..4fe1eef 100644 --- a/tests/test_xmlrpc/test_permission_plugin.py +++ b/tests/test_xmlrpc/test_permission_plugin.py @@ -194,6 +194,7 @@ class test_permission(Declarative): 'cn': [privilege1], 'description': [u'privilege desc. 1'], 'memberof_permission': [permission1], + 'objectclass': objectclasses.privilege, } ), ), @@ -501,10 +502,10 @@ class test_permission(Declarative): api.env.container_permission, api.env.basedn), 'cn': [u'Modify HBAC rule'], 'member_privilege': [u'HBAC Administrator'], + 'memberindirect_role': [u'IT Security Specialist'], 'permissions' : [u'write'], 'attrs': [u'servicecategory', u'sourcehostcategory', u'cn', u'description', u'ipaenabledflag', u'accesstime', u'usercategory', u'hostcategory', u'accessruletype', u'sourcehost'], 'subtree' : u'ldap:///%s' % DN(('ipauniqueid', '*'), ('cn', 'hbac'), api.env.basedn), - 'memberindirect': [DN(('cn', 'it security specialist'), ('cn', 'roles'), ('cn', 'accounts'), api.env.basedn)], }, ], ), diff --git a/tests/test_xmlrpc/test_privilege_plugin.py b/tests/test_xmlrpc/test_privilege_plugin.py index d4784af..81e51d5 100644 --- a/tests/test_xmlrpc/test_privilege_plugin.py +++ b/tests/test_xmlrpc/test_privilege_plugin.py @@ -142,6 +142,7 @@ class test_privilege(Declarative): 'cn': [privilege1], 'description': [u'privilege desc. 1'], 'memberof_permission': [permission1], + 'objectclass': objectclasses.privilege, } ), ), @@ -240,6 +241,7 @@ class test_privilege(Declarative): 'cn': [privilege1], 'description': [u'privilege desc. 1'], 'memberof_permission': [permission1, permission2], + 'objectclass': objectclasses.privilege, } ), ), @@ -262,6 +264,7 @@ class test_privilege(Declarative): 'cn': [privilege1], 'description': [u'privilege desc. 1'], 'memberof_permission': [permission1, permission2], + 'objectclass': objectclasses.privilege, } ), ), @@ -320,6 +323,7 @@ class test_privilege(Declarative): 'cn': [privilege1], 'description': [u'New desc 1'], 'memberof_permission': [permission2], + 'objectclass': objectclasses.privilege, } ), ), @@ -342,6 +346,7 @@ class test_privilege(Declarative): 'cn': [privilege1], 'description': [u'New desc 1'], 'memberof_permission': [permission2], + 'objectclass': objectclasses.privilege, } ), ), @@ -364,6 +369,7 @@ class test_privilege(Declarative): 'cn': [privilege1], 'description': [u'New desc 1'], 'memberof_permission': [permission2], + 'objectclass': objectclasses.privilege, } ), ), @@ -386,6 +392,7 @@ class test_privilege(Declarative): 'cn': [privilege1], 'description': [u'New desc 1'], 'memberof_permission': [permission2], + 'objectclass': objectclasses.privilege, } ), ), diff --git a/tests/test_xmlrpc/test_role_plugin.py b/tests/test_xmlrpc/test_role_plugin.py index b847ca9..be3fece 100644 --- a/tests/test_xmlrpc/test_role_plugin.py +++ b/tests/test_xmlrpc/test_role_plugin.py @@ -196,6 +196,7 @@ class test_role(Declarative): 'cn': [role1], 'description': [u'role desc 1'], 'memberof_privilege': [privilege1], + 'objectclass': objectclasses.role, } ), ), @@ -217,6 +218,7 @@ class test_role(Declarative): 'cn': [role1], 'description': [u'role desc 1'], 'memberof_privilege': [privilege1], + 'objectclass': objectclasses.role, } ), ), @@ -238,6 +240,7 @@ class test_role(Declarative): 'cn': [role1], 'description': [u'role desc 1'], 'memberof_privilege': [privilege1], + 'objectclass': objectclasses.role, } ), ), @@ -518,6 +521,7 @@ class test_role(Declarative): 'dn': role1_dn, 'cn': [role1], 'description': [u'New desc 1'], + 'objectclass': objectclasses.role, } ), ), @@ -539,6 +543,7 @@ class test_role(Declarative): 'dn': role1_dn, 'cn': [role1], 'description': [u'New desc 1'], + 'objectclass': objectclasses.role, } ), ),