dirsrvtests/tickets/ticket47431_test.py | 251 ++++++++++++++++++
ldap/schema/01core389.ldif | 3
ldap/servers/plugins/replication/repl5.h | 7
ldap/servers/plugins/replication/repl5_agmt.c | 26 +
ldap/servers/plugins/replication/repl5_agmtlist.c | 11
ldap/servers/plugins/replication/repl5_inc_protocol.c | 15 -
ldap/servers/plugins/replication/repl_globals.c | 1
ldap/servers/plugins/uiduniq/7bit.c | 12
ldap/servers/slapd/plugin.c | 50 ++-
9 files changed, 348 insertions(+), 28 deletions(-)
New commits:
commit 2802f362395eac0bbbec99fef86ca27240da0d0f
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Wed Mar 4 13:05:02 2015 -0800
Ticket #47957 - Make ReplicaWaitForAsyncResults configurable
Description: Introducing a config attr nsDS5ReplicaWaitForAsyncResults
to the agreement entry.
dn: cn=<AGREEMENT>,cn=replica,cn="<SUFFIX>",cn=mapping
tree,cn=config
nsDS5ReplicaWaitForAsyncResults: <integer in millisecond>
Prior to this patch, supplier sleeps 1 second if it finds the response
from consumer is not ready. 1 second could be too long if higher
replication throughput is required.
This patch makes the waiting time configurable, and change the default
to 100 millisecond. If the attribute nsDS5ReplicaWaitForAsyncResults
does not exist or the value is 0, the default value is set.
https://fedorahosted.org/389/ticket/47957
Reviewed by rmeggins(a)redhat.com (Thank you!!)
diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif
index 9b7ec1d..ffd8710 100644
--- a/ldap/schema/01core389.ldif
+++ b/ldap/schema/01core389.ldif
@@ -306,6 +306,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2310 NAME
'nsds5ReplicaFlowControlWindow
attributeTypes: ( 2.16.840.1.113730.3.1.2311 NAME 'nsds5ReplicaFlowControlPause'
DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.2313 NAME
'nsslapd-changelogtrim-interval' DESC 'Netscape defined attribute type'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory
Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.2314 NAME
'nsslapd-changelogcompactdb-interval' DESC 'Netscape defined attribute
type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape
Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2315 NAME
'nsDS5ReplicaWaitForAsyncResults' DESC 'Netscape defined attribute type'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory
Server' )
#
# objectclasses
#
@@ -317,7 +318,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.110 NAME
'nsMappingTree' DESC 'Netscape d
objectClasses: ( 2.16.840.1.113730.3.2.104 NAME 'nsContainer' DESC 'Netscape
defined objectclass' SUP top MUST ( CN ) X-ORIGIN 'Netscape Directory Server'
)
objectClasses: ( 2.16.840.1.113730.3.2.108 NAME 'nsDS5Replica' DESC 'Netscape
defined objectclass' SUP top MUST ( nsDS5ReplicaRoot $ nsDS5ReplicaId ) MAY (cn $
nsds5ReplicaPreciseTombstonePurging $ nsds5ReplicaCleanRUV $ nsds5ReplicaAbortCleanRUV $
nsDS5ReplicaType $ nsDS5ReplicaBindDN $ nsState $ nsDS5ReplicaName $ nsDS5Flags $
nsDS5Task $ nsDS5ReplicaReferral $ nsDS5ReplicaAutoReferral $ nsds5ReplicaPurgeDelay $
nsds5ReplicaTombstonePurgeInterval $ nsds5ReplicaChangeCount $ nsds5ReplicaLegacyConsumer
$ nsds5ReplicaProtocolTimeout $ nsds5ReplicaBackoffMin $ nsds5ReplicaBackoffMax ) X-ORIGIN
'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.113 NAME 'nsTombstone' DESC 'Netscape
defined objectclass' SUP top MAY ( nstombstonecsn $ nsParentUniqueId $ nscpEntryDN )
X-ORIGIN 'Netscape Directory Server' )
-objectClasses: ( 2.16.840.1.113730.3.2.103 NAME 'nsDS5ReplicationAgreement' DESC
'Netscape defined objectclass' SUP top MUST ( cn ) MAY (
nsds5ReplicaCleanRUVNotified $ nsDS5ReplicaHost $ nsDS5ReplicaPort $
nsDS5ReplicaTransportInfo $ nsDS5ReplicaBindDN $ nsDS5ReplicaCredentials $
nsDS5ReplicaBindMethod $ nsDS5ReplicaRoot $ nsDS5ReplicatedAttributeList $
nsDS5ReplicatedAttributeListTotal $ nsDS5ReplicaUpdateSchedule $ nsds5BeginReplicaRefresh
$ description $ nsds50ruv $ nsruvReplicaLastModified $ nsds5ReplicaTimeout $
nsds5replicaChangesSentSinceStartup $ nsds5replicaLastUpdateEnd $
nsds5replicaLastUpdateStart $ nsds5replicaLastUpdateStatus $ nsds5replicaUpdateInProgress
$ nsds5replicaLastInitEnd $ nsds5ReplicaEnabled $ nsds5replicaLastInitStart $
nsds5replicaLastInitStatus $ nsds5debugreplicatimeout $ nsds5replicaBusyWaitTime $
nsds5ReplicaStripAttrs $ nsds5replicaSessionPauseTime $ nsds5ReplicaProtocolTimeout $
nsds5ReplicaFlowControlWindow $ nsds5ReplicaFlowControlPause )
X-ORIGIN 'Netscape Directory Server' )
+objectClasses: ( 2.16.840.1.113730.3.2.103 NAME 'nsDS5ReplicationAgreement' DESC
'Netscape defined objectclass' SUP top MUST ( cn ) MAY (
nsds5ReplicaCleanRUVNotified $ nsDS5ReplicaHost $ nsDS5ReplicaPort $
nsDS5ReplicaTransportInfo $ nsDS5ReplicaBindDN $ nsDS5ReplicaCredentials $
nsDS5ReplicaBindMethod $ nsDS5ReplicaRoot $ nsDS5ReplicatedAttributeList $
nsDS5ReplicatedAttributeListTotal $ nsDS5ReplicaUpdateSchedule $ nsds5BeginReplicaRefresh
$ description $ nsds50ruv $ nsruvReplicaLastModified $ nsds5ReplicaTimeout $
nsds5replicaChangesSentSinceStartup $ nsds5replicaLastUpdateEnd $
nsds5replicaLastUpdateStart $ nsds5replicaLastUpdateStatus $ nsds5replicaUpdateInProgress
$ nsds5replicaLastInitEnd $ nsds5ReplicaEnabled $ nsds5replicaLastInitStart $
nsds5replicaLastInitStatus $ nsds5debugreplicatimeout $ nsds5replicaBusyWaitTime $
nsds5ReplicaStripAttrs $ nsds5replicaSessionPauseTime $ nsds5ReplicaProtocolTimeout $
nsds5ReplicaFlowControlWindow $ nsds5ReplicaFlowControlPause $
nsDS5ReplicaWaitForAsyncResults ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.39 NAME 'nsslapdConfig' DESC 'Netscape
defined objectclass' SUP top MAY ( cn ) X-ORIGIN 'Netscape Directory Server'
)
objectClasses: ( 2.16.840.1.113730.3.2.317 NAME 'nsSaslMapping' DESC
'Netscape defined objectclass' SUP top MUST ( cn $ nsSaslMapRegexString $
nsSaslMapBaseDNTemplate $ nsSaslMapFilterTemplate ) MAY ( nsSaslMapPriority ) X-ORIGIN
'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.43 NAME 'nsSNMP' DESC 'Netscape
defined objectclass' SUP top MUST ( cn $ nsSNMPEnabled ) MAY ( nsSNMPOrganization $
nsSNMPLocation $ nsSNMPContact $ nsSNMPDescription $ nsSNMPName $ nsSNMPMasterHost $
nsSNMPMasterPort ) X-ORIGIN 'Netscape Directory Server' )
diff --git a/ldap/servers/plugins/replication/repl5.h
b/ldap/servers/plugins/replication/repl5.h
index 39d25bb..a7da266 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -194,6 +194,9 @@ extern const char *type_winSyncSubtreePair;
/* To Allow Consumer Initialisation when adding an agreement - */
extern const char *type_nsds5BeginReplicaRefresh;
+/* For tuning replica release */
+extern const char *type_nsds5WaitForAsyncResults;
+
/* replica related attributes */
extern const char *attr_replicaId;
extern const char *attr_replicaRoot;
@@ -412,6 +415,7 @@ void add_agmt_maxcsns(Slapi_Entry *e, Replica *r);
void agmt_set_maxcsn(Repl_Agmt *ra);
void agmt_remove_maxcsn(Repl_Agmt *ra);
int agmt_maxcsn_to_smod (Replica *r, Slapi_Mod *smod);
+int agmt_set_WaitForAsyncResults(Repl_Agmt *ra, const Slapi_Entry *e);
/* In repl5_agmtlist.c */
int agmtlist_config_init();
@@ -748,6 +752,9 @@ void repl5_set_debug_timeout(const char *val);
/* temp hack XXX */
ReplicaId agmt_get_consumerRID(Repl_Agmt *ra);
+/* For replica release tuning */
+int agmt_get_WaitForAsyncResults(Repl_Agmt *ra);
+
PRBool ldif_dump_is_running();
void windows_init_agreement_from_entry(Repl_Agmt *ra, Slapi_Entry *e);
diff --git a/ldap/servers/plugins/replication/repl5_agmt.c
b/ldap/servers/plugins/replication/repl5_agmt.c
index d27648e..2ccb7ba 100644
--- a/ldap/servers/plugins/replication/repl5_agmt.c
+++ b/ldap/servers/plugins/replication/repl5_agmt.c
@@ -154,6 +154,8 @@ typedef struct repl5agmt {
* This is the duration (in msec) that the RA will pause before
sending the next entry
*/
Slapi_RWLock *attr_lock; /* RW lock for all the stripped attrs */
+ int WaitForAsyncResults; /* Pass to
DS_Sleep(PR_MillisecondsToInterval(WaitForAsyncResults))
+ * in repl5_inc_waitfor_async_results */
} repl5agmt;
/* Forward declarations */
@@ -315,7 +317,8 @@ agmt_new_from_entry(Slapi_Entry *e)
ra->port = slapi_entry_attr_get_int(e, type_nsds5ReplicaPort);
/* SSL, TLS, or other transport stuff */
ra->transport_flags = 0;
- agmt_set_transportinfo_no_lock(ra, e);
+ (void) agmt_set_transportinfo_no_lock(ra, e);
+ (void) agmt_set_WaitForAsyncResults(ra, e);
/* DN to use when binding. May be empty if certain SASL auth is to be used e.g. EXTERNAL
GSSAPI. */
ra->binddn = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaBindDN);
@@ -1727,6 +1730,27 @@ agmt_set_transportinfo_no_lock(Repl_Agmt *ra, const Slapi_Entry
*e)
return (rc);
}
+int
+agmt_set_WaitForAsyncResults(Repl_Agmt *ra, const Slapi_Entry *e)
+{
+ int wait = 0;
+ if (e) {
+ wait = slapi_entry_attr_get_int(e, type_nsds5WaitForAsyncResults);
+ }
+ if (wait <= 0) {
+ ra->WaitForAsyncResults = 100; /* 0.1 sec */
+ } else {
+ ra->WaitForAsyncResults = wait;
+ }
+ return 0;
+}
+
+int
+agmt_get_WaitForAsyncResults(Repl_Agmt *ra)
+{
+ return ra->WaitForAsyncResults;
+}
+
int
agmt_set_transportinfo_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
{
diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c
b/ldap/servers/plugins/replication/repl5_agmtlist.c
index e414e0b..5b419c6 100644
--- a/ldap/servers/plugins/replication/repl5_agmtlist.c
+++ b/ldap/servers/plugins/replication/repl5_agmtlist.c
@@ -548,7 +548,8 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore,
Slapi_Entry
rc = SLAPI_DSE_CALLBACK_ERROR;
}
}
- else if (slapi_attr_types_equivalent(mods[i]->mod_type,
type_replicaProtocolTimeout)){
+ else if (slapi_attr_types_equivalent(mods[i]->mod_type,
type_replicaProtocolTimeout))
+ {
if (mods[i]->mod_op & LDAP_MOD_DELETE)
{
agmt_set_protocol_timeout(agmt, 0);
@@ -574,6 +575,14 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore,
Slapi_Entry
agmt_set_protocol_timeout(agmt, ptimeout);
}
}
+ else if (slapi_attr_types_equivalent(mods[i]->mod_type,
type_nsds5WaitForAsyncResults))
+ {
+ if (mods[i]->mod_op & LDAP_MOD_DELETE) {
+ (void) agmt_set_WaitForAsyncResults(agmt, NULL);
+ } else {
+ (void) agmt_set_WaitForAsyncResults(agmt, e);
+ }
+ }
else if (0 == windows_handle_modify_agreement(agmt, mods[i]->mod_type, e))
{
slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
"agmtlist_modify_callback: "
diff --git a/ldap/servers/plugins/replication/repl5_inc_protocol.c
b/ldap/servers/plugins/replication/repl5_inc_protocol.c
index f18fde5..bd4edeb 100644
--- a/ldap/servers/plugins/replication/repl5_inc_protocol.c
+++ b/ldap/servers/plugins/replication/repl5_inc_protocol.c
@@ -110,6 +110,7 @@ typedef struct result_data
int last_message_id_received;
int flowcontrol_detection;
int result; /* The UPDATE_TRANSIENT_ERROR etc */
+ int WaitForAsyncResults;
} result_data;
/* Various states the incremental protocol can pass through */
@@ -492,18 +493,17 @@ repl5_inc_waitfor_async_results(result_data *rd)
slapi_log_error(SLAPI_LOG_REPL, NULL,
"repl5_inc_waitfor_async_results: %d %d\n",
rd->last_message_id_received, rd->last_message_id_sent);
- if (rd->last_message_id_received >= rd->last_message_id_sent)
- {
+ if (rd->last_message_id_received >= rd->last_message_id_sent) {
/* If so then we're done */
done = 1;
- }
- if (rd->abort && (rd->result == UPDATE_CONNECTION_LOST))
- {
+ } else if (rd->abort && (rd->result == UPDATE_CONNECTION_LOST)) {
done = 1; /* no connection == no more results */
}
PR_Unlock(rd->lock);
- /* If not then sleep a bit */
- DS_Sleep(PR_SecondsToInterval(1));
+ if (!done) {
+ /* If not then sleep a bit */
+ DS_Sleep(PR_MillisecondsToInterval(rd->WaitForAsyncResults));
+ }
loops++;
/* If we sleep forever then we can conclude that something bad happened, and bail...
*/
/* Arbitrary 30 second delay : basically we should only expect to wait as long as it
takes to process a few operations, which should be on the order of a second at most */
@@ -1912,6 +1912,7 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector,
PRUint32 *nu
{
/* We need to ensure that we wait until all the responses have been received from our
operations */
if (return_value != UPDATE_CONNECTION_LOST) {
+ rd->WaitForAsyncResults = agmt_get_WaitForAsyncResults(prp->agmt);
/* if connection was lost/closed, there will be nothing to read */
repl5_inc_waitfor_async_results(rd);
}
diff --git a/ldap/servers/plugins/replication/repl_globals.c
b/ldap/servers/plugins/replication/repl_globals.c
index e2157fa..7f4fcd2 100644
--- a/ldap/servers/plugins/replication/repl_globals.c
+++ b/ldap/servers/plugins/replication/repl_globals.c
@@ -141,6 +141,7 @@ const char *type_nsds5ReplicaEnabled =
"nsds5ReplicaEnabled";
const char *type_nsds5ReplicaStripAttrs = "nsds5ReplicaStripAttrs";
const char* type_nsds5ReplicaFlowControlWindow =
"nsds5ReplicaFlowControlWindow";
const char* type_nsds5ReplicaFlowControlPause =
"nsds5ReplicaFlowControlPause";
+const char *type_nsds5WaitForAsyncResults = "nsds5ReplicaWaitForAsyncResults";
/* windows sync specific attributes */
const char *type_nsds7WindowsReplicaArea = "nsds7WindowsReplicaSubtree";
commit 9576982b676d663139350a5aeb551ff19abedcba
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Mar 3 15:42:58 2015 -0800
Ticket 47431 - CI test: added test cases for ticket 47431
Summary: Duplicate values for the attribute nsslapd-pluginarg are not handled
correctly
Test cases:
1) cn=7-bit check,cn=plugins,cn=config
nsslapd-pluginarg0: uid
nsslapd-pluginarg1: mail
nsslapd-pluginarg2: userpassword <== repeat 27 times
nsslapd-pluginarg3: ,
nsslapd-pluginarg4: dc=test,dc=com
==>
The duplicated values are removed by str2entry_dupcheck as follows:
[..] - str2entry_dupcheck: 27 duplicate values for attribute type
nsslapd-pluginarg2
detected in entry cn=7-bit check,cn=plugins,cn=config. Extra values
ignored.
2) cn=7-bit check,cn=plugins,cn=config
nsslapd-pluginarg0: uid
nsslapd-pluginarg0: mail
nsslapd-pluginarg1: userpassword
nsslapd-pluginarg2: ,
nsslapd-pluginarg3: dc=test,dc=com
==>
nsslapd-pluginarg0: uid
nsslapd-pluginarg1: mail
nsslapd-pluginarg2: userpassword
nsslapd-pluginarg3: ,
nsslapd-pluginarg4: dc=test,dc=com
3) cn=7-bit check,cn=plugins,cn=config
nsslapd-pluginarg1: uid
nsslapd-pluginarg3: mail
nsslapd-pluginarg5: userpassword
nsslapd-pluginarg7: ,
nsslapd-pluginarg9: dc=test,dc=com
==>
nsslapd-pluginarg0: uid
nsslapd-pluginarg1: mail
nsslapd-pluginarg2: userpassword
nsslapd-pluginarg3: ,
nsslapd-pluginarg4: dc=test,dc=com
Note: it does not modify the config params. The syntax errors are
internally translated and processed accordingly.
https://fedorahosted.org/389/ticket/47431
Reviewed by rmeggins(a)redhat.com (Thank you, Rich!!)
diff --git a/dirsrvtests/tickets/ticket47431_test.py
b/dirsrvtests/tickets/ticket47431_test.py
new file mode 100644
index 0000000..893a303
--- /dev/null
+++ b/dirsrvtests/tickets/ticket47431_test.py
@@ -0,0 +1,251 @@
+import os
+import sys
+import time
+import ldap
+import logging
+import pytest
+from lib389 import DirSrv, Entry, tools, tasks
+from lib389.tools import DirSrvTools
+from lib389._constants import *
+from lib389.properties import *
+from lib389.tasks import *
+from lib389.utils import *
+
+logging.getLogger(__name__).setLevel(logging.DEBUG)
+log = logging.getLogger(__name__)
+
+installation1_prefix = None
+
+DN_7BITPLUGIN="cn=7-bit check,%s" % DN_PLUGIN
+ATTRS = ["uid", "mail", "userpassword", ",",
SUFFIX, None]
+
+class TopologyStandalone(object):
+ def __init__(self, standalone):
+ standalone.open()
+ self.standalone = standalone
+
+
+(a)pytest.fixture(scope="module")
+def topology(request):
+ global installation1_prefix
+ if installation1_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation1_prefix
+
+ # Creating standalone instance ...
+ standalone = DirSrv(verbose=False)
+ args_instance[SER_HOST] = HOST_STANDALONE
+ args_instance[SER_PORT] = PORT_STANDALONE
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
+ args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
+ args_standalone = args_instance.copy()
+ standalone.allocate(args_standalone)
+ instance_standalone = standalone.exists()
+ if instance_standalone:
+ standalone.delete()
+ standalone.create()
+ standalone.open()
+
+ # Clear out the tmp dir
+ standalone.clearTmpDir(__file__)
+
+ return TopologyStandalone(standalone)
+
+
+def test_ticket47431_0(topology):
+ '''
+ Enable 7 bit plugin
+ '''
+ log.info("Ticket 47431 - 0: Enable 7bit plugin...")
+ topology.standalone.plugins.enable(name=PLUGIN_7_BIT_CHECK)
+
+
+def test_ticket47431_1(topology):
+ '''
+ nsslapd-pluginarg0: uid
+ nsslapd-pluginarg1: mail
+ nsslapd-pluginarg2: userpassword <== repeat 27 times
+ nsslapd-pluginarg3: ,
+ nsslapd-pluginarg4: dc=example,dc=com
+
+ The duplicated values are removed by str2entry_dupcheck as follows:
+ [..] - str2entry_dupcheck: 27 duplicate values for attribute type nsslapd-pluginarg2
+ detected in entry cn=7-bit check,cn=plugins,cn=config. Extra values ignored.
+ '''
+
+ log.info("Ticket 47431 - 1: Check 26 duplicate values are treated as
one...")
+ expected = "str2entry_dupcheck: .* duplicate values for attribute type
nsslapd-pluginarg2 detected in entry cn=7-bit check,cn=plugins,cn=config."
+
+ log.debug('modify_s %s' % DN_7BITPLUGIN)
+ try:
+ topology.standalone.modify_s(DN_7BITPLUGIN,
+ [(ldap.MOD_REPLACE, 'nsslapd-pluginarg0',
"uid"),
+ (ldap.MOD_REPLACE, 'nsslapd-pluginarg1',
"mail"),
+ (ldap.MOD_REPLACE, 'nsslapd-pluginarg2',
"userpassword"),
+ (ldap.MOD_REPLACE, 'nsslapd-pluginarg3',
","),
+ (ldap.MOD_REPLACE, 'nsslapd-pluginarg4',
SUFFIX)])
+ except ValueError:
+ log.error('modify failed: Some problem occured with a value that was
provided')
+ assert False
+
+ arg2 = "nsslapd-pluginarg2: userpassword"
+ topology.standalone.stop(timeout=10)
+ dse_ldif = topology.standalone.confdir + '/dse.ldif'
+ os.system('mv %s %s.47431' % (dse_ldif, dse_ldif))
+ os.system('sed -e
"s/\\(%s\\)/\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1/"
%s.47431 > %s' % (arg2, dse_ldif, dse_ldif))
+ topology.standalone.start(timeout=10)
+
+ cmdline = 'egrep -i "%s" %s' % (expected,
topology.standalone.errlog)
+ p = os.popen(cmdline, "r")
+ line = p.readline()
+ if line == "":
+ log.error('Expected error "%s" not logged in %s' % (expected,
topology.standalone.errlog))
+ assert False
+ else:
+ log.debug('line: %s' % line)
+ log.info('Expected error "%s" logged in %s' % (expected,
topology.standalone.errlog))
+
+
+ log.info("Ticket 47431 - 1: done")
+
+
+def test_ticket47431_2(topology):
+ '''
+ nsslapd-pluginarg0: uid
+ nsslapd-pluginarg0: mail
+ nsslapd-pluginarg1: userpassword
+ nsslapd-pluginarg2: ,
+ nsslapd-pluginarg3: dc=example,dc=com
+ ==>
+ nsslapd-pluginarg0: uid
+ nsslapd-pluginarg1: mail
+ nsslapd-pluginarg2: userpassword
+ nsslapd-pluginarg3: ,
+ nsslapd-pluginarg4: dc=example,dc=com
+ Should be logged in error log:
+ [..] NS7bitAttr_Init - 0: uid
+ [..] NS7bitAttr_Init - 1: userpassword
+ [..] NS7bitAttr_Init - 2: mail
+ [..] NS7bitAttr_Init - 3: ,
+ [..] NS7bitAttr_Init - 4: dc=example,dc=com
+ '''
+
+ log.info("Ticket 47431 - 2: Check two values belonging to one arg is
fixed...")
+
+ try:
+ topology.standalone.modify_s(DN_7BITPLUGIN,
+ [(ldap.MOD_REPLACE, 'nsslapd-pluginarg0',
"uid"),
+ (ldap.MOD_ADD, 'nsslapd-pluginarg0',
"mail"),
+ (ldap.MOD_REPLACE, 'nsslapd-pluginarg1',
"userpassword"),
+ (ldap.MOD_REPLACE, 'nsslapd-pluginarg2',
","),
+ (ldap.MOD_REPLACE, 'nsslapd-pluginarg3',
SUFFIX),
+ (ldap.MOD_DELETE, 'nsslapd-pluginarg4',
None)])
+ except ValueError:
+ log.error('modify failed: Some problem occured with a value that was
provided')
+ assert False
+
+ # PLUGIN LOG LEVEL
+ topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE,
'nsslapd-errorlog-level', '65536')])
+
+ topology.standalone.restart(timeout=10)
+
+ cmdline = 'egrep -i %s %s' % ("NS7bitAttr_Init",
topology.standalone.errlog)
+ p = os.popen(cmdline, "r")
+ i = 0
+ while ATTRS[i]:
+ line = p.readline()
+ log.debug('line - %s' % line)
+ log.debug('ATTRS[%d] %s' % (i, ATTRS[i]))
+ if line == "":
+ break
+ elif line.find(ATTRS[i]) >= 0:
+ log.debug('%s was logged' % ATTRS[i])
+ else:
+ log.error('%s was not logged.' % ATTRS[i])
+ assert False
+ i = i + 1
+
+ log.info("Ticket 47431 - 2: done")
+
+
+def test_ticket47431_3(topology):
+ '''
+ nsslapd-pluginarg1: uid
+ nsslapd-pluginarg3: mail
+ nsslapd-pluginarg5: userpassword
+ nsslapd-pluginarg7: ,
+ nsslapd-pluginarg9: dc=example,dc=com
+ ==>
+ nsslapd-pluginarg0: uid
+ nsslapd-pluginarg1: mail
+ nsslapd-pluginarg2: userpassword
+ nsslapd-pluginarg3: ,
+ nsslapd-pluginarg4: dc=example,dc=com
+ Should be logged in error log:
+ [..] NS7bitAttr_Init - 0: uid
+ [..] NS7bitAttr_Init - 1: userpassword
+ [..] NS7bitAttr_Init - 2: mail
+ [..] NS7bitAttr_Init - 3: ,
+ [..] NS7bitAttr_Init - 4: dc=example,dc=com
+ '''
+
+ log.info("Ticket 47431 - 3: Check missing args are fixed...")
+
+ try:
+ topology.standalone.modify_s(DN_7BITPLUGIN,
+ [(ldap.MOD_DELETE, 'nsslapd-pluginarg0',
None),
+ (ldap.MOD_REPLACE, 'nsslapd-pluginarg1',
"uid"),
+ (ldap.MOD_DELETE, 'nsslapd-pluginarg2',
None),
+ (ldap.MOD_REPLACE, 'nsslapd-pluginarg3',
"mail"),
+ (ldap.MOD_REPLACE, 'nsslapd-pluginarg5',
"userpassword"),
+ (ldap.MOD_REPLACE, 'nsslapd-pluginarg7',
","),
+ (ldap.MOD_REPLACE, 'nsslapd-pluginarg9',
SUFFIX)])
+ except ValueError:
+ log.error('modify failed: Some problem occured with a value that was
provided')
+ assert False
+
+ # PLUGIN LOG LEVEL
+ topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE,
'nsslapd-errorlog-level', '65536')])
+
+ topology.standalone.stop(timeout=10)
+ os.system('mv %s %s.47431' % (topology.standalone.errlog,
topology.standalone.errlog))
+ os.system('touch %s' % (topology.standalone.errlog))
+ topology.standalone.start(timeout=10)
+
+ cmdline = 'egrep -i %s %s' % ("NS7bitAttr_Init",
topology.standalone.errlog)
+ p = os.popen(cmdline, "r")
+ i = 0
+ while ATTRS[i]:
+ line = p.readline()
+ if line == "":
+ break
+ elif line.find(ATTRS[i]) >= 0:
+ log.debug('%s was logged' % ATTRS[i])
+ else:
+ log.error('%s was not logged.' % ATTRS[i])
+ assert False
+ i = i + 1
+
+ log.info("Ticket 47431 - 3: done")
+ log.info('Test complete')
+
+
+def test_ticket47431_final(topology):
+ topology.standalone.delete()
+ log.info('Testcase PASSED')
+
+
+def run_isolated():
+ global installation1_prefix
+ installation1_prefix = None
+
+ topo = topology(True)
+ test_ticket47431_0(topo)
+ test_ticket47431_1(topo)
+ test_ticket47431_2(topo)
+ test_ticket47431_3(topo)
+ test_ticket47431_final(topo)
+
+
+if __name__ == '__main__':
+ run_isolated()
+
commit 6aa9fdccbc9910c3dfacb22ba22596c9b514b5b4
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Mon Mar 2 18:14:03 2015 -0800
Ticket #47431 - Duplicate values for the attribute nsslapd-pluginarg are not handled
correctly
Description:
In case nsslapd-pluginargN has simple syntax errors, recover them.
1) nsslapd-pluginargN: val_1
nsslapd-pluginargN: val_2
nsslapd-pluginargN+1: val_3
==>
nsslapd-pluginargN: val_1
nsslapd-pluginargN+1: val_2
nsslapd-pluginargN+2: val_3
Note: val_2 used to be ignored.
2) nsslapd-pluginargM: val_1
nsslapd-pluginargN: val_2
nsslapd-pluginargN+1: val_3
where N != M + 1
==>
nsslapd-pluginargM: val_1
nsslapd-pluginargM+1: val_2
nsslapd-pluginargM+2: val_3
Note: nsslapd-pluginargN and the rest were not loaded.
Reviewed by rmeggins(a)redhat.com (Thank you, Rich!!)
https://fedorahosted.org/389/ticket/47431
diff --git a/ldap/servers/plugins/uiduniq/7bit.c b/ldap/servers/plugins/uiduniq/7bit.c
index c84c79c..a96951e 100644
--- a/ldap/servers/plugins/uiduniq/7bit.c
+++ b/ldap/servers/plugins/uiduniq/7bit.c
@@ -288,7 +288,7 @@ preop_add(Slapi_PBlock *pb)
firstSubtree++;
argc--;
- for (attrName = argv; strcmp(*attrName, ",") != 0; attrName++ )
+ for (attrName = argv; attrName && *attrName && strcmp(*attrName,
","); attrName++)
{
/*
* if the attribute is userpassword, check unhashed user password
@@ -300,15 +300,14 @@ preop_add(Slapi_PBlock *pb)
if ( strcasecmp(*attrName, "userpassword") == 0 )
{
origpwd = pwd = slapi_get_first_clear_text_pw(e);
- if (pwd == NULL)
- {
+ if (pwd == NULL) {
continue;
}
val.bv_val = pwd;
val.bv_len = strlen(val.bv_val);
} else {
attr_name = *attrName;
- err = slapi_entry_attr_find(e, attr_name, &attr);
+ err = slapi_entry_attr_find(e, attr_name, &attr);
if (err) continue; /* break;*/ /* no 7-bit attribute */
}
@@ -745,11 +744,16 @@ NS7bitAttr_Init(Slapi_PBlock *pb)
err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGV, &argv);
if (err) break;
+ for (attr_count = 0; argv && argv[attr_count]; attr_count++) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, "NS7bitAttr_Init", "%d:
%s\n",
+ attr_count, argv[attr_count]);
+ }
/*
* Arguments before "," are the 7-bit attribute names. Arguments after
* "," are the subtree DN's.
*/
if (argc < 1) { err = -2; break; } /* missing arguments */
+ attr_count = 0;
for(;*argv && strcmp(*argv, ",") != 0 && argc > 0;
attr_count++, argc--, argv++);
if (argc == 0) { err = -3; break; } /* no comma separator */
if(attr_count == 0){ err = -4; break; } /* no attributes */
diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c
index 4df2eb5..2b3428e 100644
--- a/ldap/servers/slapd/plugin.c
+++ b/ldap/servers/slapd/plugin.c
@@ -2693,24 +2693,25 @@ plugin_setup(Slapi_Entry *plugin_entry, struct slapi_componentid
*group,
slapi_plugin_init_fnptr p_initfunc, int add_entry, char *returntext)
{
int ii = 0;
- char attrname[BUFSIZ];
- char *value = 0;
+ char attrname[SLAPD_TYPICAL_ATTRIBUTE_NAME_MAX_LENGTH];
+ char *value = NULL;
+ char **values = NULL;
struct slapdplugin *plugin = NULL;
struct slapdplugin **plugin_list = NULL;
- struct slapi_componentid *cid=NULL;
+ struct slapi_componentid *cid = NULL;
const char *existname = 0;
slapi_plugin_init_fnptr initfunc = p_initfunc;
Slapi_PBlock pb;
int status = 0;
int enabled = 1;
char *configdir = 0;
+ int skipped;
attrname[0] = '\0';
if (!slapi_entry_get_sdn_const(plugin_entry))
{
- LDAPDebug(LDAP_DEBUG_ANY, "plugin_setup: DN is missing from the plugin.\n",
- 0, 0, 0);
+ LDAPDebug0Args(LDAP_DEBUG_ANY, "plugin_setup: DN is missing from the
plugin.\n");
PR_snprintf (returntext, SLAPI_DSE_RETURNTEXT_SIZE,"Plugin is missing dn.");
return -1;
}
@@ -2815,8 +2816,7 @@ plugin_setup(Slapi_Entry *plugin_entry, struct slapi_componentid
*group,
slapi_ch_free((void**)&value);
}
- if (!(value = slapi_entry_attr_get_charptr(plugin_entry,
- ATTR_PLUGIN_INITFN)))
+ if (!(value = slapi_entry_attr_get_charptr(plugin_entry, ATTR_PLUGIN_INITFN)))
{
if (!initfunc)
{
@@ -2906,13 +2906,35 @@ plugin_setup(Slapi_Entry *plugin_entry, struct slapi_componentid
*group,
value = 0;
ii = 0;
PR_snprintf(attrname, sizeof(attrname), "%s%d", ATTR_PLUGIN_ARG, ii);
- while ((value = slapi_entry_attr_get_charptr(plugin_entry, attrname)) != NULL)
- {
- charray_add(&plugin->plg_argv, value);
- plugin->plg_argc++;
- ++ii;
- PR_snprintf(attrname, sizeof(attrname), "%s%d", ATTR_PLUGIN_ARG, ii);
- }
+ skipped = 0;
+#define MAXSKIPPED 10 /* Max allowed missing args */
+ do {
+ /*
+ * nsslapd-pluginarg0: val0
+ * nsslapd-pluginarg0: val00
+ * nsslapd-pluginarg2: val2
+ * nsslapd-pluginarg5: val5
+ * ==>
+ * treated as
+ * nsslapd-pluginarg0: val0
+ * nsslapd-pluginarg1: val00
+ * nsslapd-pluginarg2: val2
+ * nsslapd-pluginarg3: val5
+ */
+ char **vp = values = slapi_entry_attr_get_charray(plugin_entry, attrname);
+ if (values) {
+ charray_add(&plugin->plg_argv, slapi_ch_strdup(*vp));
+ plugin->plg_argc++;
+ for (vp++; vp && *vp; vp++) {
+ charray_add(&plugin->plg_argv, slapi_ch_strdup(*vp));
+ plugin->plg_argc++;
+ }
+ charray_free(values);
+ } else {
+ skipped++;
+ }
+ PR_snprintf(attrname, sizeof(attrname), "%s%d", ATTR_PLUGIN_ARG, ++ii);
+ } while (skipped < MAXSKIPPED);
memset((char *)&pb, '\0', sizeof(pb));
slapi_pblock_set(&pb, SLAPI_PLUGIN, plugin);