<?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 legal-notices/CDDLv1_0.txt
! or http://forgerock.org/license/CDDLv1.0.html.
! 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 legal-notices/CDDLv1_0.txt.
! 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 2012-2014 ForgeRock AS.
! -->
<stax>
<function name="get-fractional-replication-attributes" scope="local">
<function-prolog>
get the fractional-replication properties
</function-prolog>
<function-map-args>
<function-arg-def name="replicationDomain" type="required">
<function-arg-description>
replication Domain name
</function-arg-description>
<function-arg-property name="type" value="string"/>
</function-arg-def>
<function-arg-def name="server" type="required">
<function-arg-description>
target server
</function-arg-description>
</function-arg-def>
</function-map-args>
<sequence>
<message level="'debug'">
'calling get-fractional-replication-attributes(%s,%s)' % (replicationDomain,server)
</message>
<script>
domainOpt = ' -s --domain-name "%s"' % replicationDomain
includeOpt = ' --property fractional-include'
excludeOpt = ' --property fractional-exclude'
expRC = 0
</script>
<call function="'dsconfig'">
{ 'location' : server.getHostname(),
'dsPath' : '%s/%s' \
% (server.getDir(),OPENDSNAME),
'dsInstanceHost' : server.getHostname(),
'dsInstanceAdminPort' : server.getAdminPort(),
'dsInstanceDn' : server.getRootDn(),
'dsInstancePswd' : server.getRootPwd(),
'subcommand' : 'get-replication-domain-prop',
'objectType' : 'provider-name',
'objectName' : 'Multimaster Synchronization',
'optionsString' : domainOpt + includeOpt + excludeOpt,
'expectedRC' : expRC,
}
</call>
<message level="'debug'">
'%s fractional-replication attributes\n%s' % (replicationDomain,STAXResult)
</message>
<script>
retDict = {}
retRC = 0
try:
for l in STAXResult[0][1].splitlines():
lc = l.split('\t')
if lc[0] in fractionalTypes:
if len(lc) > 1:
retDict.update({lc[0]:[i.strip() for i in lc[1:]]})
else:
retDict.update({lc[0]:''})
else:
continue
except :
retRC = 1
retDict = None
</script>
<return>(retRC, retDict)</return>
</sequence>
</function>
<function name="set-fractional-replication-attributes" scope="local">
<function-prolog>
set the fractional-replication properties
</function-prolog>
<function-map-args>
<function-arg-def name="replicationDomain" type="required">
<function-arg-description>
replication Domain name
</function-arg-description>
<function-arg-property name="type" value="string"/>
</function-arg-def>
<function-arg-def name="server" type="required">
<function-arg-description>
target server
</function-arg-description>
</function-arg-def>
<function-arg-def name="include" type="optional" default="None">
<function-arg-description>
fractional-include String
</function-arg-description>
<function-arg-property name="type" value="string"/>
</function-arg-def>
<function-arg-def name="exclude" type="optional" default="None">
<function-arg-description>
fractional-exclude String
</function-arg-description>
<function-arg-property name="type" value="string"/>
</function-arg-def>
</function-map-args>
<sequence>
<script>
domainOpt = ' --domain-name "%s"' % replicationDomain
includeOpt = (' --set fractional-include:%s' % include, '')[include != None]
excludeOpt = (' --set fractional-exclude:%s' % exclude, '')[exclude != None]
expRC = expectedRC
</script>
<call function="'dsconfig'">
{ 'location' : server.getHostname(),
'dsPath' : '%s/%s' \
% (server.getDir(),OPENDSNAME),
'dsInstanceHost' : server.getHostname(),
'dsInstanceAdminPort' : server.getAdminPort(),
'dsInstanceDn' : server.getRootDn(),
'dsInstancePswd' : server.getRootPwd(),
'subcommand' : 'set-replication-domain-prop',
'objectType' : 'provider-name',
'objectName' : 'Multimaster Synchronization',
'optionsString' : domainOpt + includeOpt + excludeOpt,
'expectedRC' : expRC,
}
</call>
<message level="'debug'">
'reseting %s fractional-replication attributes' % replicationDomain
</message>
</sequence>
</function>
<function name="set-ops-fractional-replication-attributes" scope="local">
<function-prolog>
set the fractional-replication properties
</function-prolog>
<function-map-args>
<function-arg-def name="replicationDomain" type="required">
<function-arg-description>
replication Domain name
</function-arg-description>
<function-arg-property name="type" value="string"/>
</function-arg-def>
<function-arg-def name="server" type="required">
<function-arg-description>
target server
</function-arg-description>
</function-arg-def>
<function-arg-def name="include" type="optional" default="[]">
<function-arg-description>
fractional-include operations list [add/remove/set/reset]
expected List of tuples (op,string) such as :
[('add','*:jpegPhoto'),('remove','inetOrgPerson')]
</function-arg-description>
<function-arg-property name="type" value="list"/>
</function-arg-def>
<function-arg-def name="exclude" type="optional" default="[]">
<function-arg-description>
fractional-exclude operations list [add/remove/set/reset]
expected List of tuples (op,string) such as :
[('add','*:jpegPhoto'),('remove','inetOrgPerson')]
</function-arg-description>
<function-arg-property name="type" value="list"/>
</function-arg-def>
<function-arg-def name="expectedRC" type="optional" default="0">
<function-arg-description>
expected RC
</function-arg-description>
<function-arg-property name="type" value="int"/>
</function-arg-def>
<function-arg-def name="knownIssue" type="optional">
<function-arg-description>
potential known issue
</function-arg-description>
<function-arg-property name="type" value="string"/>
</function-arg-def>
</function-map-args>
<sequence>
<script>
validOps = ['add','remove','reset','set']
domainOpt = ' --domain-name "%s"' % replicationDomain
includeOpt = ''
if include:
for i in include:
if validOps.index(i[0]) == -1:
raise Exception("invalid include argument [%s]" % include)
elif i[0] == "reset":
includeOpt += ' --%s fractional-include' % i[0]
else:
includeOpt += ' --%s fractional-include:%s' % (i[0],i[1])
excludeOpt = ''
if exclude:
for e in exclude:
if validOps.index(e[0]) == -1:
raise Exception("invalid exclude argument [%s]" % exclude)
elif e[0] == 'reset':
excludeOpt += ' --%s fractional-exclude' % e[0]
else:
excludeOpt += ' --%s fractional-exclude:%s' % (e[0],e[1])
expRC = expectedRC
</script>
<call function="'dsconfig'">
{ 'location' : server.getHostname(),
'dsPath' : '%s/%s' \
% (server.getDir(),OPENDSNAME),
'dsInstanceHost' : server.getHostname(),
'dsInstanceAdminPort' : server.getAdminPort(),
'dsInstanceDn' : server.getRootDn(),
'dsInstancePswd' : server.getRootPwd(),
'subcommand' : 'set-replication-domain-prop',
'objectType' : 'provider-name',
'objectName' : 'Multimaster Synchronization',
'optionsString' : domainOpt + includeOpt + excludeOpt,
'expectedRC' : expRC,
'knownIssue' : knownIssue,
}
</call>
<message level="'debug'">
'reseting %s fractional-replication attributes' % replicationDomain
</message>
</sequence>
</function>
<function name="reset-fractional-replication-attributes" scope="local">
<function-prolog>
reset the fractional-replication properties
</function-prolog>
<function-map-args>
<function-arg-def name="replicationDomain" type="required">
<function-arg-description>
replication Domain name
</function-arg-description>
<function-arg-property name="type" value="string"/>
</function-arg-def>
<function-arg-def name="server" type="required">
<function-arg-description>
target server
</function-arg-description>
</function-arg-def>
</function-map-args>
<sequence>
<script>
domainOpt = ' --domain-name "%s"' % replicationDomain
includeOpt = ' --reset fractional-include'
excludeOpt = ' --reset fractional-exclude'
</script>
<call function="'dsconfig'">
{ 'location' : server.getHostname(),
'dsPath' : '%s/%s' \
% (server.getDir(),OPENDSNAME),
'dsInstanceHost' : server.getHostname(),
'dsInstanceAdminPort' : server.getAdminPort(),
'dsInstanceDn' : server.getRootDn(),
'dsInstancePswd' : server.getRootPwd(),
'subcommand' : 'set-replication-domain-prop',
'objectType' : 'provider-name',
'objectName' : 'Multimaster Synchronization',
'optionsString' : domainOpt + includeOpt + excludeOpt,
'expectedRC' : 0
}
</call>
<message level="'debug'">
'reseting %s fractional-replication attributes' % replicationDomain
</message>
</sequence>
</function>
<function name="replicationStatus" scope="local">
<function-prolog>
gets the status and its change date for a given replication domain
</function-prolog>
<function-map-args>
<function-required-arg name="server"/>
<function-required-arg name="replicationDomainSuffix"/>
<function-optional-arg name="expectedRC" default="0"/>
</function-map-args>
<sequence>
<!-- Search for the DN of the Replication Domain -->
<call function="'ldapSearchWithScript'">
{ 'location' : server.getHostname(),
'dsPath' : '%s/%s' \
% (server.getDir(),OPENDSNAME),
'dsInstanceHost' : server.getHostname(),
'dsInstancePort' : server.getPort(),
'dsInstanceDn' : server.getRootDn(),
'dsInstancePswd' : server.getRootPwd(),
'dsBaseDN' : replicationDomainSuffix,
'dsFilter' : 'objectclass=*',
'dsAttributes' : 'dn',
'dsDontWrap' : 'true',
}
</call>
<!-- Get the DN of the Replication Domain -->
<script>
replicationDomainDN = replicationDomainSuffix
for l in STAXResult[0][1].splitlines():
if l.startswith('dn: cn=Directory server DS'):
replicationDomainDN = l.replace('dn: ','')
</script>
<!-- Search the Replication Domain for status last-status-change-date -->
<call function="'ldapSearchWithScript'">
{ 'location' : server.getHostname(),
'dsPath' : '%s/%s' \
% (server.getDir(),OPENDSNAME),
'dsInstanceHost' : server.getHostname(),
'dsInstancePort' : server.getPort(),
'dsInstanceDn' : server.getRootDn(),
'dsInstancePswd' : server.getRootPwd(),
'dsBaseDN' : replicationDomainDN,
'dsFilter' : 'objectclass=*',
'dsAttributes' : 'status last-status-change-date',
'dsScope' : 'base',
'dsDontWrap' : 'true',
}
</call>
<if expr='RC == 0'>
<sequence>
<script>
status = None
lastChange = None
for l in STAXResult[0][1].splitlines():
if l.startswith('status'):
status = l.split(':',1)[1]
if l.startswith('last-status-change-date'):
lastChange = l.split(':',1)[1]
</script>
<return>RC == expectedRC, status, lastChange</return>
</sequence>
<else>
<return>1 == expectedRC, None</return>
</else>
</if>
</sequence>
</function>
<function name="getNumberOfEntries" scope="local">
<function-prolog>
gets the number of entries of a backend
</function-prolog>
<function-map-args>
<function-required-arg name="server"/>
<function-required-arg name="backend"/>
<function-required-arg name="domain"/>
</function-map-args>
<sequence>
<call function="'ldapSearchWithScript'">
{ 'location' : server.getHostname(),
'dsPath' : '%s/%s' \
% (server.getDir(),OPENDSNAME),
'dsInstanceHost' : server.getHostname(),
'dsInstancePort' : server.getPort(),
'dsInstanceDn' : server.getRootDn(),
'dsInstancePswd' : server.getRootPwd(),
'dsBaseDN' : 'cn=%s Backend,cn=monitor' % backend,
'dsFilter' : 'objectclass=*',
'dsAttributes' : 'ds-base-dn-entry-count',
'dsScope' : 'base',
}
</call>
<if expr='RC == 0'>
<sequence>
<script>
count = -1
for l in STAXResult[0][1].splitlines():
if l.startswith('ds-base-dn-entry-count') and \
l.endswith(domain):
count = l.split(': ',1)[1].split(' ')[0]
</script>
<return>RC, count</return>
</sequence>
<else>
<return>1, None</return>
</else>
</if>
</sequence>
</function>
<function name="getSchemaDict" scope="local">
<function-prolog>
check the schema for the equivalent of a given argument
if argument is OID then returns literal
if argument is literal returns OID
if not found return RC=1
</function-prolog>
<function-map-args>
<function-required-arg name="location"/>
<function-required-arg name="dsPath"/>
<function-required-arg name="server"/>
</function-map-args>
<sequence>
<call function="'ldapSearchWithScript'">
{ 'location' : location,
'dsPath' : dsPath,
'dsInstanceHost' : server.getHostname(),
'dsInstancePort' : server.getPort(),
'dsInstanceDn' : server.getRootDn(),
'dsInstancePswd' : server.getRootPwd(),
'dsBaseDN' : "cn=schema",
'dsFilter' : "objectclass=*",
'dsScope' : "base",
'dsAttributes' : "objectClasses attributeTypes",
'expectedRC' : "noCheck"
}
</call>
<script>
schemaContent = STAXResult[0][1]
oidDict = OIDDict()
oidDict.parseSchema(schemaContent)
</script>
<return>oidDict</return>
</sequence>
</function>
<function name="ldapsearchVerifyFrac">
<function-prolog>
verify that master and fractional replica have equivalent
</function-prolog>
<function-map-args>
<function-required-arg name="servers"/>
<function-required-arg name="keptAttributes"/>
<function-optional-arg name="baseDN" default="'o=example'"/>
<function-optional-arg name="expectedRC" default="0"/>
<function-optional-arg name="issue"/>
</function-map-args>
<sequence>
<script>
referenceTree = 'referenceTree.ldif'
filteredRefTree = 'filteredRefTree.ldif'
fractionalTree = 'fractionalTree.ldif'
treeDiffs = 'treeDiffs.ldif'
dsMaster = servers[0]
dsReplica = servers[1]
dsMasterPath = '%s/%s' % (dsMaster.getDir(),OPENDSNAME)
dsReplicaPath = '%s/%s' % (dsReplica.getDir(),OPENDSNAME)
</script>
<call function="'ldapSearchWithScript'">
{ 'location' : dsMaster.getHostname(),
'dsPath' : dsMasterPath,
'dsInstanceHost' : dsMaster.getHostname(),
'dsInstancePort' : dsMaster.getPort(),
'dsInstanceDn' : dsMaster.getRootDn(),
'dsInstancePswd' : dsMaster.getRootPwd(),
'dsBaseDN' : baseDN,
'dsFilter' : 'objectclass=*',
'dsScope' : 'sub',
'dsDontWrap' : 'true',
}
</call>
<if expr="RC == 0">
<sequence>
<script>
refFiltered = []
currentAttr = None
skipLine = False
# filter out all content that is not in the list of attribues
for f in STAXResult[0][1].splitlines():
# if entry separator
if len(f.strip()) == 0:
# if current attrib is valid
refFiltered.append(f+"\n")
currentAttr = None
skipLine = False
# if new attribute line
elif not f[0].isspace():
currentAttr = f.split(':',1)[0]
# for instance if description is a valid attribute,
# so localized description (description;lang-fr) is also valid
currentAttr = currentAttr.split(';',1)[0]
# if valid attribute
if currentAttr in keptAttributes:
refFiltered.append(f+"\n")
else:
skipLine = True
elif not skipLine:
refFiltered.append(f+"\n")
f=open('%s/%s' % (local.temp, filteredRefTree),'w')
f.writelines(refFiltered)
f.close()
</script>
<call function="'copyFile'">
{
'location' : STAXServiceMachine ,
'srcfile' : '%s/%s' % (local.temp, filteredRefTree) ,
'destfile' : '%s/%s' % (remote.temp, filteredRefTree) ,
'remotehost' : dsMaster.getHostname()
}
</call>
</sequence>
</if>
<if expr="RC == 0">
<sequence>
<call function="'ldapSearchWithScript'">
{ 'location' : dsReplica.getHostname(),
'dsPath' : dsReplicaPath,
'dsInstanceHost' : dsReplica.getHostname(),
'dsInstancePort' : dsReplica.getPort(),
'dsInstanceDn' : dsReplica.getRootDn(),
'dsInstancePswd' : dsReplica.getRootPwd(),
'dsBaseDN' : 'o=example',
'dsFilter' : 'objectclass=*',
'dsScope' : 'sub',
'dsDontWrap' : 'true',
}
</call>
</sequence>
</if>
<if expr="RC == 0">
<sequence>
<script>
filLdif = STAXResult[0][1]
f=open('%s/%s' % (local.temp, fractionalTree),'w')
f.writelines(filLdif)
f.close()
</script>
<call function="'copyFile'">
{ 'location' : STAXServiceMachine ,
'srcfile' : '%s/%s' % (local.temp, fractionalTree) ,
'destfile' : '%s/%s' % (remote.temp, fractionalTree) ,
'remotehost' : dsMaster.getHostname()
}
</call>
</sequence>
</if>
<if expr="RC == 0">
<sequence>
<call function="'LdifDiffWithScript'">
{ 'location' : dsMaster.getHostname(),
'dsPath' : dsMasterPath,
'sourceLdif' : '%s/%s' % (remote.temp, filteredRefTree),
'targetLdif' : '%s/%s' % (remote.temp, fractionalTree),
'outputLdif' : '%s/%s' % (remote.temp,treeDiffs)
}
</call>
<if expr="STAXResult == 6">
<sequence>
<return>0, None</return>
</sequence>
<else>
<sequence>
<script>
import time
tmstamp = time.time()
</script>
<call function="'copyFile'">
{ 'location' : dsMaster.getHostname(),
'srcfile' : '%s/%s' % (remote.temp,treeDiffs),
'destfile' : '%s/%s.%s' % (remote.temp,treeDiffs,tmstamp)
}
</call>
<call function="'getFile'">
{ 'location' : dsMaster.getHostname(),
'filename' : '%s/%s' % (remote.temp,treeDiffs)
}
</call>
<if expr="RC == 0">
<return>1, STAXResult[1]</return>
<else>
<return>1, None</return>
</else>
</if>
</sequence>
</else>
</if>
</sequence>
</if>
</sequence>
</function>
</stax>