dirsrvtests/tickets/ticket48294_test.py | 290 ++++++++++++++++++++++++
ldap/servers/plugins/linkedattrs/linked_attrs.c | 10
man/man1/dbgen.pl.1 | 3
3 files changed, 302 insertions(+), 1 deletion(-)
New commits:
commit c3b4c0c2ab30fd219e35f1ab4d8a05dd065f685c
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Dec 18 17:13:33 2015 -0800
Ticket #48294 - CI test: added test cases for ticket 48294
Description: Linked Attributes plug-in - won't update links after MODRDN
operation
https://fedorahosted.org/389/ticket/48294
diff --git a/dirsrvtests/tickets/ticket48294_test.py
b/dirsrvtests/tickets/ticket48294_test.py
new file mode 100644
index 0000000..109a67e
--- /dev/null
+++ b/dirsrvtests/tickets/ticket48294_test.py
@@ -0,0 +1,290 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2015 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+#
+import os
+import sys
+import time
+import ldap
+import logging
+import pytest
+import shutil
+from lib389 import DirSrv, Entry, tools
+from lib389 import DirSrvTools
+from lib389.tools import DirSrvTools
+from lib389._constants import *
+from lib389.properties import *
+
+log = logging.getLogger(__name__)
+
+installation_prefix = None
+
+LINKEDATTR_PLUGIN = 'cn=Linked Attributes,cn=plugins,cn=config'
+MANAGER_LINK = 'cn=Manager Link,' + LINKEDATTR_PLUGIN
+OU_PEOPLE = 'ou=People,' + DEFAULT_SUFFIX
+LINKTYPE = 'directReport'
+MANAGEDTYPE = 'manager'
+
+class TopologyStandalone(object):
+ def __init__(self, standalone):
+ standalone.open()
+ self.standalone = standalone
+
+
+(a)pytest.fixture(scope="module")
+def topology(request):
+ '''
+ This fixture is used to standalone topology for the 'module'.
+ '''
+ global installation_prefix
+
+ if installation_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation_prefix
+
+ standalone = DirSrv(verbose=False)
+
+ # Args for the standalone instance
+ args_instance[SER_HOST] = HOST_STANDALONE
+ args_instance[SER_PORT] = PORT_STANDALONE
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
+ args_standalone = args_instance.copy()
+ standalone.allocate(args_standalone)
+
+ # Get the status of the instance and restart it if it exists
+ instance_standalone = standalone.exists()
+
+ # Remove the instance
+ if instance_standalone:
+ standalone.delete()
+
+ # Create the instance
+ standalone.create()
+
+ # Used to retrieve configuration information (dbdir, confdir...)
+ standalone.open()
+
+ # clear the tmp directory
+ standalone.clearTmpDir(__file__)
+
+ # Here we have standalone instance up and running
+ return TopologyStandalone(standalone)
+
+
+def _header(topology, label):
+
topology.standalone.log.info("###############################################")
+ topology.standalone.log.info("####### %s" % label)
+
topology.standalone.log.info("###############################################")
+
+def check_attr_val(topology, dn, attr, expected):
+ try:
+ centry = topology.standalone.search_s(dn, ldap.SCOPE_BASE, 'uid=*')
+ if centry:
+ val = centry[0].getValue(attr)
+ if val.lower() == expected.lower():
+ log.info('Value of %s is %s' % (attr, expected))
+ else:
+ log.info('Value of %s is not %s, but %s' % (attr, expected,
val))
+ assert False
+ else:
+ log.fatal('Failed to get %s' % dn)
+ assert False
+ except ldap.LDAPError as e:
+ log.fatal('Failed to search ' + dn + ': ' +
e.message['desc'])
+ assert False
+
+
+def _modrdn_entry(topology=None, entry_dn=None, new_rdn=None, del_old=0,
new_superior=None):
+ assert topology is not None
+ assert entry_dn is not None
+ assert new_rdn is not None
+
+ topology.standalone.log.info("\n\n######################### MODRDN %s
######################\n" % new_rdn)
+ try:
+ if new_superior:
+ topology.standalone.rename_s(entry_dn, new_rdn, newsuperior=new_superior,
delold=del_old)
+ else:
+ topology.standalone.rename_s(entry_dn, new_rdn, delold=del_old)
+ except ldap.NO_SUCH_ATTRIBUTE:
+ topology.standalone.log.info("accepted failure due to 47833: modrdn reports
error.. but succeeds")
+ attempt = 0
+ if new_superior:
+ dn = "%s,%s" % (new_rdn, new_superior)
+ base = new_superior
+ else:
+ base = ','.join(entry_dn.split(",")[1:])
+ dn = "%s, %s" % (new_rdn, base)
+ myfilter = entry_dn.split(',')[0]
+
+ while attempt < 10:
+ try:
+ ent = topology.standalone.getEntry(dn, ldap.SCOPE_BASE, myfilter)
+ break
+ except ldap.NO_SUCH_OBJECT:
+ topology.standalone.log.info("Accept failure due to 47833: unable to
find (base) a modrdn entry")
+ attempt += 1
+ time.sleep(1)
+ if attempt == 10:
+ ent = topology.standalone.getEntry(base, ldap.SCOPE_SUBTREE, myfilter)
+ ent = topology.standalone.getEntry(dn, ldap.SCOPE_BASE, myfilter)
+
+
+def _48294_init(topology):
+ """
+ Set up Linked Attribute
+ """
+ _header(topology, 'Testing Ticket 48294 - Linked Attributes plug-in - won\'t
update links after MODRDN operation')
+
+ log.info('Enable Dynamic plugins, and the linked Attrs plugin')
+ try:
+ topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE,
'nsslapd-dynamic-plugins', 'on')])
+ except ldap.LDAPError as e:
+ ldap.fatal('Failed to enable dynamic plugin!' +
e.message['desc'])
+ assert False
+
+ try:
+ topology.standalone.plugins.enable(name=PLUGIN_LINKED_ATTRS)
+ except ValueError as e:
+ ldap.fatal('Failed to enable linked attributes plugin!' +
e.message['desc'])
+ assert False
+
+ log.info('Add the plugin config entry')
+ try:
+ topology.standalone.add_s(Entry((MANAGER_LINK, {
+ 'objectclass': 'top extensibleObject'.split(),
+ 'cn': 'Manager Link',
+ 'linkType': LINKTYPE,
+ 'managedType': MANAGEDTYPE
+ })))
+ except ldap.LDAPError as e:
+ log.fatal('Failed to add linked attr config entry: error ' +
e.message['desc'])
+ assert False
+
+ log.info('Add 2 entries: manager1 and employee1')
+ try:
+ topology.standalone.add_s(Entry(('uid=manager1,%s' % OU_PEOPLE, {
+ 'objectclass': 'top extensibleObject'.split(),
+ 'uid': 'manager1'})))
+ except ldap.LDAPError as e:
+ log.fatal('Add manager1 failed: error ' + e.message['desc'])
+ assert False
+
+ try:
+ topology.standalone.add_s(Entry(('uid=employee1,%s' % OU_PEOPLE, {
+ 'objectclass': 'top extensibleObject'.split(),
+ 'uid': 'employee1'})))
+ except ldap.LDAPError as e:
+ log.fatal('Add employee1 failed: error ' + e.message['desc'])
+ assert False
+
+ log.info('Add linktype to manager1')
+ topology.standalone.modify_s('uid=manager1,%s' % OU_PEOPLE,
+ [(ldap.MOD_ADD, LINKTYPE, 'uid=employee1,%s' %
OU_PEOPLE)])
+
+ log.info('Check managed attribute')
+ check_attr_val(topology, 'uid=employee1,%s' % OU_PEOPLE, MANAGEDTYPE,
'uid=manager1,%s' % OU_PEOPLE)
+
+ log.info('PASSED')
+
+
+def _48294_run_0(topology):
+ """
+ Rename employee1 to employee2 and adjust the value of directReport by replace
+ """
+ _header(topology, 'Case 0 - Rename employee1 and adjust the link type value by
replace')
+
+ log.info('Rename employee1 to employee2')
+ _modrdn_entry(topology, entry_dn='uid=employee1,%s' % OU_PEOPLE,
new_rdn='uid=employee2')
+
+ log.info('Modify the value of directReport to uid=employee2')
+ try:
+ topology.standalone.modify_s('uid=manager1,%s' % OU_PEOPLE,
+ [(ldap.MOD_REPLACE, LINKTYPE,
'uid=employee2,%s' % OU_PEOPLE)])
+ except ldap.LDAPError as e:
+ log.fatal('Failed to replace uid=employee1 with employee2: ' +
e.message['desc'])
+ assert False
+
+ log.info('Check managed attribute')
+ check_attr_val(topology, 'uid=employee2,%s' % OU_PEOPLE, MANAGEDTYPE,
'uid=manager1,%s' % OU_PEOPLE)
+
+ log.info('PASSED')
+
+
+def _48294_run_1(topology):
+ """
+ Rename employee2 to employee3 and adjust the value of directReport by delete and add
+ """
+ _header(topology, 'Case 1 - Rename employee2 and adjust the link type value by
delete and add')
+
+ log.info('Rename employee2 to employee3')
+ _modrdn_entry(topology, entry_dn='uid=employee2,%s' % OU_PEOPLE,
new_rdn='uid=employee3')
+
+ log.info('Modify the value of directReport to uid=employee3')
+ try:
+ topology.standalone.modify_s('uid=manager1,%s' % OU_PEOPLE,
+ [(ldap.MOD_DELETE, LINKTYPE,
'uid=employee2,%s' % OU_PEOPLE)])
+ except ldap.LDAPError as e:
+ log.fatal('Failed to delete employee2: ' + e.message['desc'])
+ assert False
+
+ try:
+ topology.standalone.modify_s('uid=manager1,%s' % OU_PEOPLE,
+ [(ldap.MOD_ADD, LINKTYPE, 'uid=employee3,%s'
% OU_PEOPLE)])
+ except ldap.LDAPError as e:
+ log.fatal('Failed to add employee3: ' + e.message['desc'])
+ assert False
+
+ log.info('Check managed attribute')
+ check_attr_val(topology, 'uid=employee3,%s' % OU_PEOPLE, MANAGEDTYPE,
'uid=manager1,%s' % OU_PEOPLE)
+
+ log.info('PASSED')
+
+
+def _48294_run_2(topology):
+ """
+ Rename manager1 to manager2 and make sure the managed attribute value is updated
+ """
+ _header(topology, 'Case 2 - Rename manager1 to manager2 and make sure the managed
attribute value is updated')
+
+ log.info('Rename manager1 to manager2')
+ _modrdn_entry(topology, entry_dn='uid=manager1,%s' % OU_PEOPLE,
new_rdn='uid=manager2')
+
+ log.info('Check managed attribute')
+ check_attr_val(topology, 'uid=employee3,%s' % OU_PEOPLE, MANAGEDTYPE,
'uid=manager2,%s' % OU_PEOPLE)
+
+ log.info('PASSED')
+
+
+def _48294_final(topology):
+ topology.standalone.delete()
+ log.info('All PASSED')
+
+
+def test_ticket48294(topology):
+ '''
+ run_isolated is used to run these test cases independently of a test scheduler
(xunit, py.test..)
+ To run isolated without py.test, you need to
+ - edit this file and comment '(a)pytest.fixture' line before
'topology' function.
+ - set the installation prefix
+ - run this program
+ '''
+ global installation_prefix
+ installation_prefix = None
+
+ _48294_init(topology)
+
+ _48294_run_0(topology)
+ _48294_run_1(topology)
+ _48294_run_2(topology)
+
+ _48294_final(topology)
+
+if __name__ == '__main__':
+ # Run isolated
+ # -s for DEBUG mode
+
+ CURRENT_FILE = os.path.realpath(__file__)
+ pytest.main("-s %s" % CURRENT_FILE)
commit 26a749a68e83b76cac2fbb5a031a36cd120bd800
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Dec 18 16:05:22 2015 -0800
Ticket #48294 - Linked Attributes plug-in - won't update links after MODRDN
operation
Description: When an entry is renamed and the DN is a value of linktype,
since the linktype value is under control by the user, the value needs to
be manually modified to adjust to the new DN.
But the modification failed in linked_attrs_mod_backpointers due to the
too tight error checking. This patch allows LDAP_NO_SUCH_OBJECT for the
deletion of the old DN and LDAP_TYPE_OR_VALUE_EXISTS for adding a managed
entry which exists prior to the modification.
https://fedorahosted.org/389/ticket/48294
Reviewed by mreynolds(a)redhat.com (Thank you, Mark!!)
diff --git a/ldap/servers/plugins/linkedattrs/linked_attrs.c
b/ldap/servers/plugins/linkedattrs/linked_attrs.c
index 5d1a77d..0d07a1f 100644
--- a/ldap/servers/plugins/linkedattrs/linked_attrs.c
+++ b/ldap/servers/plugins/linkedattrs/linked_attrs.c
@@ -1463,7 +1463,15 @@ linked_attrs_mod_backpointers(Slapi_PBlock *pb, char *linkdn, char
*type,
linked_attrs_get_plugin_id(), 0);
slapi_modify_internal_pb(mod_pb);
slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
- if(rc != LDAP_SUCCESS){
+ if (((LDAP_MOD_DELETE == modop) && (LDAP_NO_SUCH_OBJECT == rc)) ||
+ ((LDAP_MOD_ADD == modop) && (LDAP_TYPE_OR_VALUE_EXISTS == rc)))
{
+ /*
+ * We should ignore LDAP_NO_SUCH_OBJECT and LDAP_TYPE_OR_VALUE_EXISTS
+ * to support the case:
+ * target entry was renamed and the linktype value is being adjusted.
+ */
+ rc = LDAP_SUCCESS;
+ } else if (rc != LDAP_SUCCESS) {
char *err_msg = NULL;
err_msg = PR_smprintf("Linked Attrs Plugin: Failed to update "
commit 1076f51ae51d2bfe76b01d963a85c8275352d4d0
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Dec 18 12:21:49 2015 -0800
Ticket #48290 - No man page entry for - option '-u' of dbgen.pl for adding
group entries with uniquemembers
Description: Adding a missing option to the man page for dbgen.pl.
-u Add groups containing uniquemembers; generate a group for every
100 user entries created that contains the 100 members
https://fedorahosted.org/389/ticket/48290
Reviewed by mreynolds(a)redhat.com (Thank you, Mark!!)
diff --git a/man/man1/dbgen.pl.1 b/man/man1/dbgen.pl.1
index 6ef4d28..6f25080 100644
--- a/man/man1/dbgen.pl.1
+++ b/man/man1/dbgen.pl.1
@@ -71,6 +71,9 @@ Beginning number for RDN e.g. uid=1 (ending number is \-n value +
beginning numb
.TP
.B \-j number
0 pad numbers used in RDN to this many digits e.g. with 4 1 becomes 0001 (ignored unless
\-b number is specified)
+.TP
+.B \-u
+Add groups containing uniquemembers; generate a group for every 100 user entries created
that contains the 100 members
.br
.SH AUTHOR
dbgen.pl was written by the 389 Project.