externalchangelog_common_ecl_tests.xml revision 75e4d72341a69fa125aeab6e326e49a5422a9eac
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE stax SYSTEM "/shared/stax.dtd">
<!--
! CDDL HEADER START
!
! The contents of this file are subject to the terms of the
! Common Development and Distribution License, Version 1.0 only
! (the "License"). You may not use this file except in compliance
! with the License.
!
! You can obtain a copy of the license at
! trunk/opends/resource/legal-notices/OpenDS.LICENSE
! or https://OpenDS.dev.java.net/OpenDS.LICENSE.
! See the License for the specific language governing permissions
! and limitations under the License.
!
! When distributing Covered Code, include this CDDL HEADER in each
! file and include the License file at
! trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
! add the following below this CDDL HEADER, with the fields enclosed
! by brackets "[]" replaced with your own identifying information:
! Portions Copyright [yyyy] [name of copyright owner]
!
! CDDL HEADER END
!
! Copyright 2009-2010 Sun Microsystems, Inc.
! Portions Copyright 2011-2013 ForgeRock AS.
! -->
<stax>
<defaultcall function="common_ecl_tests"/>
<function name="common_ecl_tests">
<function-prolog>
This function contains the common testcases that can be run on any of the
ECL modes: opends proprietary mode, changelog draft-compatible mode, or
dsee-compatible mode.
</function-prolog>
<function-map-args>
<function-arg-def name="ecl_mode"
type="optional"
default="'opends'">
<function-arg-description>
External Changelog mode: opends, draft, dsee
</function-arg-description>
<function-arg-property name="type" value="string"/>
</function-arg-def>
</function-map-args>
<sequence>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Setup
#@TestID Setup
#@TestPurpose Set up environment for External Changelog tests
#@TestPreamble
#@TestSteps Reset replicated data
#@TestPostamble
#@TestResult Success if the data reset succeeds
-->
<testcase name="getTestCaseName('%s - Setup' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Setup. \
Set up environment for External Changelog tests' % ecl_mode
</message>
<message>
'Common ECL tests: reset data'
</message>
<!-- Pre-initialise the servers in the topology -->
<call function="'preInitializeReplication'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstanceAdminPort' : master.getAdminPort(),
'localOnly' : False,
'replicationDnList' : [synchroSuffix],
'adminUID' : adminUID,
'adminPswd' : adminPswd
}
</call>
<!-- Stop "master" Directory Server -->
<call function="'StopDsWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsHost' : masterHost,
'dsAdminPort' : master.getAdminPort(),
'dsBindDN' : master.getRootDn(),
'dsBindPwd' : master.getRootPwd()
}
</call>
<!-- Import data into "master" Directory Server -->
<call function="'ImportLdifWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'backEnd' : DIRECTORY_INSTANCE_BE,
'ldifFile' : '%s/replication/Example.ldif' \
% masterDataDir
}
</call>
<!-- Start the Directory Server -->
<call function="'StartDsWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath
}
</call>
<!-- Wait for DS to start -->
<call function="'isAlive'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort() ,
'dsInstanceDn' : master.getRootDn() ,
'dsInstancePswd' : master.getRootPwd() ,
'noOfLoops' : 10 ,
'noOfMilliSeconds' : 2000
}
</call>
<!-- Perform the total update -->
<call function="'initializeReplication'">
{ 'location' : clientHost,
'dsPath' : clientPath,
'sourceInstanceHost' : masterHost,
'sourceInstanceAdminPort' : master.getAdminPort(),
'replicationDnList' : ['o=example']
}
</call>
<message>
'Common ECL tests: start test execution in mode: %s' % ecl_mode
</message>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<script>
if ecl_mode == 'opends':
# initialise the searchIndex (lastCookie) value to that for the
# first ECL request
searchIndex = ';'
else :
# initialise the searchIndex (first changenumber) value to that of the
# first change: 1
searchIndex = '1'
nextIndex = None
addOperationalAttrs = """"*" creatorsname createtimestamp entryuuid"""
modOperationalAttrs = """"*" modifiersname modifytimestamp entryuuid"""
class Entry:
def __init__(self, rdn, suffix):
self.userDn = '%s,ou=People,%s' \
% (rdn, suffix)
self.suffix = suffix
self.listAttr = []
self.listAttr.append('objectclass:top')
self.listAttr.append('objectclass:organizationalperson')
self.listAttr.append('objectclass:inetorgperson')
self.listAttr.append('objectclass:person')
def getDn(self):
return self.userDn
def getSuffix(self):
return self.suffix
def getAttrList(self):
return self.listAttr
def addAttr(self, attrType, attrValue):
self.listAttr.append('%s:%s' % (attrType, attrValue))
</script>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Add_1
#@TestID Add_1
#@TestPurpose Verify add operation is recorded properly in the
external changelog on each replication server
#@TestPreamble
#@TestSteps Add entry to server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Add_1' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Add_1. \
Verify add operation is recorded properly in the external \
changelog on each replication server' % ecl_mode
</message>
<!-- Add entry to "master" server -->
<script>
myEntry = Entry('cn=a', synchroSuffix)
myEntry.addAttr('sn', 'a')
myEntry.addAttr('description', '1')
myEntry.addAttr('description', '2')
myEntry.addAttr('uid', 'A')
addedEntry = None
eclEntry = None
</script>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
addedEntry = STAXResult
myTargetDN = addedEntry['dn'][0]
myChangeType = 'add'
myChangeTime = addedEntry['createtimestamp'][0]
myTargetEntryUUID = addedEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myChanges = {}
for attr in addedEntry.keys():
if (attr != 'dn') and (attr != 'changelogcookie') :
myChanges[attr] = addedEntry[attr]
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s' %\
(replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % \
nextIndex
</message>
<if expr="addedEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
addedEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Modify_add
#@TestID Modify_add
#@TestPurpose Verify modify-add operation is recorded properly
in the external changelog on each repl server
#@TestPreamble
#@TestSteps Modify entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Modify_add' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Modify_add. \
Verify modify-add operation is recorded properly in the \
external changelog on each repl server' % ecl_mode
</message>
<script>
modEntry = None
eclEntry = None
</script>
<!-- Modify entry on one of the servers -->
<call function="'modifyAnAttribute'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : myEntry.getDn(),
'attributeName' : 'description',
'newAttributeValue' : '3',
'changetype' : 'add'
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntry = STAXResult
myTargetDN = modEntry['dn'][0]
myChangeType = 'modify'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myModifiersName = modEntry['modifiersname'][0]
myModifyTimestamp = modEntry['modifytimestamp'][0]
myChanges = []
myChanges.append(['add', 'description', '3'])
myChanges.append(['replace', 'modifiersname', myModifiersName])
myChanges.append(['replace', 'modifytimestamp', myModifyTimestamp])
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read modified entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Modify_delete
#@TestID Modify_delete
#@TestPurpose Verify modify-del operation is recorded properly
in the external changelog on each repl server
#@TestPreamble
#@TestSteps Modify entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Modify_delete' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Modify_delete. \
Verify modify-del operation is recorded properly in the \
external changelog on each repl server' % ecl_mode
</message>
<script>
modEntry = None
eclEntry = None
valuesToDelete = []
valuesToDelete.append('description:1')
</script>
<!-- Modify entry on one of the servers -->
<call function="'modifyAnAttribute'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : myEntry.getDn(),
'listAttributes' : valuesToDelete,
'changetype' : 'delete'
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntry = STAXResult
myTargetDN = modEntry['dn'][0]
myChangeType = 'modify'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myModifiersName = modEntry['modifiersname'][0]
myModifyTimestamp = modEntry['modifytimestamp'][0]
myChanges = []
myChanges.append(['delete', 'description', '1'])
myChanges.append(['replace', 'modifiersname', myModifiersName])
myChanges.append(['replace', 'modifytimestamp', myModifyTimestamp])
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read modified entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Modify_replace
#@TestID Modify_replace
#@TestPurpose Verify modify-replace operation is well recorded
in the external changelog on each repl server
#@TestPreamble
#@TestSteps Modify entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Modify_replace' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Modify_replace. \
Verify modify-replace operation is recorded properly in the \
external changelog on each repl server' % ecl_mode
</message>
<script>
modEntry = None
eclEntry = None
</script>
<!-- Modify entry on one of the servers -->
<call function="'modifyAnAttribute'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : myEntry.getDn(),
'attributeName' : 'description',
'newAttributeValue' : 'new',
'changetype' : 'replace'
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntry = STAXResult
myTargetDN = modEntry['dn'][0]
myChangeType = 'modify'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myModifiersName = modEntry['modifiersname'][0]
myModifyTimestamp = modEntry['modifytimestamp'][0]
myChanges = []
myChanges.append(['replace', 'description', 'new'])
myChanges.append(['replace', 'modifiersname', myModifiersName])
myChanges.append(['replace', 'modifytimestamp', myModifyTimestamp])
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read modified entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Modrdn_deleteoldrdn_true
#@TestID Modrdn_deleteoldrdn_true
#@TestPurpose Verify modrdn operation is recorded properly
in the external changelog on each repl server
#@TestPreamble
#@TestSteps Modrdn entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Modrdn_deleteoldrdn_true' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Modrdn_deleteoldrdn_true. \
Verify modrdn operation is recorded properly in the \
external changelog on each repl server' % ecl_mode
</message>
<script>
modEntry = None
eclEntry = None
oldEntry = myEntry
newRdn = 'cn=b'
newEntry = Entry(newRdn, synchroSuffix)
</script>
<!-- Modify entry on one of the servers -->
<call function="'modifyDn'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : oldEntry.getDn(),
'newRDN' : newRdn
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : newEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntry = STAXResult
myTargetDN = oldEntry.getDn()
myChangeType = 'modrdn'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myNewRDN = newRdn
myDeleteOldRDN = 'true'
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(newEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'newRDN' : myNewRDN,
'deleteOldRDN' : myDeleteOldRDN
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Modrdn_deleteoldrdn_false
#@TestID Modrdn_deleteoldrdn_false
#@TestPurpose Verify modrdn operation is recorded properly
in the external changelog on each repl server
#@TestPreamble
#@TestSteps Modrdn entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Modrdn_deleteoldrdn_false' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Modrdn_deleteoldrdn_false. \
Verify modrdn operation is recorded properly in the \
external changelog on each repl server' % ecl_mode
</message>
<script>
modEntry = None
eclEntry = None
oldEntry = newEntry
newRdn = 'cn=c'
newEntry = Entry(newRdn, synchroSuffix)
</script>
<!-- Modify entry on one of the servers -->
<call function="'modifyDn'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : oldEntry.getDn(),
'newRDN' : newRdn,
'deleteOldRDN' : 0
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : newEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntry = STAXResult
myTargetDN = oldEntry.getDn()
myChangeType = 'modrdn'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myNewRDN = newRdn
myDeleteOldRDN = 'false'
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(newEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'newRDN' : myNewRDN,
'deleteOldRDN' : myDeleteOldRDN
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Delete_1
#@TestID Delete_1
#@TestPurpose Verify delete operation is recorded properly
in the external changelog on each repl server
#@TestPreamble
#@TestSteps Delete entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Delete_1' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Delete_1. \
Verify delete operation is recorded properly in the \
external changelog on each repl server' % ecl_mode
</message>
<script>
delEntry = None
eclEntry = None
</script>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : newEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
delEntry = STAXResult
myTargetDN = delEntry['dn'][0]
myChangeType = 'delete'
myTargetEntryUUID = delEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(newEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<!-- Delete entry on one of the servers -->
<call function="'DeleteEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : newEntry.getDn()
}
</call>
<!-- Check delete worked on "master" server -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : newEntry.getDn(),
'dsFilter' : 'objectclass=*',
'expectedRC' : 32
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="delEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'targetEntryUUID' : myTargetEntryUUID
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
delEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Add_2
#@TestID Add_2
#@TestPurpose Verify add operation (of an entry with
userpassword) is recorded properly in the
external changelog on each replication server
#@TestPreamble
#@TestSteps Add entry to server A (with userpassword)
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Add_2' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Add_2. \
Verify add operation (of and entry with userpassword) is \
recorded properly in the external changelog on each \
replication server' % ecl_mode
</message>
<!-- Add entry to "master" server -->
<script>
myEntry = Entry('cn=user', synchroSuffix)
myEntry.addAttr('sn', 'user')
myEntry.addAttr('userpassword', 'password')
addedEntry = None
eclEntry = None
</script>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : '%s pwdChangedTime' % addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
addedEntry = STAXResult
myTargetDN = addedEntry['dn'][0]
myChangeType = 'add'
myChangeTime = addedEntry['createtimestamp'][0]
myTargetEntryUUID = addedEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myChanges = {}
for attr in addedEntry.keys():
if (attr != 'dn') and (attr != 'changelogcookie') :
myChanges[attr] = addedEntry[attr]
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s' %\
(replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="addedEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
addedEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Modify_replace_2
#@TestID Modify_replace_2
#@TestPurpose Verify modify-replace operation as non directory
manager is well recorded in the external
changelog on each repl server
#@TestPreamble
#@TestSteps Modify entry on server A (as non dir manager)
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Modify_replace_2' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Modify_replace_2. \
Verify modify-replace operation as non directory manager is \
recorded properly in the external changelog on each repl server' \
% ecl_mode
</message>
<script>
modEntry = None
eclEntry = None
</script>
<!-- Modify entry on one of the servers -->
<call function="'modifyAnAttribute'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : myEntry.getDn(),
'dsInstancePswd' : 'password',
'DNToModify' : myEntry.getDn(),
'attributeName' : 'userpassword',
'newAttributeValue' : 'newpass',
'changetype' : 'replace'
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : '%s pwdChangedTime' % modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntry = STAXResult
myTargetDN = modEntry['dn'][0]
myChangeType = 'modify'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myModifiersName = modEntry['modifiersname'][0]
myModifyTimestamp = modEntry['modifytimestamp'][0]
myUserPassword = modEntry['userpassword'][0]
myPwdChangedTime = modEntry['pwdchangedtime'][0]
myChanges = []
myChanges.append(['replace', 'userpassword', myUserPassword])
myChanges.append(['replace', 'pwdchangedtime', myPwdChangedTime])
myChanges.append(['replace', 'modifiersname', myModifiersName])
myChanges.append(['replace', 'modifytimestamp', myModifyTimestamp])
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read modified entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Last index
#@TestID Last index
#@TestPurpose Verify the last index (lastExternalChangelogCookie
or lastChangenumber) value matches that of the last
external changelog entry
#@TestPreamble
#@TestSteps Modify entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read index from last changelog entry on each server
#@TestSteps Read lastExternalchangelogCookie/lastChangenumber
from root DSE entry
#@TestSteps Check last index value against last ECL entry one
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Last index' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Last index. \
Verify the last index (lastExternalChangelogCookie or \
lastChangenumber) value matches that of the last external \
changelog entry' % ecl_mode
</message>
<script>
myEntryDn = 'cn=user,ou=People,%s' % synchroSuffix
newLoc = 'Montbonnot'
modEntry = None
eclEntry = None
</script>
<!-- Modify entry on "master" server -->
<call function="'modifyAnAttribute'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : myEntryDn,
'attributeName' : 'l',
'newAttributeValue' : newLoc,
'changetype' : 'add'
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<!-- Read last index from root DSE (lastExternalChangelogCookie /
! lastChangenumber) -->
<script>
lastIndexAttr = None
lastIndexValue = None
if ecl_mode == 'opends':
lastIndexAttr = 'lastexternalchangelogcookie'
else:
lastIndexAttr = 'lastchangenumber'
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<call function="'ldapSearchWithScript'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'base',
'dsBaseDN' : ' ',
'dsFilter' : 'objectclass=*',
'dsAttributes' : lastIndexAttr
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<script>
lastIndexValue = None
pendingValue = 0
for line in searchResult.splitlines():
notBlank = (len(line.strip()) != 0)
if line.strip().lower().startswith(lastIndexAttr):
# line corresponds to lastIndexAttr:_lastIndexValue_
lastIndexValue = line[line.find(':') + 1:].lstrip()
pendingValue = 1
elif (notBlank and pendingValue):
lastIndexValue += line.lstrip()
elif pendingValue:
pendingValue = 0
break
</script>
<message>
'Last index read from root DSE entry %s attribute: %s' % \
(lastIndexAttr, lastIndexValue)
</message>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read root DSE entry from server %s:%s' % \
(server.getHostname(), server.getPort())
</message>
</else>
</if>
<!-- Search changelog in the various replication servers -->
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
eclIndexValue = None
if ecl_mode == 'opends':
eclIndexValue = eclEntry['changelogcookie'][0]
nextIndex = eclEntry['changelogcookie'][0]
else:
eclIndexValue = eclEntry['changenumber'][0]
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="lastIndexValue != eclIndexValue">
<sequence>
<message log="1" level="'Error'">
'Last index %s:%s does not match value found in ECL \
entry %s : %s' % (lastIndexAttr, lastIndexValue,
eclEntry['dn'][0], eclIndexValue)
</message>
<call function="'testFailed'"/>
</sequence>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Failover (stop)
#@TestID Failover (stop)
#@TestPurpose Verify the external changelog can cope with a server
failover (server stopped)
#@TestPreamble
#@TestSteps Stop "consumer" servers
#@TestSteps Modify entry on server A
#@TestSteps Read entry from ldap server
#@TestSteps Start "consumer" servers
#@TestSteps Modify entry on server A
#@TestSteps Read entry from ldap server
#@TestSteps Verify servers in sync
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Failover (stop)' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Failover (stop). \
Verify the external changelog can cope with a server failover \
(server stopped)' % ecl_mode
</message>
<script>
myEntryDn = 'cn=user,ou=People,%s' % synchroSuffix
newDesc0 = 'Failover (stop) test - before server start'
newDesc1 = 'Failover (stop) test - after server start'
modEntries = []
modEntry = None
eclEntries = []
</script>
<!-- Stop the "consumer" servers -->
<call function="'stopServers'">
[consumerList]
</call>
<!-- Modify entry on "master" server -->
<call function="'modifyAnAttribute'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : myEntryDn,
'attributeName' : 'description',
'newAttributeValue' : newDesc0,
'changetype' : 'replace'
}
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntryDn,
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntries.append(STAXResult)
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read modified entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<!-- Start the "consumer" servers -->
<call function="'startServers'">
[consumerList]
</call>
<!-- Modify entry on "master" server -->
<call function="'modifyAnAttribute'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : myEntryDn,
'attributeName' : 'description',
'newAttributeValue' : newDesc1,
'changetype' : 'replace'
}
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntryDn,
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntries.append(STAXResult)
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read modified entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modifies -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the ECL entries as read from server %s:%s: \n%s' \
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
eclEntries = STAXResult
</script>
<if expr="len(modEntries) != len(eclEntries)">
<sequence>
<message log="1" level="'Error'">
'Number of added entries %s does not match number of ECL \
entries %s' % (len(modEntries), len(eclEntries))
</message>
<call function="'testFailed'"/>
</sequence>
</if>
<iterate var="eclEntry"
in="eclEntries"
indexvar="i">
<sequence>
<script>
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
modEntry = modEntries[i]
myTargetDN = modEntry['dn'][0]
myChangeType = 'modify'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myModifiersName = modEntry['modifiersname'][0]
myModifyTimestamp = modEntry['modifytimestamp'][0]
myDescription = modEntry['description'][0]
myChanges = []
myChanges.append(['replace', 'description', myDescription])
myChanges.append(['replace', 'modifiersname', myModifiersName])
myChanges.append(['replace', 'modifytimestamp', myModifyTimestamp])
if ecl_mode != 'opends':
myIntChangeNumber = int(searchIndex) + i
myChangeNumber = str(myIntChangeNumber)
else:
myChangeNumber = None
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
</iterate>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntries = []
moddEntry = None
eclEntries = []
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Failover (kill)
#@TestID Failover (kill)
#@TestPurpose Verify the external changelog can cope with a server
failover (server killed)
#@TestPreamble
#@TestSteps Kill "consumer" servers
#@TestSteps Modify entry on server A
#@TestSteps Read entry from ldap server
#@TestSteps Start "consumer" servers
#@TestSteps Modify entry on server A
#@TestSteps Read entry from ldap server
#@TestSteps Verify servers in sync
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Failover (kill)' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Failover (kill). \
Verify the external changelog can cope with a server failover \
(server killed)' % ecl_mode
</message>
<script>
myEntryDn = 'cn=user,ou=People,%s' % synchroSuffix
newDesc0 = 'Failover (kill) test - before server start'
newDesc1 = 'Failover (kill) test - after server start'
modEntries = []
modEntry = None
eclEntries = []
</script>
<!-- Kill the "consumer" servers -->
<paralleliterate var="server" in="consumerList" indexvar="i">
<sequence>
<script>
serverPath = '%s/%s' % (server.getDir(), OPENDSNAME)
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<!-- Kill server (simulate failover?) -->
<call function="'killDs'">
{ 'location' : server.getHostname(),
'dsPath' : serverPath
}
</call>
</sequence>
</paralleliterate>
<!-- Modify entry on "master" server -->
<call function="'modifyAnAttribute'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : myEntryDn,
'attributeName' : 'description',
'newAttributeValue' : newDesc0,
'changetype' : 'replace'
}
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntryDn,
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntries.append(STAXResult)
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read modified entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<!-- Start the "consumer" servers -->
<call function="'startServers'">
[consumerList]
</call>
<!-- Modify entry on "master" server -->
<call function="'modifyAnAttribute'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : myEntryDn,
'attributeName' : 'description',
'newAttributeValue' : newDesc1,
'changetype' : 'replace'
}
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntryDn,
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntries.append(STAXResult)
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read modified entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modifies -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the ECL entries as read from server %s:%s: \n%s' \
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
eclEntries = STAXResult
</script>
<if expr="len(modEntries) != len(eclEntries)">
<sequence>
<message log="1" level="'Error'">
'Number of added entries %s does not match number of ECL \
entries %s' % (len(modEntries), len(eclEntries))
</message>
<call function="'testFailed'"/>
</sequence>
</if>
<iterate var="eclEntry"
in="eclEntries"
indexvar="i">
<sequence>
<script>
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
modEntry = modEntries[i]
myTargetDN = modEntry['dn'][0]
myChangeType = 'modify'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myModifiersName = modEntry['modifiersname'][0]
myModifyTimestamp = modEntry['modifytimestamp'][0]
myDescription = modEntry['description'][0]
myChanges = []
myChanges.append(['replace', 'description', myDescription])
myChanges.append(['replace', 'modifiersname', myModifiersName])
myChanges.append(['replace', 'modifytimestamp', myModifyTimestamp])
if ecl_mode != 'opends':
myIntChangeNumber = int(searchIndex) + i
myChangeNumber = str(myIntChangeNumber)
else:
myChangeNumber = None
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
</iterate>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntries = []
moddEntry = None
eclEntries = []
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Multiple add
(single server)
#@TestID Multiple add (single server)
#@TestPurpose Verify multiple add operations on a single server
are recorded properly in the external changelog on
each replication server
#@TestPreamble
#@TestSteps Add multiple entries to server A
#@TestSteps Verify servers in sync
#@TestSteps Read entries from ldap server
#@TestSteps Read changelog entries on each repl server
#@TestSteps Check changelog entries against expected values and
order
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Multiple add (single server)' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Multiple add (single server). \
Verify multiple add operations on a single server are recorded \
properly in the external changelog on each replication server' \
% ecl_mode
</message>
<!-- Add entry to "master" server -->
<script>
myEntries = []
for i in [1,2,3]:
myEntry = Entry('cn=user-%s' % i, synchroSuffix)
myEntry.addAttr('uid', 'U-%s' % i)
myEntry.addAttr('sn', 'Multiple add')
myEntries.append(myEntry)
addedEntries = []
eclEntries = []
</script>
<iterate var="myEntry" in="myEntries">
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
</iterate>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : synchroSuffix,
'dsFilter' : 'sn=Multiple add',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the entries as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
addedEntries = STAXResult
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entries from server %s:%s' % \
(masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the ECL entries as read from server %s:%s: \n%s' \
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
eclEntries = STAXResult
</script>
<if expr="len(addedEntries) != len(eclEntries)">
<sequence>
<message log="1" level="'Error'">
'Number of added entries %s does not match number of ECL \
entries %s' % (len(addedEntries), len(eclEntries))
</message>
<call function="'testFailed'"/>
</sequence>
</if>
<iterate var="eclEntry"
in="eclEntries"
indexvar="i">
<sequence>
<script>
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
addedEntry = addedEntries[i]
myTargetDN = addedEntry['dn'][0]
myChangeType = 'add'
myChangeTime = addedEntry['createtimestamp'][0]
myTargetEntryUUID = addedEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myChanges = {}
for attr in addedEntry.keys():
if (attr != 'dn') and (attr != 'changelogcookie') :
myChanges[attr] = addedEntry[attr]
if ecl_mode != 'opends':
myIntChangeNumber = int(searchIndex) + i
myChangeNumber = str(myIntChangeNumber)
else:
myChangeNumber = None
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="addedEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
</iterate>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
addedEntries = []
addedEntry = None
eclEntries = []
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Multiple add
(multiple servers)
#@TestID Multiple add (multiple servers)
#@TestPurpose Verify multiple add operations on multiple servers
are recorded properly in the external changelog on
each replication server
#@TestPreamble
#@TestSteps Add multiple entries to different servers
#@TestSteps Verify servers in sync
#@TestSteps Read entries from ldap server
#@TestSteps Read changelog entries on each repl server
#@TestSteps Check changelog entries against expected values and
order
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Multiple add (multiple servers)' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Multiple add (multiple servers). \
Verify multiple add operations on multiple servers are recorded \
properly in the external changelog on each replication server' \
% ecl_mode
</message>
<!-- Add entries to servers -->
<script>
myEntries = []
for i in [1,2,3]:
myEntry = Entry('cn=NEWuser-%s' % i, synchroSuffix)
myEntry.addAttr('uid', 'NEWU-%s' % i)
myEntry.addAttr('sn', 'NEW Multiple add')
myEntries.append(myEntry)
addedEntries = []
eclEntries = []
</script>
<iterate var="myEntry"
in="myEntries"
indexvar="indx">
<sequence>
<script>
serverIndex = indx % len(_topologyServerList)
server = _topologyServerList[serverIndex]
</script>
<message>
'Adding entry %s to server %s:%s)' % \
(myEntry.getDn(), server.getHostname(), server.getPort())
</message>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : server.getHostname(),
'dsInstancePort' : server.getPort(),
'dsInstanceDn' : server.getRootDn(),
'dsInstancePswd' : server.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
</sequence>
</iterate>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : synchroSuffix,
'dsFilter' : 'sn=NEW Multiple add',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the entries as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
addedEntries = STAXResult
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entries from server %s:%s' % \
(masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
if ecl_mode == 'opends':
# Issue 4502: ECL: error 53 when searching with cookie older
# than updates on several server
myKnownIssue = '4502'
else:
myKnownIssue = None
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie,
'knownIssue' : myKnownIssue
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the ECL entries as read from server %s:%s: \n%s' \
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
eclEntries = STAXResult
</script>
<if expr="len(addedEntries) != len(eclEntries)">
<sequence>
<message log="1" level="'Error'">
'Number of added entries %s does not match number of ECL \
entries %s' % (len(addedEntries), len(eclEntries))
</message>
<call function="'testFailed'"/>
</sequence>
</if>
<iterate var="eclEntry"
in="eclEntries"
indexvar="i">
<sequence>
<script>
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
addedEntry = addedEntries[i]
myTargetDN = addedEntry['dn'][0]
myChangeType = 'add'
myChangeTime = addedEntry['createtimestamp'][0]
myTargetEntryUUID = addedEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myChanges = {}
for attr in addedEntry.keys():
if (attr != 'dn') and (attr != 'changelogcookie') :
myChanges[attr] = addedEntry[attr]
if ecl_mode != 'opends':
myIntChangeNumber = int(searchIndex) + i
myChangeNumber = str(myIntChangeNumber)
else:
myChangeNumber = None
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="addedEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
</iterate>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
addedEntries = []
addedEntry = None
eclEntries = []
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Multiple modify
(multiple servers)
#@TestID Multiple modify (multiple servers)
#@TestPurpose Verify multiple mod operations on multiple servers
are recorded properly in the external changelog on
each replication server
#@TestPreamble
#@TestSteps Modify multiple entries to different servers
#@TestSteps Verify servers in sync
#@TestSteps Read entries from ldap server
#@TestSteps Read changelog entries on each repl server
#@TestSteps Check changelog entries against expected values and
order
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Multiple modify (multiple servers)' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Multiple modify (multiple \
servers). \
Verify multiple mod operations on multiple servers are recorded \
properly in the external changelog on each replication server' \
% ecl_mode
</message>
<!-- Add entries to servers -->
<script>
myEntryDn = 'cn=user,ou=People,%s' % synchroSuffix
myTelephonenumbers = ['11-11-11','22-22-22','33-33-33','44-44-44']
modEntries = []
modEntry = None
eclEntries = []
</script>
<iterate var="myTelephonenumber"
in="myTelephonenumbers"
indexvar="indx">
<sequence>
<script>
serverIndex = indx % len(_topologyServerList)
server = _topologyServerList[serverIndex]
serverPath = '%s/%s' % (server.getDir(), OPENDSNAME)
</script>
<message>
'Adding telephonenumber %s to entry %s on server %s:%s' % \
(myTelephonenumber, myEntryDn,
server.getHostname(), server.getPort())
</message>
<!-- Modify entry on one of the servers -->
<call function="'modifyAnAttribute'">
{ 'location' : server.getHostname(),
'dsPath' : serverPath,
'dsInstanceHost' : server.getHostname(),
'dsInstancePort' : server.getPort(),
'dsInstanceDn' : server.getRootDn(),
'dsInstancePswd' : server.getRootPwd(),
'DNToModify' : myEntryDn,
'attributeName' : 'telephonenumber',
'newAttributeValue' : myTelephonenumber,
'changetype' : 'add'
}
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : server.getHostname(),
'dsPath' : serverPath,
'dsInstanceHost' : server.getHostname(),
'dsInstancePort' : server.getPort(),
'dsInstanceDn' : server.getRootDn(),
'dsInstancePswd' : server.getRootPwd(),
'dsBaseDN' : myEntryDn,
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(server.getHostname(), server.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntries.append(STAXResult)
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read modified entries from server %s:%s' % \
(server.getHostname(), server.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
if ecl_mode == 'opends':
# Issue 4502: ECL: error 53 when searching with cookie older
# than updates on several server
myKnownIssue = '4502'
else:
myKnownIssue = None
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modifies -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie,
'knownIssue' : myKnownIssue
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the ECL entries as read from server %s:%s: \n%s' \
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
eclEntries = STAXResult
</script>
<if expr="len(modEntries) != len(eclEntries)">
<sequence>
<message log="1" level="'Error'">
'Number of added entries %s does not match number of ECL \
entries %s' % (len(modEntries), len(eclEntries))
</message>
<call function="'testFailed'"/>
</sequence>
</if>
<iterate var="eclEntry"
in="eclEntries"
indexvar="i">
<sequence>
<script>
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
modEntry = modEntries[i]
myTargetDN = modEntry['dn'][0]
myChangeType = 'modify'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myModifiersName = modEntry['modifiersname'][0]
myModifyTimestamp = modEntry['modifytimestamp'][0]
myTelephonenumber = myTelephonenumbers[i]
myChanges = []
myChanges.append(['add', 'telephonenumber', myTelephonenumber])
myChanges.append(['replace', 'modifiersname', myModifiersName])
myChanges.append(['replace', 'modifytimestamp', myModifyTimestamp])
if ecl_mode != 'opends':
myIntChangeNumber = int(searchIndex) + i
myChangeNumber = str(myIntChangeNumber)
else:
myChangeNumber = None
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
</iterate>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntries = []
moddEntry = None
eclEntries = []
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Two suffixes (one
replicated, one non-replicated)
#@TestID Two suffixes (one replicated, one non-replicated)
#@TestPurpose Verify external changelog only cares about
replicated suffix
#@TestPreamble
#@TestSteps Add entry (old suffix) to server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestSteps Add new suffix on server A
#@TestSteps Add entry (new suffix) to server A
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Two suffixes (one replicated, one non-replicated)' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Two suffixes (one \
replicated, one non-replicated). \
Verify external changelog only cares about replicated suffix' % ecl_mode
</message>
<!-- Add entry to replicated suffix on "master" server -->
<script>
myEntry = Entry('cn=entry', synchroSuffix)
myEntry.addAttr('sn', 'Replicated')
addedEntry = None
eclEntry = None
</script>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
addedEntry = STAXResult
myTargetDN = addedEntry['dn'][0]
myChangeType = 'add'
myChangeTime = addedEntry['createtimestamp'][0]
myTargetEntryUUID = addedEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myChanges = {}
for attr in addedEntry.keys():
if (attr != 'dn') and (attr != 'changelogcookie') :
myChanges[attr] = addedEntry[attr]
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
if ecl_mode == 'opends':
# Issue 4502: ECL: error 53 when searching with cookie older
# than updates on several server
myKnownIssue = '4502'
else:
myKnownIssue = None
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie,
'knownIssue' : myKnownIssue
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s' %\
(replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="addedEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
addedEntry = None
eclEntry = None
</script>
<!-- Add entry to non-replicated suffix on "master" server -->
<script>
newSuffix = 'o=new_suffix_no_repl'
newRootEntryAttrs = []
newRootEntryAttrs.append('objectclass:top')
newRootEntryAttrs.append('objectclass:organization')
newPeopleEntryAttrs = []
newPeopleEntryAttrs.append('objectclass:top')
newPeopleEntryAttrs.append('objectclass:organizationalunit')
myNewEntry = Entry('cn=entry', newSuffix)
myNewEntry.addAttr('sn', 'Not replicated')
addedEntries = []
eclEntries = []
</script>
<!-- Add new suffix to userRoot backend on "master" server -->
<call function="'dsconfigSet'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstanceAdminPort' : master.getAdminPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'objectName' : 'backend',
'propertyType' : 'backend',
'propertyName' : 'userRoot',
'modifyType' : 'add',
'attributeName' : 'base-dn',
'attributeValue' : newSuffix
}
</call>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : newSuffix,
'listAttributes' : newRootEntryAttrs
}
</call>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : 'ou=People,%s' % newSuffix,
'listAttributes' : newPeopleEntryAttrs
}
</call>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : myNewEntry.getDn(),
'listAttributes' : myNewEntry.getAttrList()
}
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : newSuffix,
'dsFilter' : 'objectclass=*',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the entries as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
addedEntries = STAXResult
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entries from server %s:%s' % \
(masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers ;
! newSuffix not replicated => expect no new changelog entry -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
if ecl_mode == 'opends':
# Issue 4502: ECL: error 53 when searching with cookie older
# than updates on several server
myKnownIssue = '4502'
else:
myKnownIssue = None
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie,
'knownIssue' : myKnownIssue
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the ECL entries as read from server %s:%s: \n%s' \
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
eclEntries = STAXResult
eclEntriesNb = len(eclEntries)
if searchResult.find('Failed to match a replication state') != -1:
# Search returned an error => no ECL entries
eclEntriesNb = 0
# newSuffix not replicated => expect no new entry in ECL
expectedNb = 0
</script>
<message>
'Server %s:%s : ECL entries = %s ; Expected = %s' % \
(replServer.getHostname(), replServer.getPort(),
eclEntriesNb, expectedNb)
</message>
<if expr="eclEntriesNb != expectedNb">
<sequence>
<message log="1" level="'Error'">
'Number of ECL entries %s does not match number of \
expected entries %s' % (eclEntriesNb, expectedNb)
</message>
<call function="'testFailed'"/>
<!-- if eclEntries != 0, read them for the sake of
! updating the searchIndex with the latest value -->
<iterate var="eclEntry"
in="eclEntries"
indexvar="i">
<sequence>
<script>
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
</sequence>
</iterate>
</sequence>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
addedEntries = []
addedEntry = None
eclEntries = []
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Two suffixes (both
replicated)
#@TestID Two suffixes (both replicated)
#@TestPurpose Verify external changelog can manage several
suffixes
#@TestPreamble
#@TestSteps Add entry (old suffix) to server A
#@TestSteps Verify servers in sync
#@TestSteps Add new suffix on servers
#@TestSteps Enable replication for new suffix
#@TestSteps Add entries (new suffix) to server A
#@TestSteps Verify servers in sync
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Two suffixes (both replicated)' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Two suffixes (both \
replicated). \
Verify external changelog can manage several suffixes' % ecl_mode
</message>
<!-- Add entry to replicated suffix on "master" server -->
<script>
myEntry = Entry('cn=entry A', synchroSuffix)
myEntry.addAttr('sn', 'Replicated')
addedEntries = []
addedEntry = None
eclEntry = None
firstEclEntryList = []
</script>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
addedEntries.append(STAXResult)
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie,
'knownIssue' : myKnownIssue
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s' \
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
firstEclEntryList.append(eclEntry)
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<!-- Add entries to replicated suffix on "master" server -->
<script>
newReplSuffix = 'o=new_suffix_repl'
newRootEntryAttrs = []
newRootEntryAttrs.append('objectclass:top')
newRootEntryAttrs.append('objectclass:organization')
newPeopleEntryAttrs = []
newPeopleEntryAttrs.append('objectclass:top')
newPeopleEntryAttrs.append('objectclass:organizationalunit')
myNewEntry = Entry('cn=entry A', newReplSuffix)
myNewEntry.addAttr('sn', 'Replicated')
eclEntries = []
</script>
<!-- Add new suffix to userRoot backend on servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
serverPath = '%s/%s' % (server.getDir(), OPENDSNAME)
</script>
<call function="'dsconfigSet'">
{ 'location' : server.getHostname(),
'dsPath' : serverPath,
'dsInstanceHost' : server.getHostname(),
'dsInstanceAdminPort' : server.getAdminPort(),
'dsInstanceDn' : server.getRootDn(),
'dsInstancePswd' : server.getRootPwd(),
'objectName' : 'backend',
'propertyType' : 'backend',
'propertyName' : 'userRoot',
'modifyType' : 'add',
'attributeName' : 'base-dn',
'attributeValue' : newReplSuffix
}
</call>
<if expr="indx != 0">
<!-- Call enableReplication except for "master" server -->
<sequence>
<script>
if master.isOnlyLdapServer():
masterReplPort = None
else:
masterReplPort = masterReplicationServer.getPort()
if server.isOnlyLdapServer():
serverReplPort = None
else:
replicationServer = server.getChangelogServer()
serverReplPort = replicationServer.getPort()
replicatedDnList = [newReplSuffix]
</script>
<message>
'Enable replication for server:\nHost: %s\nLdap port: %s\n\
Replication port: %s\nReplicated DN list: %s' \
% (server.getHostname(), server.getPort(),
serverReplPort, replicatedDnList)
</message>
<call function="'enableReplication'">
{ 'location' : clientHost,
'dsPath' : clientPath,
'refInstanceHost' : masterHost,
'refInstanceAdminPort' : master.getAdminPort(),
'refInstanceDn' : master.getRootDn(),
'refInstancePswd' : master.getRootPwd(),
'refReplicationPort' : masterReplPort,
'refSecureReplication' : secureReplication,
'refOnlyLdapServer' : master.isOnlyLdapServer(),
'refOnlyReplServer' : master.isOnlyReplServer(),
'dsInstanceHost' : server.getHostname(),
'dsInstanceAdminPort' : server.getAdminPort(),
'dsInstanceDn' : server.getRootDn(),
'dsInstancePswd' : server.getRootPwd(),
'dsReplicationPort' : serverReplPort,
'dsSecureReplication' : secureReplication,
'dsOnlyLdapServer' : server.isOnlyLdapServer(),
'dsOnlyReplServer' : server.isOnlyReplServer(),
'replicationDnList' : replicatedDnList
}
</call>
</sequence>
</if>
</sequence>
</iterate>
<!-- Add new entries -->
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : newReplSuffix,
'listAttributes' : newRootEntryAttrs
}
</call>
<script>
firstSearchIndex = searchIndex
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
</script>
<if expr="ecl_mode == 'opends'">
<sequence>
<!-- New replicated suffix added => resync required
! Check searching ECL with old (single-suffix) cookie returns
! error 53 and requests resync
! => retrieve suggested cookie value (referring to 2 suffixes)
-->
<script>
lastCookie = searchIndex
chgNumberFilter = None
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add - expect error (RC=53) -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie,
'expectedRC' : 53
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 53">
<!-- ECL disabled => should have returned:
! SEARCH operation failed
! Result Code: 53 (Unwilling to Perform)
! Additional Information: Full resync required. Reason:
! The provided cookie is missing the replicated domain(s)
! my_domain:;. Possible cookie: <new_cookie>
-->
<sequence>
<message>
'This is the ECL search result on server %s:%s \
(expect ERROR 53 to be returned): \n%s' \
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'searchString'">
{ 'expectedString' : 'is missing the replicated domain',
'returnString' : searchResult,
'knownIssue' : myKnownIssue
}
</call>
<script>
def getnewcookiefromerror(string):
import re
pattern = re.compile(': &lt;(.*:);&gt;')
match = re.search(pattern,string)
return match.group(1)
searchStringRC = STAXResult[0]
newCookie = None
if searchStringRC == 0:
newCookie = getnewcookiefromerror(searchResult)
nextIndex = newCookie
</script>
<message>
'This is the new changelogcookie to use: %s' % newCookie
</message>
</sequence>
</if>
</sequence>
</iterate>
</sequence>
</if>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : 'ou=People,%s' % newReplSuffix,
'listAttributes' : newPeopleEntryAttrs
}
</call>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : myNewEntry.getDn(),
'listAttributes' : myNewEntry.getAttrList()
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, newReplSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : newReplSuffix,
'dsFilter' : 'objectclass=*',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the entries as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
addedEntries += STAXResult
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entries from server %s:%s' % \
(masterHost, master.getPort())
</message>
</else>
</if>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie,
'knownIssue' : myKnownIssue
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the ECL entries as read from server %s:%s: \n%s' \
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
if len(firstEclEntryList) != 0:
eclEntries = [firstEclEntryList[indx]] + STAXResult
else:
eclEntries = STAXResult
eclEntriesNb = len(eclEntries)
expectedNb = len(addedEntries)
</script>
<message>
'Server %s:%s : ECL entries = %s ; Expected = %s' % \
(replServer.getHostname(), replServer.getPort(),
eclEntriesNb, expectedNb)
</message>
<if expr="eclEntriesNb != expectedNb">
<sequence>
<message log="1" level="'Error'">
'Number of ECL entries %s does not match number of \
expected entries %s' % (eclEntriesNb, expectedNb)
</message>
<call function="'testFailed'"/>
</sequence>
</if>
<iterate var="eclEntry"
in="eclEntries"
indexvar="i">
<sequence>
<script>
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
addedEntry = addedEntries[i]
myTargetDN = addedEntry['dn'][0]
myChangeType = 'add'
myChangeTime = addedEntry['createtimestamp'][0]
myTargetEntryUUID = addedEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myChanges = {}
for attr in addedEntry.keys():
if (attr != 'dn') and (attr != 'changelogcookie') :
myChanges[attr] = addedEntry[attr]
if ecl_mode != 'opends':
myIntChangeNumber = int(firstSearchIndex) + i
myChangeNumber = str(myIntChangeNumber)
else:
myChangeNumber = None
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="addedEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
</iterate>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
addedEntries = []
addedEntry = None
eclEntries = []
eclEntry = None
firstEclEntryList = []
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Two suffixes,
alternate adds
#@TestID Two suffixes, alternate adds
#@TestPurpose Verify external changelog can manage several
suffixes
#@TestPreamble
#@TestSteps Add entries to both suffixes on different servers
alternately
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Two suffixes, alternate adds' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Two suffixes, alternate \
adds. \
Verify external changelog can manage several suffixes' % ecl_mode
</message>
<!-- Add entries to servers -->
<script>
newReplSuffix = 'o=new_suffix_repl'
myEntries = []
myEntry = Entry('cn=entry 1', synchroSuffix)
myEntry.addAttr('sn', 'Alternate')
myEntries.append(myEntry)
myEntry = Entry('cn=entry 2', newReplSuffix)
myEntry.addAttr('sn', 'Alternate')
myEntries.append(myEntry)
myEntry = Entry('cn=entry 3', synchroSuffix)
myEntry.addAttr('sn', 'Alternate')
myEntries.append(myEntry)
myEntry = Entry('cn=entry 4', newReplSuffix)
myEntry.addAttr('sn', 'Alternate')
myEntries.append(myEntry)
myEntry = Entry('cn=entry 5', newReplSuffix)
myEntry.addAttr('sn', 'Alternate')
myEntries.append(myEntry)
addedEntries = []
eclEntries = []
</script>
<iterate var="myEntry"
in="myEntries"
indexvar="indx">
<sequence>
<script>
serverIndex = indx % len(_topologyServerList)
server = _topologyServerList[serverIndex]
</script>
<message>
'Adding entry %s to server %s:%s)' % \
(myEntry.getDn(), server.getHostname(), server.getPort())
</message>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : server.getHostname(),
'dsInstancePort' : server.getPort(),
'dsInstanceDn' : server.getRootDn(),
'dsInstancePswd' : server.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
</sequence>
</iterate>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, newReplSuffix ]
</call>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- synchroSuffix -->
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : synchroSuffix,
'dsFilter' : 'sn=Alternate',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the entries as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
addedEntries = STAXResult
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entries from server %s:%s' % \
(masterHost, master.getPort())
</message>
</else>
</if>
<!-- Search changelog in the various replication servers ;
! search for synchroSuffix changes -->
<script>
if ecl_mode == 'opends':
# ECL entry DN: cn=_replicationCSN_,_suffix_,cn=changelog
eclSearchBaseDn = '%s,cn=changelog' % synchroSuffix
eclSearchFilter = '(objectclass=*)'
else:
# ECL entry DN: changenumber=_changenumber_,cn=changelog
# => suffix information found on targetDN attribute
eclSearchBaseDn = 'cn=changelog'
eclSearchFilter = '(targetdn=*%s)' % synchroSuffix
</script>
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry adds in synchroSuffix -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : eclSearchBaseDn,
'dsFilter' : eclSearchFilter,
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie,
'knownIssue' : myKnownIssue
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the ECL entries for suffix %s as read from \
server %s:%s: \n%s' \
% (synchroSuffix, replServer.getHostname(),
replServer.getPort(), searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
eclEntries = STAXResult
eclEntriesNb = len(eclEntries)
# two new updates on suffix synchroSuffix =>
expectedNb = 2
</script>
<message>
'Server %s:%s - Suffix: %s : ECL entries = %s ; Expected \
= %s' % \
(replServer.getHostname(), replServer.getPort(),
synchroSuffix, eclEntriesNb, expectedNb)
</message>
<if expr="eclEntriesNb != expectedNb">
<sequence>
<message log="1" level="'Error'">
'Number of ECL entries %s does not match number of \
expected entries %s' % (eclEntriesNb, expectedNb)
</message>
<call function="'testFailed'"/>
</sequence>
</if>
<iterate var="eclEntry"
in="eclEntries"
indexvar="i">
<sequence>
<script>
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
addedEntry = addedEntries[i]
myTargetDN = addedEntry['dn'][0]
myChangeType = 'add'
myChangeTime = addedEntry['createtimestamp'][0]
myTargetEntryUUID = addedEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myChanges = {}
for attr in addedEntry.keys():
if (attr != 'dn') and (attr != 'changelogcookie') :
myChanges[attr] = addedEntry[attr]
if ecl_mode != 'opends':
# synchroSuffix changes: 1st and 3rd
# (searchIndex = index of 1st change)
myIntChangeNumber = int(searchIndex) + i*2
myChangeNumber = str(myIntChangeNumber)
else:
myChangeNumber = None
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="addedEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
</iterate>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<!-- newReplSuffix -->
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : newReplSuffix,
'dsFilter' : 'sn=Alternate',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the entries as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
addedEntries = STAXResult
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entries from server %s:%s' % \
(masterHost, master.getPort())
</message>
</else>
</if>
<!-- Search changelog in the various replication servers;
! search for newReplSuffix changes -->
<script>
if ecl_mode == 'opends':
# ECL entry DN: cn=_replicationCSN_,_suffix_,cn=changelog
eclSearchBaseDn = '%s,cn=changelog' % newReplSuffix
eclSearchFilter = '(objectclass=*)'
else:
# ECL entry DN: changenumber=_changenumber_,cn=changelog
# => suffix information sound on targetDN attribute
eclSearchBaseDn = 'cn=changelog'
eclSearchFilter = '(targetdn=*%s)' % newReplSuffix
</script>
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry adds in newReplSuffix -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : eclSearchBaseDn,
'dsFilter' : eclSearchFilter,
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie,
'knownIssue' : myKnownIssue
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the ECL entries for suffix %s as read from \
server %s:%s: \n%s' \
% (synchroSuffix, replServer.getHostname(),
replServer.getPort(), searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
eclEntries = STAXResult
eclEntriesNb = len(eclEntries)
# three new updates on suffix newReplSuffix =>
expectedNb = 3
</script>
<message>
'Server %s:%s - Suffix: %s : ECL entries = %s ; Expected \
= %s' % \
(replServer.getHostname(), replServer.getPort(),
newReplSuffix, eclEntriesNb, expectedNb)
</message>
<if expr="eclEntriesNb != expectedNb">
<sequence>
<message log="1" level="'Error'">
'Number of ECL entries %s does not match number of \
expected entries %s' % (eclEntriesNb, expectedNb)
</message>
<call function="'testFailed'"/>
</sequence>
</if>
<iterate var="eclEntry"
in="eclEntries"
indexvar="i">
<sequence>
<script>
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
addedEntry = addedEntries[i]
myTargetDN = addedEntry['dn'][0]
myChangeType = 'add'
myChangeTime = addedEntry['createtimestamp'][0]
myTargetEntryUUID = addedEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myChanges = {}
for attr in addedEntry.keys():
if (attr != 'dn') and (attr != 'changelogcookie') :
myChanges[attr] = addedEntry[attr]
if ecl_mode != 'opends':
# newReplSuffix changes: 2nd, 4th and 5th
# (searchIndex = index of 1st change)
if i == 0:
myIntChangeNumber = int(searchIndex) + 1
elif i == 1:
myIntChangeNumber = int(searchIndex) + 3
elif i == 2:
myIntChangeNumber = int(searchIndex) + 4
myChangeNumber = str(myIntChangeNumber)
else:
myChangeNumber = None
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="addedEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
</iterate>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
addedEntries = []
addedEntry = None
eclEntries = []
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Disable ECL - add
entry to disabled suffix
#@TestID Disable ECL - add entry to disabled suffix
#@TestPurpose Verify external changelog can be disabled for a
replicated suffix, no change recorded
#@TestPreamble Read lastExternalChangelogCookie/lastChangenumber
#@TestSteps Disable ECL for old replicated suffix
#@TestSteps Add entry (old suffix)
#@TestSteps Verify servers in sync
#@TestSteps Read last changelog entry on each repl server
(expect: error 53 if in 'opends' mode;
expect: NO ECL entry if in 'mode' draft)
#@TestSteps Add entry (old suffix)
#@TestSteps Verify servers in sync
#@TestSteps Read last changelog entry on each repl server
(expect: NO ECL entry)
#@TestPostamble
#@TestResult Success if the servers synchronised and the ECL
search behaves as expected
-->
<testcase name="getTestCaseName('%s - Disable ECL - add entry to disabled suffix' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Disable ECL - add entry to \
disabled suffix. \
Verify external changelog can be disabled for a replicated suffix' \
% ecl_mode
</message>
<!-- Read last index from root DSE (lastExternalChangelogCookie /
! lastChangenumber) -->
<script>
lastIndexAttr = None
lastIndexValue = None
if ecl_mode == 'opends':
lastIndexAttr = 'lastexternalchangelogcookie'
else:
lastIndexAttr = 'lastchangenumber'
replServer = master
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<call function="'ldapSearchWithScript'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'base',
'dsBaseDN' : ' ',
'dsFilter' : 'objectclass=*',
'dsAttributes' : lastIndexAttr
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<script>
lastIndexValue = None
pendingValue = 0
for line in searchResult.splitlines():
notBlank = (len(line.strip()) != 0)
if line.strip().lower().startswith(lastIndexAttr):
# line corresponds to lastIndexAttr:_lastIndexValue_
lastIndexValue = line[line.find(':') + 1:].lstrip()
pendingValue = 1
elif (notBlank and pendingValue):
lastIndexValue += line.lstrip()
elif pendingValue:
pendingValue = 0
break
if ecl_mode == 'opends':
nextIndex = lastIndexValue
else:
nextChgNumber = int(lastIndexValue) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Last index read from root DSE entry %s attribute: %s' % \
(lastIndexAttr, lastIndexValue)
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read root DSE entry from server %s:%s' % \
(server.getHostname(), server.getPort())
</message>
</else>
</if>
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<!-- Disable ECL for synchroSuffix on server -->
<script>
myOptionString = """--domain-name "%s" --set enabled:false""" \
% synchroSuffix
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Disable ECL for suffix %s on server %s:%s' % \
(synchroSuffix, replServer.getHostname(), replServer.getPort())
</message>
<call function="'dsconfig'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstanceAdminPort' : replServer.getAdminPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'subcommand' : 'set-external-changelog-domain-prop',
'objectType' : 'provider-name',
'objectName' : 'Multimaster Synchronization',
'optionsString' : myOptionString
}
</call>
</sequence>
</iterate>
<!-- Add entry to replicated suffix on "master" server -->
<script>
myEntry = Entry('cn=Disabled ECL-1', synchroSuffix)
myEntry.addAttr('sn', 'Disabled')
</script>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
if ecl_mode == 'opends':
# ECL disabled => expect RC=53, resync required
myExpectedRC = 53
else:
myExpectedRC = 0
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie,
'expectedRC' : myExpectedRC
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == myExpectedRC">
<if expr="ecl_mode == 'opends'">
<!-- ECL disabled => should have returned:
! SEARCH operation failed
! Result Code: 53 (Unwilling to Perform)
! Additional Information: Full resync required. Reason:
! The provided cookie contains unknown replicated domain
! {old_cookie}. Possible cookie: <new_cookie>
-->
<sequence>
<message>
'This is the ECL search result on server %s:%s \
(expect ERROR 53 to be returned): \n%s' \
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'searchString'">
{ 'expectedString' : 'contains unknown replicated domain',
'returnString' : searchResult
}
</call>
<script>
searchStringRC = STAXResult[0]
newCookie = None
if searchStringRC == 0:
# Retrieve the suggested cookie value
totem = 'Possible cookie:'
lenTotem = len(totem) + 2
indexTotem = searchResult.index(totem)
newCookie = searchResult[indexTotem + lenTotem:]
indexEnd = newCookie.index('>')
newCookie = newCookie[:indexEnd]
nextIndex = newCookie
</script>
<message>
'This is the new changelogcookie to use: %s' % newCookie
</message>
</sequence>
<else>
<!-- ECL disabled => expect NO change entry returned -->
<sequence>
<message>
'This is the ECL entry as read from server %s:%s \
(expect NO ECL entry to be returned): \n%s' \
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<if expr="len(searchResult) != 0">
<sequence>
<message log="1" level="'Error'">
'Expected NO ECL entry to be returned'
</message>
<call function="'testFailed'"/>
</sequence>
</if>
</sequence>
</else>
</if>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<!-- Add entry to replicated suffix on "master" server -->
<script>
myEntry = Entry('cn=Disabled ECL-2', synchroSuffix)
myEntry.addAttr('sn', 'Disabled')
</script>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<!-- ECL disabled => expect NO change entry returned -->
<sequence>
<message>
'This is the ECL entry as read from server %s:%s \
(expect NO ECL entry to be returned): \n%s' \
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<if expr="len(searchResult) != 0">
<sequence>
<message log="1" level="'Error'">
'Expected NO ECL entry to be returned'
</message>
<call function="'testFailed'"/>
</sequence>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Disable ECL - add
entry to non-disabled suffix
#@TestID Disable ECL - add entry to non-disabled suffix
#@TestPurpose Verify external changelog can be disabled for a
replicated suffix, and still record changes in other
replicated suffix
#@TestPreamble
#@TestSteps Add entry (new repl suffix)
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Disable ECL - add entry to non-disabled suffix' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Disable ECL - add entry to \
non-disabled suffix. \
Verify external changelog can be disabled for a replicated suffix, \
and still record changes in other replicated suffix.' % ecl_mode
</message>
<!-- Add entry to "master" server -->
<script>
newReplSuffix = 'o=new_suffix_repl'
myEntry = Entry('cn=NON-Disabled ECL', newReplSuffix)
myEntry.addAttr('sn', 'NON-Disabled')
addedEntry = None
eclEntry = None
</script>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, newReplSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
addedEntry = STAXResult
myTargetDN = addedEntry['dn'][0]
myChangeType = 'add'
myChangeTime = addedEntry['createtimestamp'][0]
myTargetEntryUUID = addedEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myChanges = {}
for attr in addedEntry.keys():
if (attr != 'dn') and (attr != 'changelogcookie') :
myChanges[attr] = addedEntry[attr]
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie,
'knownIssue' : myKnownIssue
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s' %\
(replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="addedEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
addedEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Re-enable ECL
#@TestID Re-enalbe ECL
#@TestPurpose Verify external changelog can be re-enabled for a
replicated suffix
#@TestPreamble
#@TestSteps Re-enable ECL for old replicated suffix
#@TestSteps If in 'opends' mode, read last changelog entry on
each repl server
(expect: error 53 if in 'opends' mode)
#@TestSteps Add entry (old suffix)
#@TestSteps Verify servers in sync
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the servers synchronised and the ECL
search behaves as expected
-->
<testcase name="getTestCaseName('%s - Re-enable ECL' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Re-enable ECL. \
Verify external changelog can be re-enabled for a replicated \
suffix' % ecl_mode
</message>
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<!-- Re-enable ECL for synchroSuffix on server -->
<script>
myOptionString = """--domain-name "%s" --set enabled:true""" \
% synchroSuffix
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Re-enable ECL for suffix %s on server %s:%s' % \
(synchroSuffix, replServer.getHostname(), replServer.getPort())
</message>
<call function="'dsconfig'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstanceAdminPort' : replServer.getAdminPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'subcommand' : 'set-external-changelog-domain-prop',
'objectType' : 'provider-name',
'objectName' : 'Multimaster Synchronization',
'optionsString' : myOptionString
}
</call>
</sequence>
</iterate>
<!-- If ecl_mode == opends, the last changelogcookie refers only to
! one suffix (as per last ECL search before re-enabling ECL)
! => search changelog and expect: error 53, resync required
-->
<if expr="ecl_mode == 'opends'">
<sequence>
<script>
lastCookie = searchIndex
chgNumberFilter = None
replServer = master
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie,
'expectedRC' : 53
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 53">
<!-- ECL disabled => should have returned:
! SEARCH operation failed
! Result Code: 53 (Unwilling to Perform)
! Additional Information: Full resync required. Reason:
! The provided cookie is missing the replicated domain(s)
! my_domain:;. Possible cookie: <new_cookie>
-->
<sequence>
<message>
'This is the ECL search result on server %s:%s \
(expect ERROR 53 to be returned): \n%s' \
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'searchString'">
{ 'expectedString' : 'is missing the replicated domain',
'returnString' : searchResult
}
</call>
<script>
searchStringRC = STAXResult[0]
</script>
<if expr="searchStringRC == 0">
<sequence>
<!-- New replicated suffix added => resync required =>
! Retrieve lastExternalChangelogCookie from root DSE
-->
<call function="'ldapSearchWithScript'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'base',
'dsBaseDN' : ' ',
'dsFilter' : 'objectclass=*',
'dsAttributes' : 'lastExternalChangelogCookie'
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<script>
lastECLCookie = None
pendingValue = 0
for line in searchResult.splitlines():
notBlank = (len(line.strip()) != 0)
if line.strip().lower().startswith('lastexternalchangelogcookie'):
# line corresponds to lastExternalChangelogCookie:_cookie_
lastECLCookie = line[line.find(':') + 1:].lstrip()
pendingValue = 1
elif (notBlank and pendingValue):
lastECLCookie += line.lstrip()
elif pendingValue:
pendingValue = 0
break
nextIndex = lastECLCookie
</script>
<message>
'New index read from root DSE entry \
lastExternalChangelogCookie attribute: %s' \
% nextIndex
</message>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read root DSE entry from server %s:%s' \
% (masterHost, master.getPort())
</message>
</else>
</if>
</sequence>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Did not get the expected error 53 when reading changelog \
on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</if>
<!-- Add entry to replicated suffix on "master" server -->
<script>
myEntry = Entry('cn=Re-enabled ECL', synchroSuffix)
myEntry.addAttr('sn', 'Re-enabled')
addedEntry = None
eclEntry = None
</script>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
addedEntry = STAXResult
myTargetDN = addedEntry['dn'][0]
myChangeType = 'add'
myChangeTime = addedEntry['createtimestamp'][0]
myTargetEntryUUID = addedEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myChanges = {}
for attr in addedEntry.keys():
if (attr != 'dn') and (attr != 'changelogcookie') :
myChanges[attr] = addedEntry[attr]
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s' %\
(replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="addedEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges,
'knownIssue' : myKnownIssue
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
addedEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Disable + Re-enable
ECL
#@TestID Disable + Re-enalbe ECL
#@TestPurpose Verify external changelog can be disabled, then
re-enabled for a replicated suffix and still return
the changes performed in between
#@TestPreamble
#@TestSteps Disable suffix for replicated suffix
#@TestSteps Add entry to suffix
#@TestSteps Re-enable ECL for replicated suffix
#@TestSteps Add entry to suffix
#@TestSteps Verify servers in sync
#@TestSteps Read last changelog entry on each repl server
(expect 2 change entries returned)
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the servers synchronised and the ECL
search behaves as expected
-->
<testcase name="getTestCaseName('%s - Disable + Re-enable ECL' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Disable + Re-enable ECL. \
Verify external changelog can be disabled, then re-enabled for a \
replicated suffix and still return the changes performed in \
between' % ecl_mode
</message>
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<!-- Disable ECL for synchroSuffix on server -->
<script>
myOptionString = """--domain-name "%s" --set enabled:false""" \
% synchroSuffix
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Disable ECL for suffix %s on server %s:%s' % \
(synchroSuffix, replServer.getHostname(), replServer.getPort())
</message>
<call function="'dsconfig'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstanceAdminPort' : replServer.getAdminPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'subcommand' : 'set-external-changelog-domain-prop',
'objectType' : 'provider-name',
'objectName' : 'Multimaster Synchronization',
'optionsString' : myOptionString
}
</call>
</sequence>
</iterate>
<!-- Add entry to replicated suffix on "master" server -->
<script>
myEntry = Entry('cn=Disabled Re-enabled ECL-1', synchroSuffix)
myEntry.addAttr('sn', 'Disabled Re-enabled')
addedEntries = []
eclEntries = []
</script>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<!-- Re-enable ECL for synchroSuffix on server -->
<script>
myOptionString = """--domain-name "%s" --set enabled:true""" \
% synchroSuffix
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Re-enable ECL for suffix %s on server %s:%s' % \
(synchroSuffix, replServer.getHostname(), replServer.getPort())
</message>
<call function="'dsconfig'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstanceAdminPort' : replServer.getAdminPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'subcommand' : 'set-external-changelog-domain-prop',
'objectType' : 'provider-name',
'objectName' : 'Multimaster Synchronization',
'optionsString' : myOptionString
}
</call>
</sequence>
</iterate>
<!-- Add entry to replicated suffix on "master" server -->
<script>
myEntry = Entry('cn=Disabled Re-enabled ECL-2', synchroSuffix)
myEntry.addAttr('sn', 'Disabled Re-enabled')
</script>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : synchroSuffix,
'dsFilter' : 'sn=Disabled Re-enabled',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the entries as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
addedEntries = STAXResult
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entries from server %s:%s' % \
(masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
if ecl_mode == 'opends':
# Issue 4502: ECL: error 53 when searching with cookie older
# than updates on several server
myKnownIssue = '4502'
else:
myKnownIssue = None
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie,
'knownIssue' : myKnownIssue
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the ECL entries as read from server %s:%s: \n%s' \
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
eclEntries = STAXResult
</script>
<if expr="len(addedEntries) != len(eclEntries)">
<sequence>
<message log="1" level="'Error'">
'Number of added entries %s does not match number of ECL \
entries %s' % (len(addedEntries), len(eclEntries))
</message>
<call function="'testFailed'"/>
</sequence>
</if>
<iterate var="eclEntry"
in="eclEntries"
indexvar="i">
<sequence>
<script>
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
addedEntry = addedEntries[i]
myTargetDN = addedEntry['dn'][0]
myChangeType = 'add'
myChangeTime = addedEntry['createtimestamp'][0]
myTargetEntryUUID = addedEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myChanges = {}
for attr in addedEntry.keys():
if (attr != 'dn') and (attr != 'changelogcookie') :
myChanges[attr] = addedEntry[attr]
if ecl_mode != 'opends':
myIntChangeNumber = int(searchIndex) + i
myChangeNumber = str(myIntChangeNumber)
else:
myChangeNumber = None
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="addedEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
</iterate>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
addedEntries = []
addedEntry = None
eclEntries = []
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Include-Attributes:
Add, single-value include-attr
#@TestID Include-Attributes: Add, single-value include-attr
#@TestPurpose Verify add operation is recorded properly in the
external changelog on each replication server and
include-attributes are published
#@TestPreamble Read lastExternalChangelogCookie/lastChangenumber
#@TestSteps Set include-attribute on server A: sn
#@TestSteps Add entry to server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Include-Attributes: Add, single-value include-attr' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Include-Attributes: Add, \
single-value include-attr. \
Verify add operation is recorded properly in the external \
changelog on each replication server and include-attributes are \
published' % ecl_mode
</message>
<!-- Read last index from root DSE (lastExternalChangelogCookie /
! lastChangenumber) -->
<script>
lastIndexAttr = None
lastIndexValue = None
if ecl_mode == 'opends':
lastIndexAttr = 'lastexternalchangelogcookie'
else:
lastIndexAttr = 'lastchangenumber'
replServer = master
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<call function="'ldapSearchWithScript'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'base',
'dsBaseDN' : ' ',
'dsFilter' : 'objectclass=*',
'dsAttributes' : lastIndexAttr
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<script>
lastIndexValue = None
pendingValue = 0
for line in searchResult.splitlines():
notBlank = (len(line.strip()) != 0)
if line.strip().lower().startswith(lastIndexAttr):
# line corresponds to lastIndexAttr:_lastIndexValue_
lastIndexValue = line[line.find(':') + 1:].lstrip()
pendingValue = 1
elif (notBlank and pendingValue):
lastIndexValue += line.lstrip()
elif pendingValue:
pendingValue = 0
break
if ecl_mode == 'opends':
nextIndex = lastIndexValue
else:
nextChgNumber = int(lastIndexValue) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Last index read from root DSE entry %s attribute: %s' % \
(lastIndexAttr, lastIndexValue)
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read root DSE entry from server %s:%s' % \
(server.getHostname(), server.getPort())
</message>
</else>
</if>
<!-- Configure include-attributes for synchroSuffix on master -->
<script>
incAttr = 'sn'
myOptionString = """--domain-name "%s" --set ecl-include:%s""" \
% (synchroSuffix, incAttr)
replServer = master
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Set include-attribute %s for suffix %s on server %s:%s' \
% (incAttr, synchroSuffix, replServer.getHostname(),
replServer.getPort())
</message>
<call function="'dsconfig'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstanceAdminPort' : replServer.getAdminPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'subcommand' : 'set-external-changelog-domain-prop',
'objectType' : 'provider-name',
'objectName' : 'Multimaster Synchronization',
'optionsString' : myOptionString
}
</call>
<!-- Add entry to "master" server -->
<script>
myEntry = Entry('cn=Inc-SN-1', synchroSuffix)
myEntry.addAttr(incAttr, 'Include-Attr')
addedEntry = None
eclEntry = None
</script>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
addedEntry = STAXResult
myTargetDN = addedEntry['dn'][0]
myChangeType = 'add'
myChangeTime = addedEntry['createtimestamp'][0]
myTargetEntryUUID = addedEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myChanges = {}
myIncAttrs = { incAttr : addedEntry[incAttr] }
for attr in addedEntry.keys():
if (attr != 'dn') and (attr != 'changelogcookie') :
myChanges[attr] = addedEntry[attr]
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s' %\
(replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<if expr="len(searchResult) != 0">
<sequence>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % \
nextIndex
</message>
<if expr="addedEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges,
'includeAttrs' : myIncAttrs
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<sequence>
<message log="1" level="'Error'">
'Expected some ECL entry but NO ENTRY returned'
</message>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
addedEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Include-Attributes
Add (on peer server), single-value include-attr
#@TestID Include-Attributes: Add (on peer server),
single-value include-attr
#@TestPurpose Verify add operation (on a server other than where
the include-attr has been configured) is recorded
properly and include-attributes are still published
#@TestPreamble
#@TestSteps Add entry to server B
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Include-Attributes: Add (on peer server), single-value include-attr' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Include Attributes: Add (on \
peer server), single-value include-attr. \
Verify add operation (on a server other than where the include-attr\
has been configured) is recorded properly and include-attributes \
are still published' % ecl_mode
</message>
<!-- Add entry to "consumer" server -->
<script>
incAttr = 'sn'
myEntry = Entry('cn=Inc-SN-2', synchroSuffix)
myEntry.addAttr(incAttr, 'Include-Attr')
consumer = _topologyServerList[1]
consumerPath = '%s/%s' % (consumer.getDir(), OPENDSNAME)
addedEntry = None
eclEntry = None
</script>
<call function="'addAnEntry'">
{ 'location' : consumer.getHostname(),
'dsPath' : consumerPath,
'dsInstanceHost' : consumer.getHostname(),
'dsInstancePort' : consumer.getPort(),
'dsInstanceDn' : consumer.getRootDn(),
'dsInstancePswd' : consumer.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
addedEntry = STAXResult
myTargetDN = addedEntry['dn'][0]
myChangeType = 'add'
myChangeTime = addedEntry['createtimestamp'][0]
myTargetEntryUUID = addedEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myChanges = {}
myIncAttrs = { incAttr : addedEntry[incAttr] }
for attr in addedEntry.keys():
if (attr != 'dn') and (attr != 'changelogcookie') :
myChanges[attr] = addedEntry[attr]
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s' %\
(replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<if expr="len(searchResult) != 0">
<sequence>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % \
nextIndex
</message>
<if expr="addedEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges,
'includeAttrs' : myIncAttrs
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<sequence>
<message log="1" level="'Error'">
'Expected some ECL entry but NO ENTRY returned'
</message>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
addedEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Include-attributes:
Add, multiple-value include-attr
#@TestID Include-attributes: Add, multiple-value include-attr
#@TestPurpose Verify add operation is recorded properly in the
external changelog on each replication server and
newly set include-attributes are published, unlike
the old include-attributes, that should no longer
be published
#@TestPreamble
#@TestSteps Set include-attribute on server A: description
#@TestSteps Add entry to server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Include-Attributes: Add, multiple-value include-attr' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Include-Attributes: Add, \
multiple-value include-attr. \
Verify add operation is recorded properly in the external \
changelog on each replication server and newly set \
include-attributes are published, unlike the old include-attributes\
, that should no longer be published' % ecl_mode
</message>
<!-- Configure include-attributes for synchroSuffix on master -->
<script>
incAttr = 'description'
oldIncAttr = 'sn'
myOptionString = """--domain-name "%s" --set ecl-include:%s""" \
% (synchroSuffix, incAttr)
replServer = master
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Set include-attribute %s for suffix %s on server %s:%s' \
% (incAttr, synchroSuffix, replServer.getHostname(),
replServer.getPort())
</message>
<call function="'dsconfig'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstanceAdminPort' : replServer.getAdminPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'subcommand' : 'set-external-changelog-domain-prop',
'objectType' : 'provider-name',
'objectName' : 'Multimaster Synchronization',
'optionsString' : myOptionString
}
</call>
<!-- Add entry to "master" server -->
<script>
myEntry = Entry('cn=Inc-DESCRIPTION', synchroSuffix)
myEntry.addAttr('sn', 'Include')
myEntry.addAttr(incAttr, 'This is my first Include-Attr value')
myEntry.addAttr(incAttr, 'This is my second Include-Attr value')
addedEntry = None
eclEntry = None
</script>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
addedEntry = STAXResult
myTargetDN = addedEntry['dn'][0]
myChangeType = 'add'
myChangeTime = addedEntry['createtimestamp'][0]
myTargetEntryUUID = addedEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myChanges = {}
myIncAttrs = {}
for attr in addedEntry.keys():
if (attr != 'dn') and (attr != 'changelogcookie') :
myChanges[attr] = addedEntry[attr]
for attr in [incAttr, oldIncAttr]:
if attr in addedEntry.keys():
myIncAttrs[attr] = addedEntry[attr]
else:
myIncAttrs[attr] = ' '
# oldIncAttr is no longer configured as an include-attribute, so
# expect NO 'target*' include-attr to be present
# in the changelog entry
myMissingIncAttrs = [oldIncAttr]
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s' %\
(replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<if expr="len(searchResult) != 0">
<sequence>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % \
nextIndex
</message>
<if expr="addedEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges,
'includeAttrs' : myIncAttrs,
'expectMissingIncAttrs' : myMissingIncAttrs
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<sequence>
<message log="1" level="'Error'">
'Expected some ECL entry but NO ENTRY returned'
</message>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
addedEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Include-Attributes:
Add, several include-attrs
#@TestID Include-Attributes: Add, several include-attrs
#@TestPurpose Verify add operation is recorded properly in the
external changelog on each replication server and
include-attributes are published
#@TestPreamble Add include-attribute on server A: uid
#@TestSteps Add entry to server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Include-Attributes: Add, several include-attrs' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Include-Attributes: Add, \
several include-attrs. \
Verify add operation is recorded properly in the external \
changelog on each replication server and include-attributes are \
published' % ecl_mode
</message>
<!-- Configure include-attributes for synchroSuffix on master -->
<!-- 'description' has already been set as include-attribute, so
! only need to add 'uid'.
-->
<script>
incAttrs = ['uid', 'description']
myOptionString = """--domain-name "%s" --add ecl-include:%s""" \
% (synchroSuffix, incAttrs[0])
replServer = master
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Add include-attribute %s for suffix %s on server %s:%s' \
% (incAttrs[0], synchroSuffix, replServer.getHostname(),
replServer.getPort())
</message>
<call function="'dsconfig'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstanceAdminPort' : replServer.getAdminPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'subcommand' : 'set-external-changelog-domain-prop',
'objectType' : 'provider-name',
'objectName' : 'Multimaster Synchronization',
'optionsString' : myOptionString
}
</call>
<!-- Add entry to "master" server -->
<script>
myEntry = Entry('cn=Inc-UID-DESCRIPTION', synchroSuffix)
myEntry.addAttr('sn', 'Include')
myEntry.addAttr(incAttrs[0], 'Include-Attr value')
myEntry.addAttr(incAttrs[1], 'This is my first Include-Attr value')
myEntry.addAttr(incAttrs[1], 'This is my second Include-Attr value')
addedEntry = None
eclEntry = None
</script>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
addedEntry = STAXResult
myTargetDN = addedEntry['dn'][0]
myChangeType = 'add'
myChangeTime = addedEntry['createtimestamp'][0]
myTargetEntryUUID = addedEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myChanges = {}
myIncAttrs = {}
for attr in addedEntry.keys():
if (attr != 'dn') and (attr != 'changelogcookie') :
myChanges[attr] = addedEntry[attr]
for incAttr in incAttrs:
if incAttr in addedEntry.keys():
myIncAttrs[incAttr] = addedEntry[incAttr]
else:
myIncAttrs[incAttr] = ' '
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s' %\
(replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<if expr="len(searchResult) != 0">
<sequence>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % \
nextIndex
</message>
<if expr="addedEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges,
'includeAttrs' : myIncAttrs
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<sequence>
<message log="1" level="'Error'">
'Expected some ECL entry but NO ENTRY returned'
</message>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
addedEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Include-Attributes:
Add to unconfigured suffix
#@TestID Include-Attributes: Add to unconfigured suffix
#@TestPurpose Verify add operation is recorded properly in the
external changelog but include-attributes are NOT
published
#@TestPreamble
#@TestSteps Add entry to unconfigured suffix
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Include-Attributes: Add to unconfigured suffix' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Include-attributes: Add to \
unconfigured suffix. \
Verify add operation is recorded properly in the external \
changelog obut include-attributes are NOT published' % ecl_mode
</message>
<!-- ['uid','description'} have already been set as include-attrs -->
<script>
incAttrs = ['uid', 'description']
newReplSuffix = 'o=new_suffix_repl'
</script>
<!-- Add entry to "master" server -->
<script>
myEntry = Entry('cn=Inc-Unconfigured', newReplSuffix)
myEntry.addAttr('sn', 'Unconfigured')
myEntry.addAttr(incAttrs[0], 'Include-Unconfigured')
myEntry.addAttr(incAttrs[1], 'This is my first Include-Attr value')
myEntry.addAttr(incAttrs[1], 'This is my second Include-Attr value')
addedEntry = None
eclEntry = None
</script>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, newReplSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
addedEntry = STAXResult
myTargetDN = addedEntry['dn'][0]
myChangeType = 'add'
myChangeTime = addedEntry['createtimestamp'][0]
myTargetEntryUUID = addedEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myChanges = {}
myIncAttrs = {}
# No include-attr configured for newReplSuffix, so expect NO
# include-attr to be present in the changelog entry
myMissingIncAttrs = incAttrs
for attr in addedEntry.keys():
if (attr != 'dn') and (attr != 'changelogcookie') :
myChanges[attr] = addedEntry[attr]
for incAttr in incAttrs:
if incAttr in addedEntry.keys():
myIncAttrs[incAttr] = addedEntry[incAttr]
else:
myIncAttrs[incAttr] = ' '
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s' %\
(replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<if expr="len(searchResult) != 0">
<sequence>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % \
nextIndex
</message>
<if expr="addedEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges,
'includeAttrs' : myIncAttrs,
'expectMissingIncAttrs' : myMissingIncAttrs,
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<sequence>
<message log="1" level="'Error'">
'Expected some ECL entry but NO ENTRY returned'
</message>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
addedEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Include-Attributes:
Add, different include-attr per server
#@TestID Include-Attributes: Add, different include-attr per
server
#@TestPurpose Verify add operation is recorded properly in the
external changelog and ALL configured
include-attributes are published
#@TestPreamble Read lastExternalChangelogCookie/lastChangenumber
#@TestSteps Set include-attribute on server A: givenname
#@TestSteps Set include-attribute on server B: l
#@TestSteps Add entry to server A
#@TestSteps Add entry to server B
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Include-Attributes: Add, different include-attr per server' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Include-Attributes: Add, \
different include-attr per server. \
Verify add operation is recorded properly in the external \
changelog and ALL configured include-attributes are published' \
% ecl_mode
</message>
<script>
incAttrs = ['givenname', 'l']
</script>
<iterate var="incAttr"
in="incAttrs"
indexvar="indx">
<sequence>
<!-- Configure include-attributes for synchroSuffix on server -->
<script>
myOptionString = """--domain-name "%s" --set ecl-include:%s""" \
% (synchroSuffix, incAttr)
replServer = _topologyServerList[indx]
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Set include-attribute %s for suffix %s on server %s:%s' \
% (incAttr, synchroSuffix, replServer.getHostname(),
replServer.getPort())
</message>
<call function="'dsconfig'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstanceAdminPort' : replServer.getAdminPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'subcommand' : 'set-external-changelog-domain-prop',
'objectType' : 'provider-name',
'objectName' : 'Multimaster Synchronization',
'optionsString' : myOptionString
}
</call>
</sequence>
</iterate>
<!-- Add entries to servers -->
<script>
myEntries = []
myEntry = Entry('cn=INCLUDE-1', synchroSuffix)
myEntry.addAttr('sn', 'Multi-server Include-Attrs')
for incAttr in incAttrs:
myEntry.addAttr(incAttr, 'INC-ATTR %s-1' % incAttr)
myEntries.append(myEntry)
myEntry = Entry('cn=INCLUDE-2', synchroSuffix)
myEntry.addAttr('sn', 'Multi-server Include-Attrs')
for incAttr in incAttrs:
myEntry.addAttr(incAttr, 'INC-ATTR %s-2' % incAttr)
myEntries.append(myEntry)
addedEntries = []
eclEntries = []
</script>
<iterate var="myEntry"
in="myEntries"
indexvar="indx">
<sequence>
<script>
serverIndex = indx % len(_topologyServerList)
server = _topologyServerList[serverIndex]
</script>
<message>
'Adding entry %s to server %s:%s)' % \
(myEntry.getDn(), server.getHostname(), server.getPort())
</message>
<call function="'addAnEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : server.getHostname(),
'dsInstancePort' : server.getPort(),
'dsInstanceDn' : server.getRootDn(),
'dsInstancePswd' : server.getRootPwd(),
'DNToAdd' : myEntry.getDn(),
'listAttributes' : myEntry.getAttrList()
}
</call>
</sequence>
</iterate>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : synchroSuffix,
'dsFilter' : 'sn=Multi-server Include-Attrs',
'dsAttributes' : addOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the entries as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
addedEntries = STAXResult
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entries from server %s:%s' % \
(masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry add -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'These are the ECL entries as read from server %s:%s: \n%s' \
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<if expr="len(searchResult) != 0">
<sequence>
<call function="'parseLdifEntries'">
{ 'ldifEntries' : searchResult }
</call>
<script>
eclEntries = STAXResult
</script>
<if expr="len(addedEntries) != len(eclEntries)">
<sequence>
<message log="1" level="'Error'">
'Number of added entries %s does not match number of ECL \
entries %s' % (len(addedEntries), len(eclEntries))
</message>
<call function="'testFailed'"/>
</sequence>
</if>
<iterate var="eclEntry"
in="eclEntries"
indexvar="i">
<sequence>
<script>
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
addedEntry = addedEntries[i]
myTargetDN = addedEntry['dn'][0]
myChangeType = 'add'
myChangeTime = addedEntry['createtimestamp'][0]
myTargetEntryUUID = addedEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myChanges = {}
myIncAttrs = {}
for attr in addedEntry.keys():
if (attr != 'dn') and (attr != 'changelogcookie') :
myChanges[attr] = addedEntry[attr]
for incAttr in incAttrs:
if incAttr in addedEntry.keys():
myIncAttrs[incAttr] = addedEntry[incAttr]
else:
myIncAttrs[incAttr] = ' '
if ecl_mode != 'opends':
myIntChangeNumber = int(searchIndex) + i
myChangeNumber = str(myIntChangeNumber)
else:
myChangeNumber = None
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="addedEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges,
'includeAttrs' : myIncAttrs
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
</iterate>
</sequence>
<else>
<sequence>
<message log="1" level="'Error'">
'Expected some ECL entry but NO ENTRY returned'
</message>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
addedEntries = []
addedEntry = None
eclEntries = []
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Include-Attributes:
Modify_add, attribute NOT in include-attrs
#@TestID Include-Attributes: Modify_add, attribute NOT in
include-attrs
#@TestPurpose Verify modify-add operation is recorded properly
in the external changelog and include-attributes are
published
#@TestPreamble Set include-attribute: 'description'
#@TestSteps Modify entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Include-Attributes: Modify_add, attribute NOT in include-attrs' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Include-Attributes: \
Modify_add, attribute NOT in include-attrs. \
Verify modify-add operation is recorded properly in the \
external changelog and include-attributes are published' % ecl_mode
</message>
<!-- We will use the entry added in a previous testcase:
! dn: cn=Inc-DESCRIPTION, ou=People, o=example
! objectclass: top
! objectclass: person
! objectclass: organizationalperson
! objectclass: inetorgperson
! cn: Inc-DESCRIPTION
! sn: Include
! description: This is my first Include-Attr value
! description: This is my second Include-Attr value
-->
<script>
myEntry = Entry('cn=Inc-DESCRIPTION', synchroSuffix)
incAttr = 'description'
myIncAttrs = {}
addAttr = 'postaladdress'
addValue = 'Includeland'
modEntry = None
eclEntry = None
</script>
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<!-- Configure include-attributes for synchroSuffix on server -->
<script>
myOptionString = """--domain-name "%s" --set ecl-include:%s""" \
% (synchroSuffix, incAttr)
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Set include-attribute %s for suffix %s on server %s:%s' \
% (incAttr, synchroSuffix, replServer.getHostname(),
replServer.getPort())
</message>
<call function="'dsconfig'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstanceAdminPort' : replServer.getAdminPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'subcommand' : 'set-external-changelog-domain-prop',
'objectType' : 'provider-name',
'objectName' : 'Multimaster Synchronization',
'optionsString' : myOptionString
}
</call>
</sequence>
</iterate>
<!-- Retrieve entry's include-attribute's information prior to modify
! for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : incAttr
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
stubEntry = STAXResult
myIncAttrs = { incAttr : stubEntry[incAttr] }
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(newEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<!-- Modify entry on one of the servers:
! add: postaladdress
! postaladdress: Includeland
-->
<call function="'modifyAnAttribute'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : myEntry.getDn(),
'attributeName' : addAttr,
'newAttributeValue' : addValue,
'changetype' : 'add'
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntry = STAXResult
myTargetDN = modEntry['dn'][0]
myChangeType = 'modify'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myModifiersName = modEntry['modifiersname'][0]
myModifyTimestamp = modEntry['modifytimestamp'][0]
myChanges = []
myChanges.append(['add', addAttr, addValue])
myChanges.append(['replace', 'modifiersname', myModifiersName])
myChanges.append(['replace', 'modifytimestamp', myModifyTimestamp])
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read modified entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges,
'includeAttrs' : myIncAttrs
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Include-Attributes:
Modify_add, multiple-value attribute in include-attrs
#@TestID Include-Attributes: Modify_add, multiple-value
attribute in include-attrs
#@TestPurpose Verify modify-add operation is recorded properly
in the external changelog and include-attributes are
published
#@TestPreamble
#@TestSteps Modify entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Include-Attributes: Modify_add, multiple-value attribute in include-attrs' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Include-Attributes: \
Modify_add, multiple-value attribute in include-attrs. \
Verify modify-add operation is recorded properly in the \
external changelog and include-attributes are published' % ecl_mode
</message>
<!-- We will use the entry added in a previous testcase:
! dn: cn=Inc-DESCRIPTION, ou=People, o=example
! objectclass: top
! objectclass: person
! objectclass: organizationalperson
! objectclass: inetorgperson
! cn: Inc-DESCRIPTION
! sn: Include
! postaladdress: Includeland
! description: This is my first Include-Attr value
! description: This is my second Include-Attr value
!
! There is already an include-attribute configured: 'description'
-->
<script>
myEntry = Entry('cn=Inc-DESCRIPTION', synchroSuffix)
incAttr = 'description'
myIncAttrs = {}
addAttr = 'description'
addValue = 'This is my third Include-Attr value'
modEntry = None
eclEntry = None
</script>
<!-- Retrieve entry's include-attribute's information prior to modify
! for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : incAttr
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
stubEntry = STAXResult
myIncAttrs = { incAttr : stubEntry[incAttr] }
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(newEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<!-- Modify entry on one of the servers:
! add: description
! description: This is my third Include-Attr value
-->
<call function="'modifyAnAttribute'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : myEntry.getDn(),
'attributeName' : addAttr,
'newAttributeValue' : addValue,
'changetype' : 'add'
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntry = STAXResult
myTargetDN = modEntry['dn'][0]
myChangeType = 'modify'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myModifiersName = modEntry['modifiersname'][0]
myModifyTimestamp = modEntry['modifytimestamp'][0]
myChanges = []
myChanges.append(['add', addAttr, addValue])
myChanges.append(['replace', 'modifiersname', myModifiersName])
myChanges.append(['replace', 'modifytimestamp', myModifyTimestamp])
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read modified entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges,
'includeAttrs' : myIncAttrs
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Include-Attributes:
Modify_add, single-value attribute in include-attrs
#@TestID Include-Attributes: Modify_add, single-value
attribute in include-attrs
#@TestPurpose Verify modify-add operation is recorded properly
in the external changelog and include-attributes are
published
#@TestPreamble Add include-attribute: 'employeenumber'
#@TestSteps Modify entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Include-Attributes: Modify_add, single-value attribute in include-attrs' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Include-Attributes: \
Modify_add, single-value attribute in include-attrs. \
Verify modify-add operation is recorded properly in the \
external changelog and include-attributes are published' % ecl_mode
</message>
<!-- We will use the entry added in a previous testcase:
! dn: cn=Inc-DESCRIPTION, ou=People, o=example
! objectclass: top
! objectclass: person
! objectclass: organizationalperson
! objectclass: inetorgperson
! cn: Inc-DESCRIPTION
! sn: Include
! postaladdress: Includeland
! description: This is my first Include-Attr value
! description: This is my second Include-Attr value
! description: This is my third Include-Attr value
!
! There is already an include-attribute configured: 'description'
-->
<script>
myEntry = Entry('cn=Inc-DESCRIPTION', synchroSuffix)
incAttrs = ['employeenumber', 'description']
myIncAttrs = {}
addAttr = 'employeenumber'
addValue = '12345'
modEntry = None
eclEntry = None
</script>
<!-- Configure include-attributes for synchroSuffix on master -->
<!-- 'description' has already been set as include-attribute, so
! only need to add 'employeenumber'.
-->
<script>
myOptionString = """--domain-name "%s" --add ecl-include:%s""" \
% (synchroSuffix, incAttrs[0])
replServer = master
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Add include-attribute %s for suffix %s on server %s:%s' \
% (incAttrs[0], synchroSuffix, replServer.getHostname(),
replServer.getPort())
</message>
<call function="'dsconfig'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstanceAdminPort' : replServer.getAdminPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'subcommand' : 'set-external-changelog-domain-prop',
'objectType' : 'provider-name',
'objectName' : 'Multimaster Synchronization',
'optionsString' : myOptionString
}
</call>
<!-- Retrieve entry's include-attribute's information prior to modify
! for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : ' '.join(incAttrs)
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
stubEntry = STAXResult
for incAttr in incAttrs:
if incAttr in stubEntry.keys():
myIncAttrs[incAttr] = stubEntry[incAttr]
else:
myIncAttrs[incAttr] = ' '
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(newEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<!-- Modify entry on one of the servers:
! add: employeenumber
! employeenumber: 12345
-->
<call function="'modifyAnAttribute'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : myEntry.getDn(),
'attributeName' : addAttr,
'newAttributeValue' : addValue,
'changetype' : 'add'
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntry = STAXResult
myTargetDN = modEntry['dn'][0]
myChangeType = 'modify'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myModifiersName = modEntry['modifiersname'][0]
myModifyTimestamp = modEntry['modifytimestamp'][0]
myChanges = []
myChanges.append(['add', addAttr, addValue])
myChanges.append(['replace', 'modifiersname', myModifiersName])
myChanges.append(['replace', 'modifytimestamp', myModifyTimestamp])
# 'employeenumber' contained no value prior to the modify op, so
# expect NO 'targetemployeenumber' include-attr to be present
# in the changelog entry
myMissingIncAttrs = [incAttrs[0]]
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read modified entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges,
'includeAttrs' : myIncAttrs,
'expectMissingIncAttrs' : myMissingIncAttrs
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Include-Attributes:
Modify_delete, attribute NOT in include-attrs
#@TestID Include-Attributes: Modify_delete, attribute NOT in
include-attrs
#@TestPurpose Verify modify-delete operation is recorded properly
in the external changelog and include-attributes are
published
#@TestPreamble
#@TestSteps Modify entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Include-Attributes: Modify_delete, attribute NOT in include-attrs' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Include-Attributes: \
Modify_delete, attribute NOT in include-attrs. \
Verify modify-delete operation is recorded properly in the \
external changelog and include-attributes are published' % ecl_mode
</message>
<!-- We will use the entry added in a previous testcase:
! dn: cn=Inc-DESCRIPTION, ou=People, o=example
! objectclass: top
! objectclass: person
! objectclass: organizationalperson
! objectclass: inetorgperson
! cn: Inc-DESCRIPTION
! sn: Include
! postaladdress: Includeland
! employeenumber: 12345
! description: This is my first Include-Attr value
! description: This is my second Include-Attr value
! description: This is my third Include-Attr value
!
! There are already include-attributes configured:
! 'employeenumber', 'description'
-->
<script>
myEntry = Entry('cn=Inc-DESCRIPTION', synchroSuffix)
incAttrs = ['employeenumber', 'description']
myIncAttrs = {}
delAttr = 'postaladdress'
delValue = None
modEntry = None
eclEntry = None
</script>
<!-- Retrieve entry's include-attribute's information prior to modify
! for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : ' '.join(incAttrs + [delAttr])
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
stubEntry = STAXResult
delValue = stubEntry[delAttr][0]
for incAttr in incAttrs:
if incAttr in stubEntry.keys():
myIncAttrs[incAttr] = stubEntry[incAttr]
else:
myIncAttrs[incAttr] = ' '
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(newEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<!-- Modify entry on one of the servers:
! delete: postaladdress
! postaladdress: Includeland
-->
<call function="'modifyAnAttribute'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : myEntry.getDn(),
'attributeName' : delAttr,
'newAttributeValue' : delValue,
'changetype' : 'delete'
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntry = STAXResult
myTargetDN = modEntry['dn'][0]
myChangeType = 'modify'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myModifiersName = modEntry['modifiersname'][0]
myModifyTimestamp = modEntry['modifytimestamp'][0]
myChanges = []
myChanges.append(['delete', delAttr, delValue])
myChanges.append(['replace', 'modifiersname', myModifiersName])
myChanges.append(['replace', 'modifytimestamp', myModifyTimestamp])
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read modified entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges,
'includeAttrs' : myIncAttrs
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Include-Attributes:
Modify_delete, attribute in include-attrs
#@TestID Include-Attributes: Modify_delete, attribute in
include-attrs
#@TestPurpose Verify modify-delete operation is recorded properly
in the external changelog and include-attributes are
published
#@TestPreamble
#@TestSteps Modify entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Include-Attributes: Modify_delete, attribute in include-attrs' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Include-Attributes: \
Modify_delete, attribute in include-attrs. \
Verify modify-delete operation is recorded properly in the \
external changelog and include-attributes are published' % ecl_mode
</message>
<!-- We will use the entry added in a previous testcase:
! dn: cn=Inc-DESCRIPTION, ou=People, o=example
! objectclass: top
! objectclass: person
! objectclass: organizationalperson
! objectclass: inetorgperson
! cn: Inc-DESCRIPTION
! sn: Include
! employeenumber: 12345
! description: This is my first Include-Attr value
! description: This is my second Include-Attr value
! description: This is my third Include-Attr value
!
! There are already include-attributes configured:
! 'employeenumber', 'description'
-->
<script>
myEntry = Entry('cn=Inc-DESCRIPTION', synchroSuffix)
incAttrs = ['employeenumber', 'description']
myIncAttrs = {}
delAttr = 'employeenumber'
delValue = None
modEntry = None
eclEntry = None
</script>
<!-- Retrieve entry's include-attribute's information prior to modify
! for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : ' '.join(incAttrs + [delAttr])
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
stubEntry = STAXResult
delValue = stubEntry[delAttr][0]
for incAttr in incAttrs:
if incAttr in stubEntry.keys():
myIncAttrs[incAttr] = stubEntry[incAttr]
else:
myIncAttrs[incAttr] = ' '
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(newEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<!-- Modify entry on one of the servers:
! delete: employeenumber
! employeenumber: 12345
-->
<call function="'modifyAnAttribute'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : myEntry.getDn(),
'attributeName' : delAttr,
'newAttributeValue' : delValue,
'changetype' : 'delete'
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntry = STAXResult
myTargetDN = modEntry['dn'][0]
myChangeType = 'modify'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myModifiersName = modEntry['modifiersname'][0]
myModifyTimestamp = modEntry['modifytimestamp'][0]
myChanges = []
myChanges.append(['delete', delAttr, delValue])
myChanges.append(['replace', 'modifiersname', myModifiersName])
myChanges.append(['replace', 'modifytimestamp', myModifyTimestamp])
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read modified entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges,
'includeAttrs' : myIncAttrs
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Include-Attributes:
Modify_replace, attribute NOT in include-attrs
#@TestID Include-Attributes: Modify_replace, attribute NOT in
include-attrs
#@TestPurpose Verify modify-replace operation is recorded properly
in the external changelog and include-attributes are
published
#@TestPreamble
#@TestSteps Modify entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Include-Attributes: Modify_replace, attribute NOT in include-attrs' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Include-Attributes: \
Modify_replace, attribute NOT in include-attrs. \
Verify modify-replace operation is recorded properly in the \
external changelog and include-attributes are published' % ecl_mode
</message>
<!-- We will use the entry added in a previous testcase:
! dn: cn=Inc-DESCRIPTION, ou=People, o=example
! objectclass: top
! objectclass: person
! objectclass: organizationalperson
! objectclass: inetorgperson
! cn: Inc-DESCRIPTION
! sn: Include
! description: This is my first Include-Attr value
! description: This is my second Include-Attr value
! description: This is my third Include-Attr value
!
! There are already include-attributes configured:
! 'employeenumber', 'description'
-->
<script>
myEntry = Entry('cn=Inc-DESCRIPTION', synchroSuffix)
incAttrs = ['employeenumber', 'description']
myIncAttrs = {}
replAttr = 'sn'
replValue = 'Replaced Include'
modEntry = None
eclEntry = None
</script>
<!-- Retrieve entry's include-attribute's information prior to modify
! for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : ' '.join(incAttrs)
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
stubEntry = STAXResult
for incAttr in incAttrs:
if incAttr in stubEntry.keys():
myIncAttrs[incAttr] = stubEntry[incAttr]
else:
myIncAttrs[incAttr] = ' '
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(newEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<!-- Modify entry on one of the servers:
! replace: sn
! sn: Replaced Include
-->
<call function="'modifyAnAttribute'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : myEntry.getDn(),
'attributeName' : replAttr,
'newAttributeValue' : replValue,
'changetype' : 'replace'
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntry = STAXResult
myTargetDN = modEntry['dn'][0]
myChangeType = 'modify'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myModifiersName = modEntry['modifiersname'][0]
myModifyTimestamp = modEntry['modifytimestamp'][0]
myChanges = []
myChanges.append(['replace', replAttr, replValue])
myChanges.append(['replace', 'modifiersname', myModifiersName])
myChanges.append(['replace', 'modifytimestamp', myModifyTimestamp])
# 'employeenumber' contained no value prior to the modify op, so
# expect NO 'targetemployeenumber' include-attr to be present
# in the changelog entry
myMissingIncAttrs = [incAttrs[0]]
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read modified entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges,
'includeAttrs' : myIncAttrs,
'expectMissingIncAttrs' : myMissingIncAttrs
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Include-Attributes:
Modify_replace, attribute in include-attrs
#@TestID Include-Attributes: Modify_replace, attribute in
include-attrs
#@TestPurpose Verify modify-replace operation is recorded properly
in the external changelog and include-attributes are
published
#@TestPreamble
#@TestSteps Modify entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Include-Attributes: Modify_replace, attribute in include-attrs' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Include-Attributes: \
Modify_replace, attribute in include-attrs. \
Verify modify-replace operation is recorded properly in the \
external changelog and include-attributes are published' % ecl_mode
</message>
<!-- We will use the entry added in a previous testcase:
! dn: cn=Inc-DESCRIPTION, ou=People, o=example
! objectclass: top
! objectclass: person
! objectclass: organizationalperson
! objectclass: inetorgperson
! cn: Inc-DESCRIPTION
! sn: Replaced Include
! description: This is my first Include-Attr value
! description: This is my second Include-Attr value
! description: This is my third Include-Attr value
!
! There are already include-attributes configured:
! 'employeenumber', 'description'
-->
<script>
myEntry = Entry('cn=Inc-DESCRIPTION', synchroSuffix)
incAttrs = ['employeenumber', 'description']
myIncAttrs = {}
replAttr = 'description'
replValue = 'This is my only Include-Attr value'
modEntry = None
eclEntry = None
</script>
<!-- Retrieve entry's include-attribute's information prior to modify
! for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : ' '.join(incAttrs)
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
stubEntry = STAXResult
for incAttr in incAttrs:
if incAttr in stubEntry.keys():
myIncAttrs[incAttr] = stubEntry[incAttr]
else:
myIncAttrs[incAttr] = ' '
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(newEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<!-- Modify entry on one of the servers:
! replace: description
! description: This is my only Include-Attr value
-->
<call function="'modifyAnAttribute'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : myEntry.getDn(),
'attributeName' : replAttr,
'newAttributeValue' : replValue,
'changetype' : 'replace'
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntry = STAXResult
myTargetDN = modEntry['dn'][0]
myChangeType = 'modify'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myModifiersName = modEntry['modifiersname'][0]
myModifyTimestamp = modEntry['modifytimestamp'][0]
myChanges = []
myChanges.append(['replace', replAttr, replValue])
myChanges.append(['replace', 'modifiersname', myModifiersName])
myChanges.append(['replace', 'modifytimestamp', myModifyTimestamp])
# 'employeenumber' contained no value prior to the modify op, so
# expect NO 'targetemployeenumber' include-attr to be present
# in the changelog entry
myMissingIncAttrs = [incAttrs[0]]
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read modified entry %s from server %s:%s' % \
(myEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'changes' : myChanges,
'includeAttrs' : myIncAttrs,
'expectMissingIncAttrs' : myMissingIncAttrs
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Include-Attributes:
Modrdn_deleteoldrdn_true, rdn NOT in include-attrs
#@TestID Include-Attributes: Modrdn_deleteoldrdn_true, rdn
NOT in include-attrs
#@TestPurpose Verify modrdn operation is recorded properly
in the external changelog and include-attributes are
published
#@TestPreamble
#@TestSteps Modrdn entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Include-Attributes: Modrdn_deleteoldrdn_true, rdn NOT in include-attrs' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Include-Attributes: \
Modrdn_deleteoldrdn_true, rdn NOT in include-attrs. \
Verify modrdn operation is recorded properly in the \
external changelog and include-attributes are published' % ecl_mode
</message>
<!-- We will use the entry added in a previous testcase:
! dn: cn=Inc-DESCRIPTION, ou=People, o=example
! objectclass: top
! objectclass: person
! objectclass: organizationalperson
! objectclass: inetorgperson
! sn: Replaced Include
! description: This is my only Include-Attr value
!
! There are already include-attributes configured:
! 'employeenumber', 'description'
-->
<script>
myEntry = Entry('cn=Inc-DESCRIPTION', synchroSuffix)
incAttrs = ['employeenumber', 'description']
myIncAttrs = {}
oldEntry = myEntry
newRdn = 'cn=Renamed-Include-Attr-Entry'
newEntry = Entry(newRdn, synchroSuffix)
modEntry = None
eclEntry = None
</script>
<!-- Retrieve entry's include-attribute's information prior to modify
! for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : ' '.join(incAttrs)
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
stubEntry = STAXResult
for incAttr in incAttrs:
if incAttr in stubEntry.keys():
myIncAttrs[incAttr] = stubEntry[incAttr]
else:
myIncAttrs[incAttr] = ' '
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(newEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<!-- Modify entry on one of the servers:
! newrdn: cn=Renamed-Include-Attr-Entry
! deleteoldrdn: true
-->
<call function="'modifyDn'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : oldEntry.getDn(),
'newRDN' : newRdn
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : newEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntry = STAXResult
myTargetDN = oldEntry.getDn()
myChangeType = 'modrdn'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myNewRDN = newRdn
myDeleteOldRDN = 'true'
# 'employeenumber' contained no value prior to the modify op, so
# expect NO 'targetemployeenumber' include-attr to be present
# in the changelog entry
myMissingIncAttrs = [incAttrs[0]]
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(newEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'newRDN' : myNewRDN,
'deleteOldRDN' : myDeleteOldRDN,
'includeAttrs' : myIncAttrs,
'expectMissingIncAttrs' : myMissingIncAttrs
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Include-Attributes:
Modrdn_deleteoldrdn_true, rdn in include-attrs
#@TestID Include-Attributes: Modrdn_deleteoldrdn_true, rdn
in include-attrs
#@TestPurpose Verify modrdn operation is recorded properly
in the external changelog and include-attributes are
published
#@TestPreamble Add include-attribute: 'cn'
#@TestSteps Modrdn entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Include-Attributes: Modrdn_deleteoldrdn_true, rdn in include-attrs' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Include-Attributes: \
Modrdn_deleteoldrdn_true, rdn in include-attrs. \
Verify modrdn operation is recorded properly in the \
external changelog and include-attributes are published' % ecl_mode
</message>
<!-- We will use the entry added in a previous testcase:
! dn: cn=Renamed-Include-Attr-Entry, ou=People, o=example
! objectclass: top
! objectclass: person
! objectclass: organizationalperson
! objectclass: inetorgperson
! cn: Renamed-Include-Attr-Entry
! sn: Replaced Include
! description: This is my only Include-Attr value
!
! There are already include-attributes configured:
! 'employeenumber', 'description'
-->
<script>
myEntry = Entry('cn=Renamed-Include-Attr-Entry', synchroSuffix)
incAttrs = ['cn', 'employeenumber', 'description']
myIncAttrs = {}
oldEntry = myEntry
newRdn = 'cn=NEW-Renamed-Include-Attr-Entry'
newEntry = Entry(newRdn, synchroSuffix)
modEntry = None
eclEntry = None
</script>
<!-- Configure include-attributes for synchroSuffix on master -->
<!-- Add 'cn' to the existing: 'employeenumber' and 'description'.
-->
<script>
myOptionString = """--domain-name "%s" --add ecl-include:%s""" \
% (synchroSuffix, incAttrs[0])
replServer = master
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Add include-attribute %s for suffix %s on server %s:%s' \
% (incAttrs[0], synchroSuffix, replServer.getHostname(),
replServer.getPort())
</message>
<call function="'dsconfig'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstanceAdminPort' : replServer.getAdminPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'subcommand' : 'set-external-changelog-domain-prop',
'objectType' : 'provider-name',
'objectName' : 'Multimaster Synchronization',
'optionsString' : myOptionString
}
</call>
<!-- Retrieve entry's include-attribute's information prior to modify
! for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : ' '.join(incAttrs)
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
stubEntry = STAXResult
for incAttr in incAttrs:
if incAttr in stubEntry.keys():
myIncAttrs[incAttr] = stubEntry[incAttr]
else:
myIncAttrs[incAttr] = ' '
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(newEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<!-- Modify entry on one of the servers:
! newrdn: cn=NEW-Renamed-Include-Attr-Entry
! deleteoldrdn: true
-->
<call function="'modifyDn'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : oldEntry.getDn(),
'newRDN' : newRdn
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : newEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntry = STAXResult
myTargetDN = oldEntry.getDn()
myChangeType = 'modrdn'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myNewRDN = newRdn
myDeleteOldRDN = 'true'
# 'employeenumber' contained no value prior to the modify op, so
# expect NO 'targetemployeenumber' include-attr to be present
# in the changelog entry
myMissingIncAttrs = [incAttrs[1]]
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(newEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'newRDN' : myNewRDN,
'deleteOldRDN' : myDeleteOldRDN,
'includeAttrs' : myIncAttrs,
'expectMissingIncAttrs' : myMissingIncAttrs
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Include-Attributes:
Moddn_deleteoldrdn_false, rdn in include-attrs
#@TestID Include-Attributes: Moddn_deleteoldrdn_false, rdn
in include-attrs
#@TestPurpose Verify moddn operation is recorded properly
in the external changelog and include-attributes are
published
#@TestPreamble
#@TestSteps Modddn entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Include-Attributes: Moddn_deleteoldrdn_false, rdn in include-attrs' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Include-Attributes: \
Moddn_deleteoldrdn_false, rdn in include-attrs. \
Verify moddn operation is recorded properly in the \
external changelog and include-attributes are published' % ecl_mode
</message>
<!-- We will use the entry added in a previous testcase:
! dn: cn=NEW-Renamed-Include-Attr-Entry, ou=People, o=example
! objectclass: top
! objectclass: person
! objectclass: organizationalperson
! objectclass: inetorgperson
! cn: NEW-Renamed-Include-Attr-Entry
! sn: Replaced Include
! description: This is my only Include-Attr value
!
! There are already include-attributes configured:
! 'cn', 'employeenumber', 'description'
-->
<script>
myEntry = Entry('cn=NEW-Renamed-Include-Attr-Entry', synchroSuffix)
incAttrs = ['cn', 'employeenumber', 'description']
myIncAttrs = {}
oldEntry = myEntry
newRdn = 'cn=Moved-Include-Attr-Entry'
newSuperior = 'cn=entry,ou=People,%s' % synchroSuffix
newEntry = Entry('%s,cn=entry' % newRdn, synchroSuffix)
modEntry = None
eclEntry = None
</script>
<!-- Retrieve entry's include-attribute's information prior to modify
! for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : ' '.join(incAttrs)
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
stubEntry = STAXResult
for incAttr in incAttrs:
if incAttr in stubEntry.keys():
myIncAttrs[incAttr] = stubEntry[incAttr]
else:
myIncAttrs[incAttr] = ' '
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(newEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<!-- Modify entry on one of the servers:
! newrdn: cn=Moved-Include-Attr-Entry
! newSuperior: ou=People,o=new_suffix_repl
! deleteoldrdn: false
-->
<call function="'modifyDn'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'DNToModify' : oldEntry.getDn(),
'newRDN' : newRdn,
'newSuperior' : newSuperior,
'deleteOldRDN' : 0
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : newEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
modEntry = STAXResult
myTargetDN = oldEntry.getDn()
myChangeType = 'modrdn'
myChangeTime = modEntry['modifytimestamp'][0]
myTargetEntryUUID = modEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
myNewRDN = newRdn
myNewSuperior = newSuperior
myDeleteOldRDN = 'false'
# 'employeenumber' contained no value prior to the modify op, so
# expect NO 'targetemployeenumber' include-attr to be present
# in the changelog entry
myMissingIncAttrs = [incAttrs[1]]
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(newEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="modEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'changeTime' : myChangeTime,
'targetEntryUUID' : myTargetEntryUUID,
'newRDN' : myNewRDN,
'newSuperior' : myNewSuperior,
'deleteOldRDN' : myDeleteOldRDN,
'includeAttrs' : myIncAttrs,
'expectMissingIncAttrs' : myMissingIncAttrs
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
modEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Include-Attributes:
Delete
#@TestID Include-Attributes: Delete
#@TestPurpose Verify delete operation is recorded properly
in the external changelog and include-attributes are
published
#@TestPreamble
#@TestSteps Delete entry on server A
#@TestSteps Verify servers in sync
#@TestSteps Read entry from ldap server
#@TestSteps Read last changelog entry on each repl server
#@TestSteps Check changelog entry against expected values
#@TestPostamble
#@TestResult Success if the server synchronised and the
changelog entry value check succeeds
-->
<testcase name="getTestCaseName('%s - Include-Attributes: Delete' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Include-Attributes: Delete. \
Verify delete operation is recorded properly in the \
external changelog and include-attributes are published' % ecl_mode
</message>
<!-- We will use the entry added in a previous testcase:
! dn: cn=Moved-Include-Attr-Entry, cn=entry, ou=People, o=example
! objectclass: top
! objectclass: person
! objectclass: organizationalperson
! objectclass: inetorgperson
! cn: NEW-Renamed-Include-Attr-Entry
! cn: Moved-Include-Attr-Entry
! sn: Replaced Include
! description: This is my only Include-Attr value
!
! There are already include-attributes configured:
! 'cn', 'employeenumber', 'description'
-->
<script>
myEntry = Entry('cn=Moved-Include-Attr-Entry,cn=entry',
synchroSuffix)
incAttrs = ['cn', 'employeenumber', 'description']
myIncAttrs = {}
delEntry = None
eclEntry = None
</script>
<!-- Retrieve entry information for checkChangelogEntry's sake -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'dsAttributes' : modOperationalAttrs
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the entry as read from server %s:%s: \n%s' % \
(masterHost, master.getPort(), searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
delEntry = STAXResult
myTargetDN = delEntry['dn'][0]
myChangeType = 'delete'
myTargetEntryUUID = delEntry['entryuuid'][0]
# myReplicationCSN = ----> grab from where???
# myReplicatIdentifier = ----> grab from ldap server
for incAttr in incAttrs:
if incAttr in delEntry.keys():
myIncAttrs[incAttr] = delEntry[incAttr]
else:
myIncAttrs[incAttr] = ' '
# 'employeenumber' contained no value prior to the modify op, so
# expect NO 'targetemployeenumber' include-attr to be present
# in the changelog entry
myMissingIncAttrs = [incAttrs[1]]
if ecl_mode != 'opends':
myChangeNumber = searchIndex
else:
myChangeNumber = None
</script>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read added entry %s from server %s:%s' % \
(newEntry.getDn(), masterHost, master.getPort())
</message>
</else>
</if>
<!-- Delete entry on one of the servers -->
<call function="'DeleteEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn()
}
</call>
<!-- Check delete worked on "master" server -->
<call function="'ldapSearchWithScript'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstancePort' : master.getPort(),
'dsInstanceDn' : master.getRootDn(),
'dsInstancePswd' : master.getRootPwd(),
'dsBaseDN' : myEntry.getDn(),
'dsFilter' : 'objectclass=*',
'expectedRC' : 32
}
</call>
<!-- Verify the synchronization of the trees among the servers in
the topology -->
<call function="'verifyTrees'">
[ clientHost, clientPath, master, consumerList, synchroSuffix ]
</call>
<script>
if ecl_mode == 'opends':
lastCookie = searchIndex
chgNumberFilter = None
else:
lastCookie = None
chgNumberFilter = """(changenumber>=%s)""" % searchIndex
</script>
<!-- Search changelog in the various replication servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
replServer = server
replServerPath = '%s/%s' % (replServer.getDir(), OPENDSNAME)
</script>
<message>
'Reading changelog in replication server %s:%s from index: \
%s' % \
(replServer.getHostname(), replServer.getPort(), searchIndex)
</message>
<!-- Search for entry modify -->
<call function="'SearchExternalChangelog'">
{ 'location' : replServer.getHostname(),
'dsPath' : replServerPath,
'dsInstanceHost' : replServer.getHostname(),
'dsInstancePort' : replServer.getPort(),
'dsInstanceDn' : replServer.getRootDn(),
'dsInstancePswd' : replServer.getRootPwd(),
'dsScope' : 'subordinate',
'dsBaseDN' : 'cn=changelog',
'dsFilter' : '(objectclass=*)',
'changeNumberFilter' : chgNumberFilter,
'changelogCookie' : lastCookie
}
</call>
<script>
searchRC = RC
searchResult = STAXResult[0][1]
</script>
<if expr="searchRC == 0">
<sequence>
<message>
'This is the ECL entry as read from server %s:%s: \n%s'\
% (replServer.getHostname(), replServer.getPort(),
searchResult)
</message>
<call function="'parseLdifEntry'">
{ 'ldifEntry' : searchResult }
</call>
<script>
eclEntry = STAXResult
if ecl_mode == 'opends':
nextIndex = eclEntry['changelogcookie'][0]
else:
nextChgNumber = int(eclEntry['changenumber'][0]) + 1
nextIndex = str(nextChgNumber)
</script>
<message>
'Parsed changelog entry: \n%s' % eclEntry
</message>
<message>
'Index to use for the next ECL search: %s' % nextIndex
</message>
<if expr="delEntry and eclEntry">
<call function="'checkChangelogEntry'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'changelogEntry' : eclEntry,
'targetDN' : myTargetDN,
'changeNumber' : myChangeNumber,
'changeType' : myChangeType,
'targetEntryUUID' : myTargetEntryUUID,
'includeAttrs' : myIncAttrs,
'expectMissingIncAttrs' : myMissingIncAttrs
}
</call>
<else>
<sequence>
<message log="1" level="'Error'">
'Unable to check external changelog entry \
(failed to read LDAP and/or changelog entry)'
</message>
<call function="'testFailed'"/>
</sequence>
</else>
</if>
</sequence>
<else>
<message log="1" level="'Error'">
'Could not read changelog on replication server %s:%s' \
% (replServer.getHostname(), replServer.getPort())
</message>
</else>
</if>
</sequence>
</iterate>
<script>
# set the index for the next ECL search
if nextIndex:
searchIndex = nextIndex
nextIndex = None
# reset variables, just in case
delEntry = None
eclEntry = None
</script>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
<!--- Test Case information
#@TestMarker Replication External Changelog Tests
#@TestName Replication: External Changelog: Clean up
#@TestID Clean up
#@TestPurpose Clean up environment for External Changelog tests
#@TestPreamble
#@TestSteps Clean changelog
#@TestSteps Disable replication of newReplSuffix
#@TestSteps Remove added suffixes
#@TestPostamble
#@TestResult Success if the data reset succeeds
-->
<testcase name="getTestCaseName('%s - Clean up' % ecl_mode)">
<sequence>
<call function="'testCase_Preamble'"/>
<message>
'Replication: External Changelog: %s - Clean up. \
Clean up environment for External Changelog tests' % ecl_mode
</message>
<!-- Clean newReplSuffix changes from changelog -->
<call function="'preInitializeReplication'">
{ 'location' : masterHost,
'dsPath' : masterPath,
'dsInstanceHost' : masterHost,
'dsInstanceAdminPort' : master.getAdminPort(),
'localOnly' : False,
'replicationDnList' : [newReplSuffix],
'adminUID' : adminUID,
'adminPswd' : adminPswd
}
</call>
<!-- Clean new suffixes on servers -->
<iterate var="server"
in="_topologyServerList"
indexvar="indx">
<sequence>
<script>
newSuffix = "o=new_suffix_no_repl"
newReplSuffix = "o=new_suffix_repl"
serverPath = '%s/%s' % (server.getDir(), OPENDSNAME)
</script>
<!-- Disable replication for newReplSuffix -->
<message>
'Disable replication for suffix %s on server %s:%s' % \
(newReplSuffix, server.getHostname(), server.getPort())
</message>
<call function="'disableReplication'">
{ 'location' : server.getHostname(),
'dsPath' : serverPath,
'dsInstanceHost' : server.getHostname(),
'dsInstanceAdminPort' : server.getAdminPort(),
'replicationDnList' : [newReplSuffix]
}
</call>
<!-- Remove newReplSuffix -->
<message>
'Remove suffix %s on server %s:%s' % \
(newReplSuffix, server.getHostname(), server.getPort())
</message>
<call function="'dsconfigSet'">
{ 'location' : server.getHostname(),
'dsPath' : serverPath,
'dsInstanceHost' : server.getHostname(),
'dsInstanceAdminPort' : server.getAdminPort(),
'dsInstanceDn' : server.getRootDn(),
'dsInstancePswd' : server.getRootPwd(),
'objectName' : 'backend',
'propertyType' : 'backend',
'propertyName' : 'userRoot',
'modifyType' : 'remove',
'attributeName' : 'base-dn',
'attributeValue' : newReplSuffix
}
</call>
<!-- Remove newSuffix (only present on "master" server) -->
<if expr="indx == 0">
<sequence>
<message>
'Remove suffix %s on server %s:%s' % \
(newSuffix, server.getHostname(), server.getPort())
</message>
<call function="'dsconfigSet'">
{ 'location' : server.getHostname(),
'dsPath' : serverPath,
'dsInstanceHost' : server.getHostname(),
'dsInstanceAdminPort' : server.getAdminPort(),
'dsInstanceDn' : server.getRootDn(),
'dsInstancePswd' : server.getRootPwd(),
'objectName' : 'backend',
'propertyType' : 'backend',
'propertyName' : 'userRoot',
'modifyType' : 'remove',
'attributeName' : 'base-dn',
'attributeValue' : newSuffix
}
</call>
</sequence>
</if>
</sequence>
</iterate>
<call function="'testCase_Postamble'"/>
</sequence>
</testcase>
</sequence>
</function>
</stax>