dirsrvtests/suites/dynamic-plugins/plugin_tests.py | 486 ++++++++++---
dirsrvtests/suites/dynamic-plugins/stress_tests.py | 10
dirsrvtests/suites/dynamic-plugins/test_dynamic_plugins.py | 463 +++++++++---
dirsrvtests/tickets/ticket47560_test.py | 2
ldap/servers/plugins/acctpolicy/acct_config.c | 8
ldap/servers/plugins/acctpolicy/acct_init.c | 99 ++
ldap/servers/plugins/acctpolicy/acct_plugin.c | 178 ++++
ldap/servers/plugins/acctpolicy/acct_util.c | 19
ldap/servers/plugins/acctpolicy/acctpolicy.h | 25
ldap/servers/plugins/linkedattrs/fixup_task.c | 4
ldap/servers/plugins/memberof/memberof_config.c | 1
ldap/servers/slapd/dse.c | 2
ldap/servers/slapd/plugin.c | 45 -
ldap/servers/slapd/slapi-plugin.h | 6
ldap/servers/slapd/thread_data.c | 29
15 files changed, 1112 insertions(+), 265 deletions(-)
New commits:
commit 14e5422328d8f116916efb4a9e192b8db4686e44
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Tue Dec 23 21:40:00 2014 -0500
Ticket 47451 - Dynamic plugins - fixed thread synchronization
Description: Made various fixes and overall improvements to the dynamic
plugin feature,and Tthe CI test suite.
dirsrvtests/suites/dynamic-plugins/plugin_tests.py
dirsrvtests/suites/dynamic-plugins/stress_tests.py
dirsrvtests/suites/dynamic-plugins/test_dynamic_plugins.py
- Improved/intensified stress test
- Improved task monitoring
- Added a replication run to the entire test suite
- Added tests for "shared config areas": MO & RI
plugins
ldap/servers/plugins/acctpolicy/acct_config.c
ldap/servers/plugins/acctpolicy/acct_init.c
ldap/servers/plugins/acctpolicy/acct_plugin.c
ldap/servers/plugins/acctpolicy/acct_util.c
ldap/servers/plugins/acctpolicy/acctpolicy.h
- Added the necessary postop calls to check for config
updates
ldap/servers/plugins/linkedattrs/fixup_task.c
- Fixed logging issue
ldap/servers/plugins/memberof/memberof_config.c
- Fixed double free/crash
ldap/servers/slapd/dse.c
- The ADD entry was incorrectly being set to NULL(memory
leak)
ldap/servers/slapd/plugin.c
- Improved thread sychronization/fixed race condition
- Fixed memory leak when deleting plugin for the plugin config
area
ldap/servers/slapd/slapi-plugin.h
ldap/servers/slapd/thread_data.c
- Revised plugin lock thread data wrappers
https://fedorahosted.org/389/ticket/47451
Jenkins: Passed
Valgrind: Passed
Reviewed by: nhosoi(Thanks!)
diff --git a/dirsrvtests/suites/dynamic-plugins/plugin_tests.py
b/dirsrvtests/suites/dynamic-plugins/plugin_tests.py
index fa88145..e147be5 100644
--- a/dirsrvtests/suites/dynamic-plugins/plugin_tests.py
+++ b/dirsrvtests/suites/dynamic-plugins/plugin_tests.py
@@ -31,6 +31,7 @@ BRANCH2_DN = 'ou=branch2,' + DEFAULT_SUFFIX
GROUP_OU = 'ou=groups,' + DEFAULT_SUFFIX
PEOPLE_OU = 'ou=people,' + DEFAULT_SUFFIX
GROUP_DN = 'cn=group,' + DEFAULT_SUFFIX
+CONFIG_AREA = 'nsslapd-pluginConfigArea'
'''
Functional tests for each plugin
@@ -85,6 +86,35 @@ def test_dependency(inst, plugin):
################################################################################
#
+# Wait for task to complete
+#
+################################################################################
+def wait_for_task(conn, task_dn):
+ finished = False
+ count = 0
+ while count < 60:
+ try:
+ task_entry = conn.search_s(task_dn, ldap.SCOPE_BASE,
'objectclass=*')
+ if not task_entry:
+ log.fatal('wait_for_task: Search failed to find task: ' +
task_dn)
+ assert False
+ if task_entry[0].hasAttr('nstaskexitcode'):
+ # task is done
+ finished = True
+ break
+ except ldap.LDAPError, e:
+ log.fatal('wait_for_task: Search failed: ' +
e.message['desc'])
+ assert False
+
+ time.sleep(1)
+ count += 1
+ if not finished:
+ log.error('wait_for_task: Task (%s) did not complete!' % task_dn)
+ assert False
+
+
+################################################################################
+#
# Test Account Policy Plugin (0)
#
################################################################################
@@ -97,6 +127,7 @@ def test_acctpolicy(inst, args=None):
return True
CONFIG_DN = 'cn=config,cn=Account Policy Plugin,cn=plugins,cn=config'
+
log.info('Testing ' + PLUGIN_ACCT_POLICY + '...')
############################################################################
@@ -123,23 +154,12 @@ def test_acctpolicy(inst, args=None):
log.error('test_acctpolicy: Failed to add config entry: error ' +
e.message['desc'])
assert False
- # Now set the config entry in the plugin entry
- #try:
- # inst.modify_s('cn=' + PLUGIN_ACCT_POLICY +
',cn=plugins,cn=config',
- # [(ldap.MOD_REPLACE, 'nsslapd-pluginarg0', CONFIG_DN)])
- #except ldap.LDAPError, e:
- # log.error('test_acctpolicy: Failed to set config entry in plugin entry:
error ' + e.message['desc'])
- # assert False
-
############################################################################
# Test plugin
############################################################################
- # !!!! acctpolicy does have have a dse callabck to check for live updates - restart
plugin for now !!!!
- inst.plugins.disable(name=PLUGIN_ACCT_POLICY)
- inst.plugins.enable(name=PLUGIN_ACCT_POLICY)
-
# Add an entry
+ time.sleep(1)
try:
inst.add_s(Entry((USER1_DN, {'objectclass': "top
extensibleObject".split(),
'sn': '1',
@@ -154,10 +174,11 @@ def test_acctpolicy(inst, args=None):
try:
inst.simple_bind_s(USER1_DN, "password")
except ldap.LDAPError, e:
- log.error('test_acctpolicy:Failed to bind as user1: ' +
e.message['desc'])
+ log.error('test_acctpolicy: Failed to bind as user1: ' +
e.message['desc'])
assert False
# Bind as Root DN
+ time.sleep(1)
try:
inst.simple_bind_s(DN_DM, PASSWORD)
except ldap.LDAPError, e:
@@ -185,14 +206,11 @@ def test_acctpolicy(inst, args=None):
log.error('test_acctpolicy: Failed to modify config entry: error ' +
e.message['desc'])
assert False
- # !!!! must restart for now !!!!!
- inst.plugins.disable(name=PLUGIN_ACCT_POLICY)
- inst.plugins.enable(name=PLUGIN_ACCT_POLICY)
-
############################################################################
# Test plugin
############################################################################
+ time.sleep(1)
# login as user
try:
inst.simple_bind_s(USER1_DN, "password")
@@ -200,6 +218,7 @@ def test_acctpolicy(inst, args=None):
log.error('test_acctpolicy: Failed to bind(2nd) as user1: ' +
e.message['desc'])
assert False
+ time.sleep(1)
# Bind as Root DN
try:
inst.simple_bind_s(DN_DM, PASSWORD)
@@ -498,7 +517,7 @@ def test_automember(inst, args=None):
log.error('test_automember: Failed to user3 to branch2: error ' +
e.message['desc'])
assert False
- # Check the group - uniquemember sahould not exist
+ # Check the group - uniquemember should not exist
try:
entries = inst.search_s(GROUP_DN, ldap.SCOPE_BASE,
'(uniquemember=' + BUSER3_DN + ')')
@@ -512,9 +531,10 @@ def test_automember(inst, args=None):
# Enable plugin
inst.plugins.enable(name=PLUGIN_AUTOMEMBER)
+ TASK_DN = 'cn=task-' + str(int(time.time())) + ',cn=automember rebuild
membership,cn=tasks,cn=config'
# Add the task
try:
- inst.add_s(Entry(('cn=task-' + str(int(time.time())) +
',cn=automember rebuild membership,cn=tasks,cn=config', {
+ inst.add_s(Entry((TASK_DN, {
'objectclass': 'top extensibleObject'.split(),
'basedn': 'ou=branch2,' + DEFAULT_SUFFIX,
'filter': 'objectclass=top'})))
@@ -522,7 +542,7 @@ def test_automember(inst, args=None):
log.error('test_automember: Failed to add task: error ' +
e.message['desc'])
assert False
- time.sleep(3) # Wait for the task to do its work
+ wait_for_task(inst, TASK_DN)
# Verify the fixup task worked
try:
@@ -722,7 +742,7 @@ def test_dna(inst, args=None):
try:
inst.delete_s(USER1_DN)
except ldap.LDAPError, e:
- log.error('test_automember: Failed to delete test entry1: ' +
e.message['desc'])
+ log.error('test_dna: Failed to delete test entry1: ' +
e.message['desc'])
assert False
inst.plugins.disable(name=PLUGIN_DNA)
@@ -914,32 +934,11 @@ def test_linkedattrs(inst, args=None):
log.fatal('test_linkedattrs: Search for user1 failed: ' +
e.message['desc'])
assert False
- # Verify that the task does not work yet(not until we enable the plugin)
- try:
- inst.add_s(Entry(('cn=task-' + str(int(time.time())) + ',cn=fixup
linked attributes,cn=tasks,cn=config', {
- 'objectclass': 'top extensibleObject'.split(),
- 'basedn': DEFAULT_SUFFIX,
- 'filter': '(objectclass=top)'})))
- except ldap.LDAPError, e:
- log.error('test_linkedattrs: Failed to add task: error ' +
e.message['desc'])
- assert False
-
- time.sleep(3) # Wait for the task to do, or not do, its work
-
- # The entry should still not have a manager attribute
- try:
- entries = inst.search_s(USER2_DN, ldap.SCOPE_BASE, '(manager=*)')
- if entries:
- log.fatal('test_linkedattrs: user2 incorrectly has a "manager"
attr')
- assert False
- except ldap.LDAPError, e:
- log.fatal('test_linkedattrs: Search for user2 failed: ' +
e.message['desc'])
- assert False
-
# Enable the plugin and rerun the task entry
inst.plugins.enable(name=PLUGIN_LINKED_ATTRS)
# Add the task again
+ TASK_DN = 'cn=task-' + str(int(time.time())) + ',cn=fixup linked
attributes,cn=tasks,cn=config'
try:
inst.add_s(Entry(('cn=task-' + str(int(time.time())) + ',cn=fixup
linked attributes,cn=tasks,cn=config', {
'objectclass': 'top extensibleObject'.split(),
@@ -949,7 +948,7 @@ def test_linkedattrs(inst, args=None):
log.error('test_linkedattrs: Failed to add task: error ' +
e.message['desc'])
assert False
- time.sleep(3) # Wait for the task to do its work
+ wait_for_task(inst, TASK_DN)
# Check if user2 now has a manager attribute now
try:
@@ -1011,6 +1010,7 @@ def test_memberof(inst, args=None):
return
PLUGIN_DN = 'cn=' + PLUGIN_MEMBER_OF + ',cn=plugins,cn=config'
+ SHARED_CONFIG_DN = 'cn=memberOf Config,' + DEFAULT_SUFFIX
log.info('Testing ' + PLUGIN_MEMBER_OF + '...')
@@ -1048,6 +1048,16 @@ def test_memberof(inst, args=None):
log.error('test_memberof: Failed to add group: error ' +
e.message['desc'])
assert False
+ try:
+ inst.add_s(Entry((SHARED_CONFIG_DN, {
+ 'objectclass': 'top extensibleObject'.split(),
+ 'memberofgroupattr': 'member',
+ 'memberofattr': 'memberof'
+ })))
+ except ldap.LDAPError, e:
+ log.error('test_memberof: Failed to shared config entry: error ' +
e.message['desc'])
+ assert False
+
# Check if the user now has a "memberOf" attribute
try:
entries = inst.search_s(USER1_DN, ldap.SCOPE_BASE, '(memberOf=*)')
@@ -1069,7 +1079,7 @@ def test_memberof(inst, args=None):
try:
entries = inst.search_s(USER1_DN, ldap.SCOPE_BASE, '(memberOf=*)')
if entries:
- log.fatal('test_memberof: user1 incorrect has memberOf attr')
+ log.fatal('test_memberof: user1 incorrectly has memberOf attr')
assert False
except ldap.LDAPError, e:
log.fatal('test_memberof: Search for user1 failed: ' +
e.message['desc'])
@@ -1116,51 +1126,169 @@ def test_memberof(inst, args=None):
try:
entries = inst.search_s(USER1_DN, ldap.SCOPE_BASE, '(memberOf=*)')
if entries:
- log.fatal('test_memberof: user1 incorrect has memberOf attr')
+ log.fatal('test_memberof: user1 incorrectly has memberOf attr')
assert False
except ldap.LDAPError, e:
log.fatal('test_memberof: Search for user1 failed: ' +
e.message['desc'])
assert False
############################################################################
- # Test Fixup Task
+ # Set the shared config entry and test the plugin
############################################################################
- inst.plugins.disable(name=PLUGIN_MEMBER_OF)
+ # The shared config entry uses "member" - the above test uses
"uniquemember"
+ try:
+ inst.modify_s(PLUGIN_DN, [(ldap.MOD_REPLACE, CONFIG_AREA, SHARED_CONFIG_DN)])
+ except ldap.LDAPError, e:
+ log.error('test_memberof: Failed to set plugin area: error ' +
e.message['desc'])
+ assert False
+
+ # Delete the test entries then readd them to start with a clean slate
+ try:
+ inst.delete_s(USER1_DN)
+ except ldap.LDAPError, e:
+ log.error('test_memberof: Failed to delete test entry1: ' +
e.message['desc'])
+ assert False
+
+ try:
+ inst.delete_s(GROUP_DN)
+ except ldap.LDAPError, e:
+ log.error('test_memberof: Failed to delete test group: ' +
e.message['desc'])
+ assert False
+
+ try:
+ inst.add_s(Entry((USER1_DN, {
+ 'objectclass': 'top extensibleObject'.split(),
+ 'uid': 'user1'
+ })))
+ except ldap.LDAPError, e:
+ log.error('test_memberof: Failed to add user1: error ' +
e.message['desc'])
+ assert False
+
+ try:
+ inst.add_s(Entry((GROUP_DN, {
+ 'objectclass': 'top groupOfNames groupOfUniqueNames
extensibleObject'.split(),
+ 'cn': 'group',
+ 'member': USER1_DN
+ })))
+ except ldap.LDAPError, e:
+ log.error('test_memberof: Failed to add group: error ' +
e.message['desc'])
+ assert False
+
+ # Test the shared config
+ # Check if the user now has a "memberOf" attribute
+ try:
+ entries = inst.search_s(USER1_DN, ldap.SCOPE_BASE, '(memberOf=*)')
+ if not entries:
+ log.fatal('test_memberof: user1 missing memberOf')
+ assert False
+ except ldap.LDAPError, e:
+ log.fatal('test_memberof: Search for user1 failed: ' +
e.message['desc'])
+ assert False
+
+ # Remove "member" should remove "memberOf" from the entry
+ try:
+ inst.modify_s(GROUP_DN, [(ldap.MOD_DELETE, 'member', None)])
+ except ldap.LDAPError, e:
+ log.error('test_memberof: Failed to delete member: error ' +
e.message['desc'])
+ assert False
+
+ # Check that "memberOf" was removed
+ try:
+ entries = inst.search_s(USER1_DN, ldap.SCOPE_BASE, '(memberOf=*)')
+ if entries:
+ log.fatal('test_memberof: user1 incorrectly has memberOf attr')
+ assert False
+ except ldap.LDAPError, e:
+ log.fatal('test_memberof: Search for user1 failed: ' +
e.message['desc'])
+ assert False
+
+ ############################################################################
+ # Change the shared config entry to use 'uniquemember' and test the plugin
+ ############################################################################
+
+ try:
+ inst.modify_s(SHARED_CONFIG_DN, [(ldap.MOD_REPLACE, 'memberofgroupattr',
'uniquemember')])
+ except ldap.LDAPError, e:
+ log.error('test_memberof: Failed to set shared plugin entry(uniquemember):
error '
+ + e.message['desc'])
+ assert False
- # Add uniquemember, should not update USER1
try:
inst.modify_s(GROUP_DN, [(ldap.MOD_REPLACE, 'uniquemember', USER1_DN)])
except ldap.LDAPError, e:
log.error('test_memberof: Failed to add uniquemember: error ' +
e.message['desc'])
assert False
- # Check for "memberOf"
+ # Check if the user now has a "memberOf" attribute
+ try:
+ entries = inst.search_s(USER1_DN, ldap.SCOPE_BASE, '(memberOf=*)')
+ if not entries:
+ log.fatal('test_memberof: user1 missing memberOf')
+ assert False
+ except ldap.LDAPError, e:
+ log.fatal('test_memberof: Search for user1 failed: ' +
e.message['desc'])
+ assert False
+
+ # Remove "uniquemember" should remove "memberOf" from the entry
+ try:
+ inst.modify_s(GROUP_DN, [(ldap.MOD_DELETE, 'uniquemember', None)])
+ except ldap.LDAPError, e:
+ log.error('test_memberof: Failed to delete member: error ' +
e.message['desc'])
+ assert False
+
+ # Check that "memberOf" was removed
try:
entries = inst.search_s(USER1_DN, ldap.SCOPE_BASE, '(memberOf=*)')
if entries:
- log.fatal('test_memberof: user1 incorrect has memberOf attr')
+ log.fatal('test_memberof: user1 incorrectly has memberOf attr')
assert False
except ldap.LDAPError, e:
log.fatal('test_memberof: Search for user1 failed: ' +
e.message['desc'])
assert False
- # Run fixup task while plugin disabled - should not add "memberOf
- # Verify that the task does not work yet(not until we enable the plugin)
+ ############################################################################
+ # Remove shared config from plugin, and retest
+ ############################################################################
+
+ # First change the plugin to use member before we move the shared config that uses
uniquemember
try:
- inst.add_s(Entry(('cn=task-' + str(int(time.time())) + ',' +
DN_MBO_TASK, {
- 'objectclass': 'top extensibleObject'.split(),
- 'basedn': DEFAULT_SUFFIX,
- 'filter': 'objectclass=top'})))
- except ldap.NO_SUCH_OBJECT:
- pass
+ inst.modify_s(PLUGIN_DN, [(ldap.MOD_REPLACE, 'memberofgroupattr',
'member')])
except ldap.LDAPError, e:
- log.error('test_memberof: Failed to add task: error ' +
e.message['desc'])
+ log.error('test_memberof: Failed to update config(uniquemember): error '
+ e.message['desc'])
assert False
- time.sleep(3) # Wait for the task to do, or not do, its work
+ # Remove shared config from plugin
+ try:
+ inst.modify_s(PLUGIN_DN, [(ldap.MOD_DELETE, CONFIG_AREA, None)])
+ except ldap.LDAPError, e:
+ log.error('test_memberof: Failed to add uniquemember: error ' +
e.message['desc'])
+ assert False
- # Check for "memberOf"
+ try:
+ inst.modify_s(GROUP_DN, [(ldap.MOD_REPLACE, 'member', USER1_DN)])
+ except ldap.LDAPError, e:
+ log.error('test_memberof: Failed to add uniquemember: error ' +
e.message['desc'])
+ assert False
+
+ # Check if the user now has a "memberOf" attribute
+ try:
+ entries = inst.search_s(USER1_DN, ldap.SCOPE_BASE, '(memberOf=*)')
+ if not entries:
+ log.fatal('test_memberof: user1 missing memberOf')
+ assert False
+ except ldap.LDAPError, e:
+ log.fatal('test_memberof: Search for user1 failed: ' +
e.message['desc'])
+ assert False
+
+ # Remove "uniquemember" should remove "memberOf" from the entry
+ try:
+ inst.modify_s(GROUP_DN, [(ldap.MOD_DELETE, 'member', None)])
+ except ldap.LDAPError, e:
+ log.error('test_memberof: Failed to delete member: error ' +
e.message['desc'])
+ assert False
+
+ # Check that "memberOf" was removed
try:
entries = inst.search_s(USER1_DN, ldap.SCOPE_BASE, '(memberOf=*)')
if entries:
@@ -1170,11 +1298,42 @@ def test_memberof(inst, args=None):
log.fatal('test_memberof: Search for user1 failed: ' +
e.message['desc'])
assert False
+ ############################################################################
+ # Test Fixup Task
+ ############################################################################
+
+ inst.plugins.disable(name=PLUGIN_MEMBER_OF)
+
+ # First change the plugin to use uniquemember
+ try:
+ inst.modify_s(PLUGIN_DN, [(ldap.MOD_REPLACE, 'memberofgroupattr',
'uniquemember')])
+ except ldap.LDAPError, e:
+ log.error('test_memberof: Failed to update config(uniquemember): error '
+ e.message['desc'])
+ assert False
+
+ # Add uniquemember, should not update USER1
+ try:
+ inst.modify_s(GROUP_DN, [(ldap.MOD_REPLACE, 'uniquemember', USER1_DN)])
+ except ldap.LDAPError, e:
+ log.error('test_memberof: Failed to add uniquemember: error ' +
e.message['desc'])
+ assert False
+
+ # Check for "memberOf"
+ try:
+ entries = inst.search_s(USER1_DN, ldap.SCOPE_BASE, '(memberOf=*)')
+ if entries:
+ log.fatal('test_memberof: user1 incorrect has memberOf attr')
+ assert False
+ except ldap.LDAPError, e:
+ log.fatal('test_memberof: Search for user1 failed: ' +
e.message['desc'])
+ assert False
+
# Enable the plugin, and run the task
inst.plugins.enable(name=PLUGIN_MEMBER_OF)
+ TASK_DN = 'cn=task-' + str(int(time.time())) + ',' + DN_MBO_TASK
try:
- inst.add_s(Entry(('cn=task-' + str(int(time.time())) + ',' +
DN_MBO_TASK, {
+ inst.add_s(Entry((TASK_DN, {
'objectclass': 'top extensibleObject'.split(),
'basedn': DEFAULT_SUFFIX,
'filter': 'objectclass=top'})))
@@ -1182,7 +1341,7 @@ def test_memberof(inst, args=None):
log.error('test_memberof: Failed to add task: error ' +
e.message['desc'])
assert False
- time.sleep(3) # Wait for the task to do its work
+ wait_for_task(inst, TASK_DN)
# Check for "memberOf"
try:
@@ -1216,6 +1375,12 @@ def test_memberof(inst, args=None):
log.error('test_memberof: Failed to delete test group: ' +
e.message['desc'])
assert False
+ try:
+ inst.delete_s(SHARED_CONFIG_DN)
+ except ldap.LDAPError, e:
+ log.error('test_memberof: Failed to delete shared config entry: ' +
e.message['desc'])
+ assert False
+
############################################################################
# Test passed
############################################################################
@@ -1286,9 +1451,6 @@ def test_mep(inst, args=None):
log.error('test_mep: Failed to add template entry: error ' +
e.message['desc'])
assert False
- # log.info('geb.....')
- # time.sleep(30)
-
# Add the config entry
try:
inst.add_s(Entry((CONFIG_DN, {
@@ -1456,19 +1618,10 @@ def test_passthru(inst, args=None):
# Create second instance
passthru_inst = DirSrv(verbose=False)
- #if installation1_prefix:
- # args_instance[SER_DEPLOYED_DIR] = installation1_prefix
-
- # Args for the master1 instance
- """
- args_instance[SER_HOST] = '127.0.0.1'
- args_instance[SER_PORT] = '33333'
- args_instance[SER_SERVERID_PROP] = 'passthru'
- """
- args_instance[SER_HOST] = 'localhost.localdomain'
+ # Args for the instance
+ args_instance[SER_HOST] = LOCALHOST
args_instance[SER_PORT] = 33333
args_instance[SER_SERVERID_PROP] = 'passthru'
-
args_instance[SER_CREATION_SUFFIX] = PASS_SUFFIX1
args_passthru_inst = args_instance.copy()
passthru_inst.allocate(args_passthru_inst)
@@ -1615,6 +1768,7 @@ def test_referint(inst, args=None):
log.info('Testing ' + PLUGIN_REFER_INTEGRITY + '...')
PLUGIN_DN = 'cn=' + PLUGIN_REFER_INTEGRITY + ',cn=plugins,cn=config'
+ SHARED_CONFIG_DN = 'cn=RI Config,' + DEFAULT_SUFFIX
############################################################################
# Configure plugin
@@ -1660,6 +1814,28 @@ def test_referint(inst, args=None):
log.error('test_referint: Failed to add group: error ' +
e.message['desc'])
assert False
+ # Grab the referint log file from the plugin
+
+ try:
+ entries = inst.search_s(PLUGIN_DN, ldap.SCOPE_BASE, '(objectclass=top)')
+ REFERINT_LOGFILE = entries[0].getValue('referint-logfile')
+ except ldap.LDAPError, e:
+ log.fatal('test_referint: Unable to search plugin entry: ' +
e.message['desc'])
+ assert False
+
+ # Add shared config entry
+ try:
+ inst.add_s(Entry((SHARED_CONFIG_DN, {
+ 'objectclass': 'top extensibleObject'.split(),
+ 'referint-membership-attr': 'member',
+ 'referint-update-delay': '0',
+ 'referint-logfile': REFERINT_LOGFILE,
+ 'referint-logchanges': '0'
+ })))
+ except ldap.LDAPError, e:
+ log.error('test_referint: Failed to shared config entry: error ' +
e.message['desc'])
+ assert False
+
# Delete a user
try:
inst.delete_s(USER1_DN)
@@ -1709,6 +1885,150 @@ def test_referint(inst, args=None):
assert False
############################################################################
+ # Set the shared config entry and test the plugin
+ ############################################################################
+
+ # The shared config entry uses "member" - the above test used
"uniquemember"
+ try:
+ inst.modify_s(PLUGIN_DN, [(ldap.MOD_REPLACE, CONFIG_AREA, SHARED_CONFIG_DN)])
+ except ldap.LDAPError, e:
+ log.error('test_referint: Failed to set plugin area: error ' +
e.message['desc'])
+ assert False
+
+ # Delete the group, and readd everything
+ try:
+ inst.delete_s(GROUP_DN)
+ except ldap.LDAPError, e:
+ log.error('test_referint: Failed to delete group: ' +
e.message['desc'])
+ assert False
+
+ try:
+ inst.add_s(Entry((USER1_DN, {
+ 'objectclass': 'top extensibleObject'.split(),
+ 'uid': 'user1'
+ })))
+ except ldap.LDAPError, e:
+ log.error('test_referint: Failed to add user1: error ' +
e.message['desc'])
+ assert False
+
+ try:
+ inst.add_s(Entry((USER2_DN, {
+ 'objectclass': 'top extensibleObject'.split(),
+ 'uid': 'user2'
+ })))
+ except ldap.LDAPError, e:
+ log.error('test_referint: Failed to add user2: error ' +
e.message['desc'])
+ assert False
+
+ try:
+ inst.add_s(Entry((GROUP_DN, {
+ 'objectclass': 'top extensibleObject'.split(),
+ 'cn': 'group',
+ 'member': USER1_DN,
+ 'uniquemember': USER2_DN
+ })))
+ except ldap.LDAPError, e:
+ log.error('test_referint: Failed to add group: error ' +
e.message['desc'])
+ assert False
+
+ # Delete a user
+ try:
+ inst.delete_s(USER1_DN)
+ except ldap.LDAPError, e:
+ log.error('test_referint: Failed to delete user1: ' +
e.message['desc'])
+ assert False
+
+ # Check for integrity
+ try:
+ entry = inst.search_s(GROUP_DN, ldap.SCOPE_BASE, '(member=' + USER1_DN +
')')
+ if entry:
+ log.error('test_referint: user1 was not removed from group')
+ assert False
+ except ldap.LDAPError, e:
+ log.fatal('test_referint: Unable to search group: ' +
e.message['desc'])
+ assert False
+
+ ############################################################################
+ # Change the shared config entry to use 'uniquemember' and test the plugin
+ ############################################################################
+
+ try:
+ inst.modify_s(SHARED_CONFIG_DN, [(ldap.MOD_REPLACE,
'referint-membership-attr', 'uniquemember')])
+ except ldap.LDAPError, e:
+ log.error('test_referint: Failed to set shared plugin entry(uniquemember):
error '
+ + e.message['desc'])
+ assert False
+
+ # Delete a user
+ try:
+ inst.delete_s(USER2_DN)
+ except ldap.LDAPError, e:
+ log.error('test_referint: Failed to delete user1: ' +
e.message['desc'])
+ assert False
+
+ # Check for integrity
+ try:
+ entry = inst.search_s(GROUP_DN, ldap.SCOPE_BASE, '(uniquemember=' +
USER2_DN + ')')
+ if entry:
+ log.error('test_referint: user2 was not removed from group')
+ assert False
+ except ldap.LDAPError, e:
+ log.fatal('test_referint: Unable to search group: ' +
e.message['desc'])
+ assert False
+
+ ############################################################################
+ # Remove shared config from plugin, and retest
+ ############################################################################
+
+ # First change the plugin to use member before we move the shared config that uses
uniquemember
+ try:
+ inst.modify_s(PLUGIN_DN, [(ldap.MOD_REPLACE, 'referint-membership-attr',
'member')])
+ except ldap.LDAPError, e:
+ log.error('test_referint: Failed to update config(uniquemember): error '
+ e.message['desc'])
+ assert False
+
+ # Remove shared config from plugin
+ try:
+ inst.modify_s(PLUGIN_DN, [(ldap.MOD_DELETE, CONFIG_AREA, None)])
+ except ldap.LDAPError, e:
+ log.error('test_referint: Failed to add uniquemember: error ' +
e.message['desc'])
+ assert False
+
+ # Add test user
+ try:
+ inst.add_s(Entry((USER1_DN, {
+ 'objectclass': 'top extensibleObject'.split(),
+ 'uid': 'user1'
+ })))
+ except ldap.LDAPError, e:
+ log.error('test_referint: Failed to add user1: error ' +
e.message['desc'])
+ assert False
+
+ # Add user to group
+ try:
+ inst.modify_s(GROUP_DN, [(ldap.MOD_REPLACE, 'member', USER1_DN)])
+ except ldap.LDAPError, e:
+ log.error('test_referint: Failed to add uniquemember: error ' +
e.message['desc'])
+ assert False
+
+ # Delete a user
+ try:
+ inst.delete_s(USER1_DN)
+ except ldap.LDAPError, e:
+ log.error('test_referint: Failed to delete user1: ' +
e.message['desc'])
+ assert False
+
+ # Check for integrity
+ try:
+ entry = inst.search_s(GROUP_DN, ldap.SCOPE_BASE, '(member=' + USER1_DN +
')')
+ if entry:
+ log.error('test_referint: user1 was not removed from group')
+ assert False
+ except ldap.LDAPError, e:
+ log.fatal('test_referint: Unable to search group: ' +
e.message['desc'])
+ assert False
+
+ ############################################################################
# Test plugin dependency
############################################################################
@@ -1721,7 +2041,13 @@ def test_referint(inst, args=None):
try:
inst.delete_s(GROUP_DN)
except ldap.LDAPError, e:
- log.error('test_referint: Failed to delete user1: ' +
e.message['desc'])
+ log.error('test_referint: Failed to delete group: ' +
e.message['desc'])
+ assert False
+
+ try:
+ inst.delete_s(SHARED_CONFIG_DN)
+ except ldap.LDAPError, e:
+ log.error('test_referint: Failed to delete shared config entry: ' +
e.message['desc'])
assert False
############################################################################
@@ -1863,7 +2189,7 @@ def test_rootdn(inst, args=None):
'userpassword': 'password'
})))
except ldap.LDAPError, e:
- log.error('test_retrocl: Failed to add user1: error ' +
e.message['desc'])
+ log.error('test_rootdn: Failed to add user1: error ' +
e.message['desc'])
assert False
# Set an aci so we can modify the plugin after ew deny the root dn
diff --git a/dirsrvtests/suites/dynamic-plugins/stress_tests.py
b/dirsrvtests/suites/dynamic-plugins/stress_tests.py
index a1f666d..f1a34b4 100644
--- a/dirsrvtests/suites/dynamic-plugins/stress_tests.py
+++ b/dirsrvtests/suites/dynamic-plugins/stress_tests.py
@@ -21,6 +21,7 @@ from constants import *
log = logging.getLogger(__name__)
NUM_USERS = 250
+GROUP_DN = 'cn=stress-group,' + DEFAULT_SUFFIX
def openConnection(inst):
@@ -58,6 +59,14 @@ def configureMO(inst):
assert False
+def cleanup(conn):
+ try:
+ conn.delete_s(GROUP_DN)
+ except ldap.LDAPError, e:
+ log.error('cleanup: failed to delete group (' + GROUP_DN + ') error:
' + e.message['desc'])
+ assert False
+
+
class DelUsers(threading.Thread):
def __init__(self, inst, rdnval):
threading.Thread.__init__(self)
@@ -97,7 +106,6 @@ class AddUsers(threading.Thread):
idx = 0
if self.addToGroup:
- GROUP_DN = 'cn=stress-group,' + DEFAULT_SUFFIX
try:
conn.add_s(Entry((GROUP_DN,
{'objectclass': 'top groupOfNames groupOfUniqueNames
extensibleObject'.split(),
diff --git a/dirsrvtests/suites/dynamic-plugins/test_dynamic_plugins.py
b/dirsrvtests/suites/dynamic-plugins/test_dynamic_plugins.py
index 3677fd5..288505b 100644
--- a/dirsrvtests/suites/dynamic-plugins/test_dynamic_plugins.py
+++ b/dirsrvtests/suites/dynamic-plugins/test_dynamic_plugins.py
@@ -31,6 +31,12 @@ class TopologyStandalone(object):
self.standalone = standalone
+def repl_fail(replica):
+ # remove replica instance, and assert failure
+ replica.delete()
+ assert False
+
+
@pytest.fixture(scope="module")
def topology(request):
'''
@@ -128,7 +134,10 @@ def test_dynamic_plugins(topology):
Test Dynamic Plugins - exercise each plugin and its main features, while
changing the configuration without restarting the server.
- Need to test: functionality, stability, and stress.
+ Need to test: functionality, stability, and stress. These tests need to run
+ with replication disabled, and with replication setup with a
+ second instance. Then test if replication is working, and we have
+ same entries on each side.
Functionality - Make sure that as configuration changes are made they take
effect immediately. Cross plugin interaction (e.g.
automember/memberOf)
@@ -137,17 +146,21 @@ def test_dynamic_plugins(topology):
Memory Corruption - Restart the plugins many times, and in different orders and
test
functionality, and stability. This will excerise the
internal
- plugin linked lists, dse callabcks, and task handlers.
+ plugin linked lists, dse callbacks, and task handlers.
- Stress - Put the server under some type of load that is using a particular
- plugin for each operation, and then make changes to that plugin.
- The new changes should take effect, and the server should not crash.
+ Stress - Put the server under load that will trigger multiple plugins(MO, RI,
DNA, etc)
+ Restart various plugins while these operations are going on. Perform
this test
+ 5 times(stress_max_run).
"""
- ############################################################################
- # Test plugin functionality
- ############################################################################
+ REPLICA_PORT = 33334
+ RUV_FILTER =
'(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))'
+ master_maxcsn = 0
+ replica_maxcsn = 0
+ msg = ' (no replication)'
+ replication_run = False
+ stress_max_runs = 5
# First enable dynamic plugins
try:
@@ -156,132 +169,337 @@ def test_dynamic_plugins(topology):
ldap.error('Failed to enable dynamic plugin!' +
e.message['desc'])
assert False
- log.info('#####################################################')
- log.info('Testing Dynamic Plugins Functionality...')
- log.info('#####################################################\n')
-
- plugin_tests.test_all_plugins(topology.standalone)
-
- log.info('#####################################################')
- log.info('Successfully Tested Dynamic Plugins Functionality.')
- log.info('#####################################################\n')
-
- ############################################################################
- # Test the stability by exercising the internal lists, callabcks, and task handlers
- ############################################################################
-
- log.info('#####################################################')
- log.info('Testing Dynamic Plugins for Memory Corruption...')
- log.info('#####################################################\n')
- prev_plugin_test = None
- prev_prev_plugin_test = None
- for plugin_test in plugin_tests.func_tests:
+ while 1:
#
- # Restart the plugin several times (and prev plugins) - work that linked list
+ # First run the tests with replication disabled, then rerun them with replication
set up
#
- plugin_test(topology.standalone, "restart")
- if prev_prev_plugin_test:
- prev_prev_plugin_test(topology.standalone, "restart")
+ ############################################################################
+ # Test plugin functionality
+ ############################################################################
+
+
log.info('####################################################################')
+ log.info('Testing Dynamic Plugins Functionality' + msg + '...')
+
log.info('####################################################################\n')
+
+ plugin_tests.test_all_plugins(topology.standalone)
+
+
log.info('####################################################################')
+ log.info('Successfully Tested Dynamic Plugins Functionality' + msg +
'.')
+
log.info('####################################################################\n')
+
+ ############################################################################
+ # Test the stability by exercising the internal lists, callabcks, and task
handlers
+ ############################################################################
+
+
log.info('####################################################################')
+ log.info('Testing Dynamic Plugins for Memory Corruption' + msg +
'...')
+
log.info('####################################################################\n')
+ prev_plugin_test = None
+ prev_prev_plugin_test = None
+
+ for plugin_test in plugin_tests.func_tests:
+ #
+ # Restart the plugin several times (and prev plugins) - work that linked
list
+ #
+ plugin_test(topology.standalone, "restart")
+
+ if prev_prev_plugin_test:
+ prev_prev_plugin_test(topology.standalone, "restart")
+
+ plugin_test(topology.standalone, "restart")
+
+ if prev_plugin_test:
+ prev_plugin_test(topology.standalone, "restart")
+
+ plugin_test(topology.standalone, "restart")
+
+ # Now run the functional test
+ plugin_test(topology.standalone)
+
+ # Set the previous tests
+ if prev_plugin_test:
+ prev_prev_plugin_test = prev_plugin_test
+ prev_plugin_test = plugin_test
+
+
log.info('####################################################################')
+ log.info('Successfully Tested Dynamic Plugins for Memory Corruption' +
msg + '.')
+
log.info('####################################################################\n')
+
+ ############################################################################
+ # Stress two plugins while restarting it, and while restarting other plugins.
+ # The goal is to not crash, and have the plugins work after stressing them.
+ ############################################################################
+
+
log.info('####################################################################')
+ log.info('Stressing Dynamic Plugins' + msg + '...')
+
log.info('####################################################################\n')
+
+ stress_tests.configureMO(topology.standalone)
+ stress_tests.configureRI(topology.standalone)
+
+ stress_count = 0
+ while stress_count < stress_max_runs:
+
log.info('####################################################################')
+ log.info('Running stress test' + msg + '. Run (%d/%d)...' %
(stress_count + 1, stress_max_runs))
+
log.info('####################################################################\n')
+
+ try:
+ # Launch three new threads to add a bunch of users
+ add_users = stress_tests.AddUsers(topology.standalone,
'employee', True)
+ add_users.start()
+ add_users2 = stress_tests.AddUsers(topology.standalone, 'entry',
True)
+ add_users2.start()
+ add_users3 = stress_tests.AddUsers(topology.standalone, 'person',
True)
+ add_users3.start()
+ time.sleep(1)
+
+ # While we are adding users restart the MO plugin and an idle plugin
+ topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
+ topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
+ time.sleep(1)
+ topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
+ time.sleep(1)
+ topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
+ topology.standalone.plugins.disable(name=PLUGIN_LINKED_ATTRS)
+ topology.standalone.plugins.enable(name=PLUGIN_LINKED_ATTRS)
+ time.sleep(1)
+ topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
+ topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
+ time.sleep(2)
+ topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
+ time.sleep(1)
+ topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
+ topology.standalone.plugins.disable(name=PLUGIN_LINKED_ATTRS)
+ topology.standalone.plugins.enable(name=PLUGIN_LINKED_ATTRS)
+ topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
+ time.sleep(1)
+ topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
+ topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
+ topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
+
+ # Wait for the 'adding' threads to complete
+ add_users.join()
+ add_users2.join()
+ add_users3.join()
+
+ # Now launch three threads to delete the users
+ del_users = stress_tests.DelUsers(topology.standalone,
'employee')
+ del_users.start()
+ del_users2 = stress_tests.DelUsers(topology.standalone, 'entry')
+ del_users2.start()
+ del_users3 = stress_tests.DelUsers(topology.standalone,
'person')
+ del_users3.start()
+ time.sleep(1)
+
+ # Restart both the MO, RI plugins during these deletes, and an idle
plugin
+ topology.standalone.plugins.disable(name=PLUGIN_REFER_INTEGRITY)
+ topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
+ topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
+ topology.standalone.plugins.enable(name=PLUGIN_REFER_INTEGRITY)
+ time.sleep(1)
+ topology.standalone.plugins.disable(name=PLUGIN_REFER_INTEGRITY)
+ time.sleep(1)
+ topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
+ time.sleep(1)
+ topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
+ time.sleep(1)
+ topology.standalone.plugins.enable(name=PLUGIN_REFER_INTEGRITY)
+ topology.standalone.plugins.disable(name=PLUGIN_LINKED_ATTRS)
+ topology.standalone.plugins.enable(name=PLUGIN_LINKED_ATTRS)
+ topology.standalone.plugins.disable(name=PLUGIN_REFER_INTEGRITY)
+ topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
+ topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
+ topology.standalone.plugins.enable(name=PLUGIN_REFER_INTEGRITY)
+ time.sleep(2)
+ topology.standalone.plugins.disable(name=PLUGIN_REFER_INTEGRITY)
+ time.sleep(1)
+ topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
+ time.sleep(1)
+ topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
+ time.sleep(1)
+ topology.standalone.plugins.enable(name=PLUGIN_REFER_INTEGRITY)
+ topology.standalone.plugins.disable(name=PLUGIN_LINKED_ATTRS)
+ topology.standalone.plugins.enable(name=PLUGIN_LINKED_ATTRS)
+
+ # Wait for the 'deleting' threads to complete
+ del_users.join()
+ del_users2.join()
+ del_users3.join()
+
+ # Now make sure both the MO and RI plugins still work correctly
+ plugin_tests.func_tests[8](topology.standalone) # RI plugin
+ plugin_tests.func_tests[5](topology.standalone) # MO plugin
+
+ # Cleanup the stress tests
+ stress_tests.cleanup(topology.standalone)
+
+ except:
+ log.info('Stress test failed!')
+ repl_fail(replica_inst)
+
+ stress_count += 1
+
log.info('####################################################################')
+ log.info('Successfully Stressed Dynamic Plugins' + msg +
+ '. Completed (%d/%d)' % (stress_count, stress_max_runs))
+
log.info('####################################################################\n')
+
+ if replication_run:
+ # We're done.
+ break
+ else:
+ #
+ # Enable replication and run everything one more time
+ #
+ log.info('Setting up replication, and rerunning the tests...\n')
+
+ # Create replica instance
+ replica_inst = DirSrv(verbose=False)
+ args_instance[SER_HOST] = LOCALHOST
+ args_instance[SER_PORT] = REPLICA_PORT
+ args_instance[SER_SERVERID_PROP] = 'replica'
+ args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
+
+ args_replica_inst = args_instance.copy()
+ replica_inst.allocate(args_replica_inst)
+ replica_inst.create()
+ replica_inst.open()
+
+ try:
+ topology.standalone.replica.enableReplication(suffix=DEFAULT_SUFFIX,
+ role=REPLICAROLE_MASTER,
+ replicaId=1)
+ replica_inst.replica.enableReplication(suffix=DEFAULT_SUFFIX,
+ role=REPLICAROLE_CONSUMER,
+ replicaId=65535)
+ properties = {RA_NAME: r'to_replica',
+ RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
+ RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
+ RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
+ RA_TRANSPORT_PROT:
defaultProperties[REPLICATION_TRANSPORT]}
+
+ repl_agreement =
topology.standalone.agreement.create(suffix=DEFAULT_SUFFIX,
+ host=LOCALHOST,
+ port=REPLICA_PORT,
+
properties=properties)
+
+ if not repl_agreement:
+ log.fatal("Fail to create a replica agreement")
+ repl_fail(replica_inst)
+
+ topology.standalone.agreement.init(DEFAULT_SUFFIX, LOCALHOST,
REPLICA_PORT)
+ topology.standalone.waitForReplInit(repl_agreement)
+ except:
+ log.info('Failed to setup replication!')
+ repl_fail(replica_inst)
+
+ replication_run = True
+ msg = ' (replication enabled)'
+ time.sleep(1)
- plugin_test(topology.standalone, "restart")
+ ############################################################################
+ # Check replication, and data are in sync, and remove the instance
+ ############################################################################
- if prev_plugin_test:
- prev_plugin_test(topology.standalone, "restart")
+ log.info('Checking if replication is in sync...')
- plugin_test(topology.standalone, "restart")
+ try:
+ # Grab master's max CSN
+ entry = topology.standalone.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE,
RUV_FILTER)
+ if not entry:
+ log.error('Failed to find db tombstone entry from master')
+ repl_fail(replica_inst)
+ elements = entry[0].getValues('nsds50ruv')
+ for ruv in elements:
+ if 'replica 1' in ruv:
+ parts = ruv.split()
+ if len(parts) == 5:
+ master_maxcsn = parts[4]
+ break
+ else:
+ log.error('RUV is incomplete')
+ repl_fail(replica_inst)
+ if master_maxcsn == 0:
+ log.error('Failed to find maxcsn on master')
+ repl_fail(replica_inst)
- # Now run the functional test
- plugin_test(topology.standalone)
+ except ldap.LDAPError, e:
+ log.fatal('Unable to search masterfor db tombstone: ' +
e.message['desc'])
+ repl_fail(replica_inst)
+
+ # Loop on the consumer - waiting for it to catch up
+ count = 0
+ insync = False
+ while count < 10:
+ try:
+ # Grab master's max CSN
+ entry = replica_inst.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE,
RUV_FILTER)
+ if not entry:
+ log.error('Failed to find db tombstone entry on consumer')
+ repl_fail(replica_inst)
+ elements = entry[0].getValues('nsds50ruv')
+ for ruv in elements:
+ if 'replica 1' in ruv:
+ parts = ruv.split()
+ if len(parts) == 5:
+ replica_maxcsn = parts[4]
+ break
+ if replica_maxcsn == 0:
+ log.error('Failed to find maxcsn on consumer')
+ repl_fail(replica_inst)
+ except ldap.LDAPError, e:
+ log.fatal('Unable to search for db tombstone on consumer: ' +
e.message['desc'])
+ repl_fail(replica_inst)
+
+ if master_maxcsn == replica_maxcsn:
+ insync = True
+ log.info('Replication is in sync.\n')
+ break
+ count += 1
+ time.sleep(1)
+
+ # Report on replication status
+ if not insync:
+ log.error('Consumer not in sync with master!')
+ repl_fail(replica_inst)
- # Set the previous tests
- if prev_plugin_test:
- prev_prev_plugin_test = prev_plugin_test
- prev_plugin_test = plugin_test
+ #
+ # Verify the databases are identical. There should not be any "user, entry,
employee" entries
+ #
+ log.info('Checking if the data is the same between the replicas...')
- log.info('#####################################################')
- log.info('Successfully Tested Dynamic Plugins for Memory Corruption.')
- log.info('#####################################################\n')
+ # Check the master
+ try:
+ entries = topology.standalone.search_s(DEFAULT_SUFFIX,
+ ldap.SCOPE_SUBTREE,
+
"(|(uid=person*)(uid=entry*)(uid=employee*))")
+ if len(entries) > 0:
+ log.error('Master database has incorrect data set!\n')
+ repl_fail(replica_inst)
+ except ldap.LDAPError, e:
+ log.fatal('Unable to search db on master: ' + e.message['desc'])
+ repl_fail(replica_inst)
- ############################################################################
- # Stress two plugins while restarting it, and while restarting other plugins.
- # The goal is to not crash, and have the plugins work after stressing it.
- ############################################################################
+ # Check the consumer
+ try:
+ entries = replica_inst.search_s(DEFAULT_SUFFIX,
+ ldap.SCOPE_SUBTREE,
+
"(|(uid=person*)(uid=entry*)(uid=employee*))")
+ if len(entries) > 0:
+ log.error('Consumer database in not consistent with master
database')
+ repl_fail(replica_inst)
+ except ldap.LDAPError, e:
+ log.fatal('Unable to search db on consumer: ' +
e.message['desc'])
+ repl_fail(replica_inst)
- log.info('#####################################################')
- log.info('Stressing Dynamic Plugins...')
- log.info('#####################################################\n')
+ log.info('Data is consistent across the replicas.\n')
- # Configure the plugins
- stress_tests.configureMO(topology.standalone)
- stress_tests.configureRI(topology.standalone)
-
- # Launch three new threads to add a bunch of users
- add_users = stress_tests.AddUsers(topology.standalone, 'user', True)
- add_users.start()
- add_users2 = stress_tests.AddUsers(topology.standalone, 'entry', True)
- add_users2.start()
- add_users3 = stress_tests.AddUsers(topology.standalone, 'person', True)
- add_users3.start()
- time.sleep(1)
-
- # While we are adding users restart the MO plugin
- topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
- topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
- time.sleep(3)
- topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
- time.sleep(1)
- topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
-
- # Restart idle plugin
- topology.standalone.plugins.disable(name=PLUGIN_LINKED_ATTRS)
- topology.standalone.plugins.enable(name=PLUGIN_LINKED_ATTRS)
-
- # Wait for the 'adding' threads to complete
- add_users.join()
- add_users2.join()
- add_users3.join()
-
- # Now launch three threads to delete the users, and restart both the MO and RI
plugins
- del_users = stress_tests.DelUsers(topology.standalone, 'user')
- del_users.start()
- del_users2 = stress_tests.DelUsers(topology.standalone, 'entry')
- del_users2.start()
- del_users3 = stress_tests.DelUsers(topology.standalone, 'person')
- del_users3.start()
- time.sleep(1)
-
- # Restart the both the MO and RI plugins during these deletes
-
- topology.standalone.plugins.disable(name=PLUGIN_REFER_INTEGRITY)
- topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
- topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
- topology.standalone.plugins.enable(name=PLUGIN_REFER_INTEGRITY)
- time.sleep(3)
- topology.standalone.plugins.disable(name=PLUGIN_REFER_INTEGRITY)
- time.sleep(1)
- topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
- time.sleep(1)
- topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
- time.sleep(1)
- topology.standalone.plugins.enable(name=PLUGIN_REFER_INTEGRITY)
-
- # Restart idle plugin
- topology.standalone.plugins.disable(name=PLUGIN_LINKED_ATTRS)
- topology.standalone.plugins.enable(name=PLUGIN_LINKED_ATTRS)
-
- # Wait for the 'deleting' threads to complete
- del_users.join()
- del_users2.join()
- del_users3.join()
-
- # Now make sure both the MO and RI plugins still work
- plugin_tests.func_tests[8](topology.standalone) # RI plugin
- plugin_tests.func_tests[5](topology.standalone) # MO plugin
+
log.info('####################################################################')
+ log.info('Replication consistency test passed')
+
log.info('####################################################################\n')
- log.info('#####################################################')
- log.info('Successfully Stressed Dynamic Plugins.')
- log.info('#####################################################\n')
+ # Remove the replica instance
+ replica_inst.delete()
############################################################################
# We made it to the end!
@@ -291,7 +509,8 @@ def test_dynamic_plugins(topology):
log.info('#####################################################')
log.info("Dynamic Plugins Testsuite: Completed Successfully!")
log.info('#####################################################')
- log.info('#####################################################')
+ log.info('#####################################################\n')
+
def test_dynamic_plugins_final(topology):
topology.standalone.stop(timeout=10)
diff --git a/dirsrvtests/tickets/ticket47560_test.py
b/dirsrvtests/tickets/ticket47560_test.py
index 0b7e436..af7fdc3 100644
--- a/dirsrvtests/tickets/ticket47560_test.py
+++ b/dirsrvtests/tickets/ticket47560_test.py
@@ -146,7 +146,7 @@ def test_ticket47560(topology):
Enable or disable mbo plugin depending on 'value'
('on'/'off')
"""
# enable/disable the mbo plugin
- if value != 'on':
+ if value == 'on':
topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
else:
topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
diff --git a/ldap/servers/plugins/acctpolicy/acct_config.c
b/ldap/servers/plugins/acctpolicy/acct_config.c
index 25352b1..d1acf1a 100644
--- a/ldap/servers/plugins/acctpolicy/acct_config.c
+++ b/ldap/servers/plugins/acctpolicy/acct_config.c
@@ -53,9 +53,11 @@ acct_policy_load_config_startup( Slapi_PBlock* pb, void* plugin_id ) {
PLUGIN_CONFIG_DN, rc );
return( -1 );
}
-
+ config_wr_lock();
+ free_config();
newcfg = get_config();
rc = acct_policy_entry2config( config_entry, newcfg );
+ config_unlock();
slapi_entry_free( config_entry );
@@ -85,8 +87,8 @@ acct_policy_entry2config( Slapi_Entry *e, acctPluginCfg *newcfg ) {
} else if (!update_is_allowed_attr(newcfg->state_attr_name)) {
/* log a warning that this attribute cannot be updated */
slapi_log_error( SLAPI_LOG_FATAL, PLUGIN_NAME,
- "The configured state attribute [%s] cannot be updated, accounts will always
become inactive.\n",
- newcfg->state_attr_name );
+ "The configured state attribute [%s] cannot be updated, accounts will always
become inactive.\n",
+ newcfg->state_attr_name );
}
newcfg->alt_state_attr_name = get_attr_string_val( e, CFG_ALT_LASTLOGIN_STATE_ATTR
);
diff --git a/ldap/servers/plugins/acctpolicy/acct_init.c
b/ldap/servers/plugins/acctpolicy/acct_init.c
index c4dba22..0b1af91 100644
--- a/ldap/servers/plugins/acctpolicy/acct_init.c
+++ b/ldap/servers/plugins/acctpolicy/acct_init.c
@@ -63,6 +63,47 @@ int acct_postop_init( Slapi_PBlock *pb );
int acct_bind_preop( Slapi_PBlock *pb );
int acct_bind_postop( Slapi_PBlock *pb );
+static void *_PluginID = NULL;
+static Slapi_DN *_PluginDN = NULL;
+static Slapi_DN *_ConfigAreaDN = NULL;
+static Slapi_RWLock *config_rwlock = NULL;
+
+void
+acct_policy_set_plugin_id(void *pluginID)
+{
+ _PluginID = pluginID;
+}
+
+void *
+acct_policy_get_plugin_id()
+{
+ return _PluginID;
+}
+
+void
+acct_policy_set_plugin_sdn(Slapi_DN *pluginDN)
+{
+ _PluginDN = pluginDN;
+}
+
+Slapi_DN *
+acct_policy_get_plugin_sdn()
+{
+ return _PluginDN;
+}
+
+void
+acct_policy_set_config_area(Slapi_DN *sdn)
+{
+ _ConfigAreaDN = sdn;
+}
+
+Slapi_DN *
+acct_policy_get_config_area()
+{
+ return _ConfigAreaDN;
+}
+
/*
Master init function for the account plugin
*/
@@ -120,14 +161,32 @@ acct_policy_init( Slapi_PBlock *pb )
which is needed to retrieve the plugin configuration
*/
int
-acct_policy_start( Slapi_PBlock *pb ) {
+acct_policy_start( Slapi_PBlock *pb )
+{
acctPluginCfg *cfg;
void *plugin_id = get_identity();
+ Slapi_DN *plugindn = NULL;
+ char *config_area = NULL;
if(slapi_plugin_running(pb)){
return 0;
}
+ slapi_pblock_get(pb, SLAPI_TARGET_SDN, &plugindn);
+ acct_policy_set_plugin_sdn(slapi_sdn_dup(plugindn));
+
+ /* Set the alternate config area if one is defined. */
+ slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_AREA, &config_area);
+ if (config_area) {
+ acct_policy_set_config_area(slapi_sdn_new_normdn_byval(config_area));
+ }
+
+ if(config_rwlock == NULL){
+ if((config_rwlock = slapi_new_rwlock()) == NULL){
+ return( CALLBACK_ERR );
+ }
+ }
+
/* Load plugin configuration */
if( acct_policy_load_config_startup( pb, plugin_id ) ) {
slapi_log_error( SLAPI_LOG_FATAL, PLUGIN_NAME,
@@ -151,6 +210,10 @@ acct_policy_close( Slapi_PBlock *pb )
{
int rc = 0;
+ slapi_destroy_rwlock(config_rwlock);
+ config_rwlock = NULL;
+ slapi_sdn_free(&_PluginDN);
+ slapi_sdn_free(&_ConfigAreaDN);
free_config();
return rc;
@@ -168,8 +231,11 @@ acct_preop_init( Slapi_PBlock *pb ) {
return( CALLBACK_ERR );
}
- if ( slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_BIND_FN,
- (void *) acct_bind_preop ) != 0 ) {
+ if ( slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_BIND_FN, (void *) acct_bind_preop ) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ADD_FN, (void *) acct_add_pre_op) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_MODIFY_FN, (void *) acct_mod_pre_op) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_DELETE_FN, (void *) acct_del_pre_op) != 0)
+ {
slapi_log_error( SLAPI_LOG_FATAL, PRE_PLUGIN_NAME,
"Failed to set plugin callback function\n" );
return( CALLBACK_ERR );
@@ -192,8 +258,11 @@ acct_postop_init( Slapi_PBlock *pb )
return( CALLBACK_ERR );
}
- if ( slapi_pblock_set( pb, SLAPI_PLUGIN_POST_BIND_FN,
- (void *)acct_bind_postop ) != 0 ) {
+
+ if ( slapi_pblock_set( pb, SLAPI_PLUGIN_POST_BIND_FN, (void *)acct_bind_postop ) != 0
||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN, (void *) acct_post_op) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN, (void *) acct_post_op) != 0)
+ {
slapi_log_error( SLAPI_LOG_FATAL, POST_PLUGIN_NAME,
"Failed to set plugin callback function\n" );
return( CALLBACK_ERR );
@@ -208,3 +277,23 @@ acct_postop_init( Slapi_PBlock *pb )
return( CALLBACK_OK );
}
+/*
+ * Wrappers for config locking
+ */
+void
+config_rd_lock()
+{
+ slapi_rwlock_rdlock(config_rwlock);
+}
+
+void
+config_wr_lock()
+{
+ slapi_rwlock_wrlock(config_rwlock);
+}
+
+void
+config_unlock()
+{
+ slapi_rwlock_unlock(config_rwlock);
+}
diff --git a/ldap/servers/plugins/acctpolicy/acct_plugin.c
b/ldap/servers/plugins/acctpolicy/acct_plugin.c
index 5719f27..a61a50c 100644
--- a/ldap/servers/plugins/acctpolicy/acct_plugin.c
+++ b/ldap/servers/plugins/acctpolicy/acct_plugin.c
@@ -28,6 +28,46 @@ Hewlett-Packard Development Company, L.P.
#include "acctpolicy.h"
/*
+ * acct_policy_dn_is_config()
+ *
+ * Checks if dn is a plugin config entry.
+ */
+static int
+acct_policy_dn_is_config(Slapi_DN *sdn)
+{
+ int ret = 0;
+
+ slapi_log_error(SLAPI_LOG_TRACE, PLUGIN_NAME,
+ "--> automember_dn_is_config\n");
+
+ if (sdn == NULL) {
+ goto bail;
+ }
+
+ /* If an alternate config area is configured, treat it's child
+ * entries as config entries. If the alternate config area is
+ * not configured, treat children of the top-level plug-in
+ * config entry as our config entries. */
+ if (acct_policy_get_config_area()) {
+ if (slapi_sdn_issuffix(sdn, acct_policy_get_config_area()) &&
+ slapi_sdn_compare(sdn, acct_policy_get_config_area())) {
+ ret = 1;
+ }
+ } else {
+ if (slapi_sdn_issuffix(sdn, acct_policy_get_plugin_sdn()) &&
+ slapi_sdn_compare(sdn, acct_policy_get_plugin_sdn())) {
+ ret = 1;
+ }
+ }
+
+bail:
+ slapi_log_error(SLAPI_LOG_TRACE, PLUGIN_NAME,
+ "<-- automember_dn_is_config\n");
+
+ return ret;
+}
+
+/*
Checks bind entry for last login state and compares current time with last
login time plus the limit to decide whether to deny the bind.
*/
@@ -39,6 +79,7 @@ acct_inact_limit( Slapi_PBlock *pb, const char *dn, Slapi_Entry
*target_entry, a
int rc = 0; /* Optimistic default */
acctPluginCfg *cfg;
+ config_rd_lock();
cfg = get_config();
if( ( lasttimestr = get_attr_string_val( target_entry,
cfg->state_attr_name ) ) != NULL ) {
@@ -75,6 +116,7 @@ acct_inact_limit( Slapi_PBlock *pb, const char *dn, Slapi_Entry
*target_entry, a
}
done:
+ config_unlock();
/* Deny bind; the account has exceeded the inactivity limit */
if( rc == 1 ) {
slapi_send_ldap_result( pb, LDAP_CONSTRAINT_VIOLATION, NULL,
@@ -106,13 +148,14 @@ acct_record_login( const char *dn )
Slapi_PBlock *modpb = NULL;
int skip_mod_attrs = 1; /* value doesn't matter as long as not NULL */
+ config_rd_lock();
cfg = get_config();
/* if we are not allowed to modify the state attr we're done
* this could be intentional, so just return
*/
if (! update_is_allowed_attr(cfg->always_record_login_attr) )
- return rc;
+ goto done;
plugin_id = get_identity();
@@ -152,6 +195,7 @@ acct_record_login( const char *dn )
}
done:
+ config_unlock();
slapi_pblock_destroy( modpb );
slapi_ch_free_string( ×tr );
@@ -274,6 +318,7 @@ acct_bind_postop( Slapi_PBlock *pb )
goto done;
}
+ config_rd_lock();
cfg = get_config();
tracklogin = cfg->always_record_login;
@@ -296,6 +341,7 @@ acct_bind_postop( Slapi_PBlock *pb )
}
}
}
+ config_unlock();
if( tracklogin ) {
rc = acct_record_login( dn );
@@ -319,3 +365,133 @@ done:
return( rc == 0 ? CALLBACK_OK : CALLBACK_ERR );
}
+
+static int acct_pre_op( Slapi_PBlock *pb, int modop )
+{
+ Slapi_DN *sdn = 0;
+ Slapi_Entry *e = 0;
+ Slapi_Mods *smods = 0;
+ LDAPMod **mods;
+ int free_entry = 0;
+ char *errstr = NULL;
+ int ret = SLAPI_PLUGIN_SUCCESS;
+
+ slapi_log_error(SLAPI_LOG_TRACE, PRE_PLUGIN_NAME, "--> acct_pre_op\n");
+
+ slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
+
+ if (acct_policy_dn_is_config(sdn)) {
+ /* Validate config changes, but don't apply them.
+ * This allows us to reject invalid config changes
+ * here at the pre-op stage. Applying the config
+ * needs to be done at the post-op stage. */
+
+ if (LDAP_CHANGETYPE_ADD == modop) {
+ slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
+
+ /* If the entry doesn't exist, just bail and
+ * let the server handle it. */
+ if (e == NULL) {
+ goto bail;
+ }
+ } else if (LDAP_CHANGETYPE_MODIFY == modop) {
+ /* Fetch the entry being modified so we can
+ * create the resulting entry for validation. */
+ if (sdn) {
+ slapi_search_internal_get_entry(sdn, 0, &e, get_identity());
+ free_entry = 1;
+ }
+
+ /* If the entry doesn't exist, just bail and
+ * let the server handle it. */
+ if (e == NULL) {
+ goto bail;
+ }
+
+ /* Grab the mods. */
+ slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
+ smods = slapi_mods_new();
+ slapi_mods_init_byref(smods, mods);
+
+ /* Apply the mods to create the resulting entry. */
+ if (mods && (slapi_entry_apply_mods(e, mods) != LDAP_SUCCESS)) {
+ /* The mods don't apply cleanly, so we just let this op go
+ * to let the main server handle it. */
+ goto bailmod;
+ }
+ } else if (modop == LDAP_CHANGETYPE_DELETE){
+ ret = LDAP_UNWILLING_TO_PERFORM;
+ slapi_log_error(SLAPI_LOG_FATAL, PRE_PLUGIN_NAME,
+ "acct_pre_op: can not delete plugin config entry [%d]\n", ret);
+ } else {
+ errstr = slapi_ch_smprintf("acct_pre_op: invalid op type %d", modop);
+ ret = LDAP_PARAM_ERROR;
+ goto bail;
+ }
+ }
+
+ bailmod:
+ /* Clean up smods. */
+ if (LDAP_CHANGETYPE_MODIFY == modop) {
+ slapi_mods_free(&smods);
+ }
+
+ bail:
+ if (free_entry && e)
+ slapi_entry_free(e);
+
+ if (ret) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, PRE_PLUGIN_NAME,
+ "acct_pre_op: operation failure [%d]\n", ret);
+ slapi_send_ldap_result(pb, ret, NULL, errstr, 0, NULL);
+ slapi_ch_free((void **)&errstr);
+ slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ret);
+ ret = SLAPI_PLUGIN_FAILURE;
+ }
+
+ slapi_log_error(SLAPI_LOG_TRACE, PRE_PLUGIN_NAME, "<-- acct_pre_op\n");
+
+ return ret;
+}
+
+int
+acct_add_pre_op( Slapi_PBlock *pb )
+{
+ return acct_pre_op(pb, LDAP_CHANGETYPE_ADD);
+}
+
+int
+acct_mod_pre_op( Slapi_PBlock *pb )
+{
+ return acct_pre_op(pb, LDAP_CHANGETYPE_MODIFY);
+}
+
+int
+acct_del_pre_op( Slapi_PBlock *pb )
+{
+ return acct_pre_op(pb, LDAP_CHANGETYPE_DELETE);
+}
+
+int
+acct_post_op(Slapi_PBlock *pb)
+{
+ Slapi_DN *sdn = NULL;
+
+ slapi_log_error(SLAPI_LOG_TRACE, POST_PLUGIN_NAME,
+ "--> acct_policy_post_op\n");
+
+ slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
+ if (acct_policy_dn_is_config(sdn)){
+ if( acct_policy_load_config_startup( pb, get_identity() ) ) {
+ slapi_log_error( SLAPI_LOG_FATAL, PLUGIN_NAME,
+ "acct_policy_start failed to load configuration\n" );
+ return( CALLBACK_ERR );
+ }
+ }
+
+ slapi_log_error(SLAPI_LOG_TRACE, POST_PLUGIN_NAME,
+ "<-- acct_policy_mod_post_op\n");
+
+ return SLAPI_PLUGIN_SUCCESS;
+}
+
diff --git a/ldap/servers/plugins/acctpolicy/acct_util.c
b/ldap/servers/plugins/acctpolicy/acct_util.c
index 2e24da2..cff0176 100644
--- a/ldap/servers/plugins/acctpolicy/acct_util.c
+++ b/ldap/servers/plugins/acctpolicy/acct_util.c
@@ -82,7 +82,8 @@ get_attr_string_val( Slapi_Entry* target_entry, char* attr_name ) {
*/
int
get_acctpolicy( Slapi_PBlock *pb, Slapi_Entry *target_entry, void *plugin_id,
- acctPolicy **policy ) {
+ acctPolicy **policy )
+{
Slapi_DN *sdn = NULL;
Slapi_Entry *policy_entry = NULL;
Slapi_Attr *attr;
@@ -93,8 +94,6 @@ get_acctpolicy( Slapi_PBlock *pb, Slapi_Entry *target_entry, void
*plugin_id,
acctPluginCfg *cfg;
int rc = 0;
- cfg = get_config();
-
if( policy == NULL ) {
/* Bad parameter */
return( -1 );
@@ -102,19 +101,22 @@ get_acctpolicy( Slapi_PBlock *pb, Slapi_Entry *target_entry, void
*plugin_id,
*policy = NULL;
+ config_rd_lock();
+ cfg = get_config();
/* Return success and NULL policy */
policy_dn = get_attr_string_val( target_entry, cfg->spec_attr_name );
if( policy_dn == NULL ) {
slapi_log_error( SLAPI_LOG_PLUGIN, PLUGIN_NAME,
"\"%s\" is not governed by an account inactivity "
"policy subentry\n", slapi_entry_get_ndn( target_entry ) );
- if (cfg->inactivitylimit != ULONG_MAX) {
- goto dopolicy;
- }
+ if (cfg->inactivitylimit != ULONG_MAX) {
+ goto dopolicy;
+ }
slapi_log_error( SLAPI_LOG_PLUGIN, PLUGIN_NAME,
"\"%s\" is not governed by an account inactivity "
"global policy\n", slapi_entry_get_ndn( target_entry ) );
- return rc;
+ config_unlock();
+ return rc;
}
sdn = slapi_sdn_new_dn_byref( policy_dn );
@@ -153,7 +155,8 @@ dopolicy:
}
}
done:
- slapi_ch_free_string( &policy_dn );
+ config_unlock();
+ slapi_ch_free_string( &policy_dn );
slapi_entry_free( policy_entry );
return( rc );
}
diff --git a/ldap/servers/plugins/acctpolicy/acctpolicy.h
b/ldap/servers/plugins/acctpolicy/acctpolicy.h
index 2185b95..64f37fb 100644
--- a/ldap/servers/plugins/acctpolicy/acctpolicy.h
+++ b/ldap/servers/plugins/acctpolicy/acctpolicy.h
@@ -69,10 +69,9 @@ typedef struct accountpolicy {
int get_acctpolicy( Slapi_PBlock *pb, Slapi_Entry *target_entry,
void *plugin_id, acctPolicy **policy );
void free_acctpolicy( acctPolicy **policy );
-int has_attr( Slapi_Entry* target_entry, char* attr_name,
- char** val );
+int has_attr( Slapi_Entry* target_entry, char* attr_name, char** val );
char* get_attr_string_val( Slapi_Entry* e, char* attr_name );
-void* get_identity();
+void* get_identity(void);
void set_identity(void*);
time_t gentimeToEpochtime( char *gentimestr );
char* epochtimeToGentime( time_t epochtime );
@@ -80,6 +79,22 @@ int update_is_allowed_attr (const char *attr);
/* acct_config.c */
int acct_policy_load_config_startup( Slapi_PBlock* pb, void* plugin_id );
-acctPluginCfg* get_config();
-void free_config();
+acctPluginCfg* get_config(void);
+void free_config(void);
+
+/* acct_init.c */
+void acct_policy_set_plugin_sdn(Slapi_DN *pluginDN);
+Slapi_DN * acct_policy_get_plugin_sdn(void);
+void acct_policy_set_config_area(Slapi_DN *sdn);
+Slapi_DN * acct_policy_get_config_area(void);
+void config_rd_lock(void);
+void config_wr_lock(void);
+void config_unlock(void);
+
+/* acc_plugins.c */
+int acct_add_pre_op( Slapi_PBlock *pb );
+int acct_mod_pre_op( Slapi_PBlock *pb );
+int acct_del_pre_op( Slapi_PBlock *pb );
+int acct_post_op( Slapi_PBlock *pb );
+
diff --git a/ldap/servers/plugins/linkedattrs/fixup_task.c
b/ldap/servers/plugins/linkedattrs/fixup_task.c
index db3c693..f3f5c04 100644
--- a/ldap/servers/plugins/linkedattrs/fixup_task.c
+++ b/ldap/servers/plugins/linkedattrs/fixup_task.c
@@ -197,8 +197,8 @@ linked_attrs_fixup_task_thread(void *arg)
linked_attrs_unlock();
/* Log finished message. */
- slapi_task_log_notice(task, "Linked attributes fixup task complete.\n");
- slapi_task_log_status(task, "Linked attributes fixup task complete.\n");
+ slapi_task_log_notice(task, "Linked attributes fixup task complete.");
+ slapi_task_log_status(task, "Linked attributes fixup task complete.");
slapi_log_error(SLAPI_LOG_FATAL, LINK_PLUGIN_SUBSYSTEM, "Linked attributes fixup
task complete.\n");
slapi_task_inc_progress(task);
diff --git a/ldap/servers/plugins/memberof/memberof_config.c
b/ldap/servers/plugins/memberof/memberof_config.c
index 012e2d0..7fa5897 100644
--- a/ldap/servers/plugins/memberof/memberof_config.c
+++ b/ldap/servers/plugins/memberof/memberof_config.c
@@ -867,7 +867,6 @@ memberof_shared_config_validate(Slapi_PBlock *pb)
}
slapi_ch_free_string(&configarea_dn);
slapi_sdn_free(&config_sdn);
- slapi_entry_free(config_entry);
}
}
}
diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c
index f0ce255..f80178e 100644
--- a/ldap/servers/slapd/dse.c
+++ b/ldap/servers/slapd/dse.c
@@ -2426,8 +2426,6 @@ dse_add(Slapi_PBlock *pb) /* JCM There should only be one exit point
from this f
}
}
- /* entry has been freed, so make sure no one tries to use it later */
- slapi_pblock_set(pb, SLAPI_ADD_ENTRY, NULL);
slapi_send_ldap_result(pb, returncode, NULL, returntext[0] ? returntext : NULL, 0,
NULL );
return dse_add_return(rc, e);
}
diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c
index 5530c70..b0b18e7 100644
--- a/ldap/servers/slapd/plugin.c
+++ b/ldap/servers/slapd/plugin.c
@@ -454,10 +454,21 @@ plugin_call_plugins( Slapi_PBlock *pb, int whichfunction )
{
/* We stash the pblock plugin pointer to preserve the callers context */
struct slapdplugin *p;
+ int locked = 0;
+
+ locked = slapi_td_get_plugin_locked();
+ if (!locked) {
+ slapi_rwlock_rdlock(global_rwlock);
+ }
+
slapi_pblock_get(pb, SLAPI_PLUGIN, &p);
/* Call the operation on the Global Plugins */
rc = plugin_call_list(global_plugin_list[plugin_list_number], whichfunction, pb);
slapi_pblock_set(pb, SLAPI_PLUGIN, p);
+
+ if (!locked) {
+ slapi_rwlock_unlock(global_rwlock);
+ }
}
else
{
@@ -1080,12 +1091,6 @@ plugin_start(Slapi_Entry *entry, char *returntext)
int ret = 0;
int i = 0;
- /*
- * Disable registered plugin functions so preops/postops/etc
- * dont get called prior to the plugin being started (due to
- * plugins performing ops on the DIT)
- */
- global_plugin_callbacks_enabled = 0;
global_plugins_started = 0;
/* Count the plugins so we can allocate memory for the config array */
@@ -1404,6 +1409,7 @@ plugin_free_plugin_dep_config(plugin_dep_config **cfg)
}
slapi_ch_free_string(&config[index].type);
slapi_ch_free_string(&config[index].name);
+ slapi_ch_free_string(&config[index].config_area);
pblock_done(&config[index].pb);
index++;
}
@@ -1909,16 +1915,6 @@ plugin_call_func (struct slapdplugin *list, int operation,
Slapi_PBlock *pb, int
int rc;
int return_value = 0;
int count = 0;
- int *locked = 0;
-
- /*
- * Take the read lock
- */
- slapi_td_get_plugin_locked(&locked);
- if(locked == 0){
- slapi_rwlock_rdlock(global_rwlock);
- }
-
for (; list != NULL; list = list->plg_next)
{
@@ -1998,9 +1994,6 @@ plugin_call_func (struct slapdplugin *list, int operation,
Slapi_PBlock *pb, int
if(call_one)
break;
}
- if(locked == 0){
- slapi_rwlock_unlock(global_rwlock);
- }
return( return_value );
}
@@ -2323,6 +2316,7 @@ plugin_restart(Slapi_Entry *pentryBefore, Slapi_Entry *pentryAfter)
}
slapi_rwlock_wrlock(global_rwlock);
+ slapi_td_set_plugin_locked();
if(plugin_delete(pentryBefore, returntext, 1) == LDAP_SUCCESS){
if(plugin_add(pentryAfter, returntext, 1) == LDAP_SUCCESS){
@@ -2346,6 +2340,7 @@ plugin_restart(Slapi_Entry *pentryBefore, Slapi_Entry *pentryAfter)
}
slapi_rwlock_unlock(global_rwlock);
+ slapi_td_set_plugin_unlocked();
return rc;
}
@@ -2995,12 +2990,11 @@ int
plugin_add(Slapi_Entry *entry, char *returntext, int locked)
{
int rc = LDAP_SUCCESS;
- int td_locked = 1;
if(!locked){
slapi_rwlock_wrlock(global_rwlock);
+ slapi_td_set_plugin_locked();
}
- slapi_td_set_plugin_locked(&td_locked);
if((rc = plugin_setup(entry, 0, 0, 1, returntext)) != LDAP_SUCCESS){
LDAPDebug(LDAP_DEBUG_PLUGIN, "plugin_add: plugin_setup failed for
(%s)\n",slapi_entry_get_dn(entry), rc, 0);
@@ -3015,9 +3009,8 @@ plugin_add(Slapi_Entry *entry, char *returntext, int locked)
done:
if(!locked){
slapi_rwlock_unlock(global_rwlock);
+ slapi_td_set_plugin_unlocked();
}
- td_locked = 0;
- slapi_td_set_plugin_locked(&td_locked);
return rc;
}
@@ -3372,7 +3365,6 @@ plugin_delete(Slapi_Entry *plugin_entry, char *returntext, int
locked)
struct slapdplugin *plugin = NULL;
const char *plugin_dn = slapi_entry_get_dn_const(plugin_entry);
char *value = NULL;
- int td_locked = 1;
int removed = PLUGIN_BUSY;
int type = 0;
int rc = LDAP_SUCCESS;
@@ -3400,8 +3392,8 @@ plugin_delete(Slapi_Entry *plugin_entry, char *returntext, int
locked)
removed = PLUGIN_NOT_FOUND;
if(!locked){
slapi_rwlock_wrlock(global_rwlock);
+ slapi_td_set_plugin_locked();
}
- slapi_td_set_plugin_locked(&td_locked);
rc = plugin_get_type_and_list(value, &type, &plugin_list);
if ( rc != 0 ) {
@@ -3445,9 +3437,8 @@ plugin_delete(Slapi_Entry *plugin_entry, char *returntext, int
locked)
unlock:
if(!locked){
slapi_rwlock_unlock(global_rwlock);
+ slapi_td_set_plugin_unlocked();
}
- td_locked = 0;
- slapi_td_set_plugin_locked(&td_locked);
}
}
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index cb8aad0..a61d954 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -5585,8 +5585,10 @@ int slapi_td_dn_init(void);
int slapi_td_set_dn(char *dn);
void slapi_td_get_dn(char **dn);
int slapi_td_plugin_lock_init(void);
-int slapi_td_set_plugin_locked(int *value);
-void slapi_td_get_plugin_locked(int **value);
+int slapi_td_get_plugin_locked(void);
+int slapi_td_set_plugin_locked(void);
+int slapi_td_set_plugin_unlocked(void);
+
/* Thread Local Storage Index Types */
#define SLAPI_TD_REQUESTOR_DN 1
diff --git a/ldap/servers/slapd/thread_data.c b/ldap/servers/slapd/thread_data.c
index 121e2d8..4d9bb93 100644
--- a/ldap/servers/slapd/thread_data.c
+++ b/ldap/servers/slapd/thread_data.c
@@ -168,19 +168,38 @@ slapi_td_plugin_lock_init()
}
int
-slapi_td_set_plugin_locked(int *value)
+slapi_td_set_plugin_locked()
{
- if(slapi_td_set_val(SLAPI_TD_PLUGIN_LIST_LOCK, (void *)value) == PR_FAILURE){
+ int val = 12345;
+
+ if(slapi_td_set_val(SLAPI_TD_PLUGIN_LIST_LOCK, (void *)&val) == PR_FAILURE){
return PR_FAILURE;
}
return PR_SUCCESS;
}
-void
-slapi_td_get_plugin_locked(int **value)
+int
+slapi_td_set_plugin_unlocked()
{
- slapi_td_get_val(SLAPI_TD_PLUGIN_LIST_LOCK, (void **)value);
+ if(slapi_td_set_val(SLAPI_TD_PLUGIN_LIST_LOCK, NULL) == PR_FAILURE){
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+
+int
+slapi_td_get_plugin_locked()
+{
+ int *value = 0;
+
+ slapi_td_get_val(SLAPI_TD_PLUGIN_LIST_LOCK, (void **)&value);
+ if(value){
+ return 1;
+ } else{
+ return 0;
+ }
}
/* requestor dn */