mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

andrug
28.00.2008 10f74c7682e52c5caf4ea8232ea2f0b3be455e19
first version
49 files added
12165 ■■■■■ changed files
opends/tests/system-tests/clients/LDAPjdk/ldapjdk.jar patch | view | raw | blame | history
opends/tests/system-tests/clients/modifyLoad/build.ksh 37 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/clients/modifyLoad/modifyLoad.xml 286 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/clients/modifyLoad/run.ksh 28 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/clients/modifyLoad/src/Client.java 343 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/clients/modifyLoad/src/Server.java 46 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/clients/modifyLoad/src/Worker.java 107 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/clients/restartDs/restartDs.xml 125 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/clients/searchLoad/build.ksh 36 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/clients/searchLoad/run.ksh 28 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/clients/searchLoad/searchLoad.xml 258 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/clients/searchLoad/src/Client.java 355 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/clients/searchLoad/src/Server.java 46 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/clients/searchLoad/src/Worker.java 127 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/config.py 36 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/.main_run.xml.marks 1 ●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/configuration/configuration.xml 140 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/configuration/configuration_opends.xml 680 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/generateLdif/generateLdif.xml 299 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/generateLdif/inetOrgPerson.py 79 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/generateLdif/inetOrgPersonJpeg1Mb.py 79 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/generateLdif/organizationalPerson.py 57 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/generateLdif/person.py 40 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/generateLdif/scalablePerson.py 50 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/installation/installation.xml 107 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/installation/installation_opends.xml 435 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/log/log.py 48 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/log/log.xml 634 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/log/topology.xml 296 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/main_run.xml 301 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/main_run_lib.xml 341 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/parser/parser.py 1107 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/parser/parser.xml 302 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/scheduler/scheduler.py 36 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/scheduler/scheduler.xml 577 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/shared/dsadm.xml 971 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/shared/ldap.xml 906 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/shared/signals.xml 76 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/shared/stafcmd.xml 514 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/shared/staxcmd.xml 61 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/shared/utils.xml 658 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/verdict/verdict.xml 169 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/phases/verdict/verdict_opends.xml 209 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/report/opends_logo_sm.png patch | view | raw | blame | history
opends/tests/system-tests/report/result.css 142 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/report/result.xsl 680 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/scenario/conf.dtd 111 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/scenario/sample/conf.xml 147 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/scenario/sample/sample.xml 54 ●●●●● patch | view | raw | blame | history
opends/tests/system-tests/clients/LDAPjdk/ldapjdk.jar
Binary files differ
opends/tests/system-tests/clients/modifyLoad/build.ksh
New file
@@ -0,0 +1,37 @@
#!/bin/ksh
# 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
# information:
#      Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#      Copyright 2008 Sun Microsystems, Inc.
export CLASSPATH=$CLASSPATH:../LDAPjdk/ldapjdk.jar
echo "Compiling classes..."
javac src/*.java -d .
[ $? -ne 0 ] && return 1
echo "Creating jarfile"
jar cvf modify.jar *.class
[ $? -ne 0 ] && return 1
echo "Cleanup"
rm -f *.class
opends/tests/system-tests/clients/modifyLoad/modifyLoad.xml
New file
@@ -0,0 +1,286 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <defaultcall function="modifyLoad"/>
  <!-- ************************************************************ -->
  <function name="modifyLoad">
    <function-map-args>
      <function-arg-def name="client" type="required">
      </function-arg-def>
      <function-arg-def name="instances" type="required">
      </function-arg-def>
      <function-arg-def name="duration" type="required">
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- ===================   Comments   =================== -->
      <!-- client is run under paralleliterate tag              -->
      <!-- each variables defined are internal                  -->
      <!-- client should have its own err_num variable in order -->
      <!-- to inform scheduler if it has pass/fail status       -->
      <script>
        errNum = 0
      </script>
      <!-- ==================    Preamble   =================== -->
      <!-- parse the client parameters :                        -->
      <!-- params is [[param1,val1],[param2,val2],...]          -->
      <!-- get the ldap instance parameters                     -->
      <script>
        outFile = '%s/client_modifyLoad_%s.txt' % (LOG_DIR,client.getId())
        cParams = client.getParams()
        serverInstanceFromClient = cParams[0][1]
        baseDn = cParams[1][1]
        nbCnx = cParams[2][1]
        nbMaxSearch = cParams[3][1]
        attributeName = cParams[4][1]
        sys.path.append("%s/phases/scheduler" % TESTS_DIR )
        from scheduler import getInstance
        serverInstance = getInstance(serverInstanceFromClient,instances)
        if (serverInstance == 'ERROR'):
          msg = 'ERROR: cant find client instance named'
          msg = '%s %s in server instance list' %(msg,serverInstanceFromClient)
        else:
          # remove sec, try to finish before timer kill -9 the client
          duration = duration - 10
          parms=[]
          parms.append('-h %s -p %s' % \
                      (serverInstance.getHost(),serverInstance.getLDAPPort()))
          parms.append('-b "%s"' % baseDn)
          parms.append('-D "%s" -w "%s"' % \
                      (DIRECTORY_INSTANCE_DN,DIRECTORY_INSTANCE_PSWD))
          parms.append('-t %s -M %s -a %s -d %s' % \
                      (nbCnx,nbMaxSearch,attributeName,duration))
          parms = ' '.join(parms)
      </script>
      <if expr="msg.find('ERROR') != -1">
        <sequence>
          <message>'%s' % msg</message>
          <call function="'writeOperationResult'">
            {
              'returncode' : '1',
              'expected'   : '0',
              'result'     : msg,
              'status'     : 'ERROR',
              'fileFd'     : fileFd
            }
          </call>
          <script>
            errNum += 1
          </script>
        </sequence>
      <else>
        <sequence>
          <!-- ==== Add execute permission to build.ksh file ==== -->
          <call function="'writeStartTagOperation'">
          { 'tagName' : 'chmod',
            'fileFd'  : fileFd }
          </call>
          <call function="'writeMessage'">
          {'content' : 'Add execute permission to build.ksh file',
           'fileFd'  : fileFd}
          </call>
          <process name="'%s: chmod +x build.ksh' % client.getHost()">
            <location>client.getHost()</location>
            <command mode="'shell'">'chmod +x build.ksh'</command>
            <parms/>
            <workdir>'%s/clients/modifyLoad' % LOG_DIR</workdir>
            <envs>['PATH=/bin:/usr/bin']</envs>
            <stderr mode="'stdout'"/>
            <stdout/>
            <returnstdout/>
          </process>
          <call function="'checkRC'">
            { 'returncode' : RC,
              'result'     : STAXResult[0][1],
              'fileFd'     : fileFd }
          </call>
          <script>
            errNum += STAXResult
          </script>
          <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
          <!-- ==== build client : run build.ksh file ==== -->
          <call function="'writeStartTagOperation'">
          { 'tagName' : 'build',
            'fileFd'  : fileFd }
          </call>
          <call function="'writeMessage'">
          {'content' : 'Build client',
           'fileFd'  : fileFd}
          </call>
          <process name="'%s: build %s' % (client.getHost(),client.getName())">
            <location>client.getHost()</location>
            <command mode="'shell'">'./build.ksh'</command>
            <parms/>
            <workdir>'%s/clients/modifyLoad' % LOG_DIR</workdir>
            <envs>['PATH=/bin:/usr/bin']</envs>
            <stderr mode="'stdout'"/>
            <stdout/>
            <returnstdout/>
          </process>
          <call function="'checkRC'">
            { 'returncode' : RC,
              'result'     : STAXResult[0][1],
              'fileFd'     : fileFd }
          </call>
          <if expr="RC != 0">
            <message>
              'FAILED to build client %s on %s' % \
              (client.getHost(),client.getName())
            </message>
          </if>
          <script>
            errNum += STAXResult
          </script>
          <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
          <!-- ========== Run the client ========== -->
          <call function="'writeStartTagOperation'">
          { 'tagName' : 'run',
            'fileFd'  : fileFd }
          </call>
          <call function="'writeMessage'">
          { 'fileFd'  : fileFd,
            'content' : 'Do ldapsearchs on %s:%s' % \
                        (serverInstance.getHost(),serverInstance.getLDAPPort())
          }
          </call>
          <script>
            cParam = '-client -Xmx1G -Xms1G'
            cParam = '%s -XX:NewRatio=1 -XX:SurvivorRatio=100' % cParam
            cParam = '%s -cp %s/clients/LDAPjdk/ldapjdk.jar' % (cParam,LOG_DIR)
            cParam = '%s:%s/clients/searchLoad/search.jar' % (cParam,LOG_DIR)
            cParam = '%s Client %s' % (cParam,parms)
            titleName = '%s: run %s on %s' % \
                        (client.getHost(),client.getName(),
                         serverInstance.getName())
          </script>
          <process name="'%s' % titleName">
            <location>client.getHost()</location>
            <command>'java'</command>
            <parms>cParam </parms>
            <workdir>'%s/clients/searchLoad' % LOG_DIR</workdir>
            <envs>['PATH=/bin:/usr/bin']</envs>
            <stderr mode="'stdout'"/>
            <stdout>outFile</stdout>
            <returnstdout/>
          </process>
          <!-- TBD : result should be STAXResult[0][1] : problem when
                     javaexception, with carac " and < >-->
          <call function="'checkRC'">
            { 'returncode' : RC ,
              'result'     : '',
              'fileFd'     : fileFd }
          </call>
          <script>
            errNum += STAXResult
          </script>
          <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
          <!-- ========== Postamble ========== -->
          <call function="'writeMessage'">
          {'content' : 'Output file %s' % outFile,
           'fileFd'  : fileFd}
          </call>
          <process name="'%s:%s: Grep' % (client.getHost(),client.getName())">
            <location>client.getHost()</location>
            <command mode="'shell'">
              "grep 'TOTAL' %s | cut -d ' ' -f3-" % outFile
            </command>
            <envs>['PATH=/bin:/usr/bin']</envs>
            <stderr mode="'stdout'"/>
            <stdout/>
            <returnstdout/>
          </process>
          <script>
            summary = STAXResult[0][1]
          </script>
          <call function="'writeMessage'">
          {'content' : 'Summary %s' % (summary),
           'fileFd'  : fileFd}
          </call>
          <!-- ==== Copy output file in main log directory ==== -->
          <script>
            clientHostFullName = '%s%s' % (client.getHost(),DOMAIN[0])
          </script>
          <if expr="clientHostFullName != STAXServiceMachine">
            <sequence>
              <call function="'copyFile'">
                {
                  'location'   : client.getHost(),
                  'remoteHost' : STAXServiceMachine,
                  'srcFile'    : outFile,
                  'destFile'   : outFile,
                  'fileFd'     : fileFd
                }
              </call>
              <script>
                errNum += STAXResult[0]
              </script>
            </sequence>
          </if>
        </sequence>
      </else>
      </if>
      <return> errNum </return>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/clients/modifyLoad/run.ksh
New file
@@ -0,0 +1,28 @@
#!/bin/ksh
# 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
# information:
#      Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#      Copyright 2008 Sun Microsystems, Inc.
java -cp ../LDAPjdk/ldapjdk.jar:modify.jar Client $@
opends/tests/system-tests/clients/modifyLoad/src/Client.java
New file
@@ -0,0 +1,343 @@
// 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
// information:
//      Portions Copyright [yyyy] [name of copyright owner]
//
// CDDL HEADER END
//
//
//      Copyright 2008 Sun Microsystems, Inc.
import netscape.ldap.*;
import netscape.ldap.util.*;
import java.util.*;
import java.io.*;
import java.lang.Thread;
public class Client {
//    static String dn="cn=Directory Manager";
//    static String password="secret12";
    static int NB_MAX_MODS=100;
    static Object lock;
    static int nb_mods_started=0;
    static int nb_mods_done=0;
    static int total_nb_mods=0;
    static int nb_threads=3;
    public ArrayList<String> DNList;
    // String dn="cn=admin,dc=com";
//    String dn="cn=Directory Manager";
//    String password="secret12";
    Random random;
    static String attr="description";
    public String attribute;
    static String hostname ;
    static int portnumber;
    static String bindDN;
    static String bindPW;
    static String suffix;
    static Server server;
    static String time= new String ("0 sec.");;
    static long duration=0;
    static long maxDuration=0;
    static long startup=System.currentTimeMillis();
    public Client()
    {
        attribute=attr;
        random=new Random();
        lock = new Object();
        DNList=new ArrayList<String>();
        // println("INFO", "Getting DN from file " + DNFileName);
        try {
            println ("INFO", "Get the DNs on suffix \"" + suffix + "\" from server " + server );
            LDAPConnection  c = new LDAPConnection();
            // no bind
            c.connect( server.host, server.port);
            println ("INFO", "Connected to server " + server );
            // bind if needed
            if ( bindDN != null ) {
                println ("INFO", "Binding as \"" + bindDN + "\"");
                c.bind(bindDN, bindPW);
            }
            else {
                println ("INFO", "Anonymous mode (no bind)");
            }
            // no limit for nb of entries returned by a search
            Integer sizeLimit = new Integer( 0 );
            c.setOption( LDAPv3.SIZELIMIT, sizeLimit );
            LDAPSearchResults results = c.search( suffix, LDAPv3.SCOPE_SUB, "(objectclass=*)" , new String[] {"dn"} , false );
            while ( results.hasMoreElements() ) {
                Object o=null;
                try {
                    o=results.nextElement();
                    LDAPEntry entry=(LDAPEntry) o;
                    // println("DEBUG", "DN="+entry.getDN());
                    DNList.add(entry.getDN());
                }
                catch (java.lang.ClassCastException e) {
                    e.printStackTrace();
                    println ("ERROR", o.toString() );
                }
            }
            DNList.trimToSize();
            if ( DNList.size() == 0) {
                println("ERROR", "No entry found in \"" + suffix + "\"");
                System.exit(1);
            }
            println("INFO", "Found " + DNList.size() + " entries in \"" + suffix + "\" on " + server.toString() );
            c.disconnect();
        } catch (LDAPException e) {
            int errorCode = e.getLDAPResultCode();
            if ( errorCode == 32) {
                println ("WARNING", "No entry found in suffix \"" + suffix + "\"");
            }
            else {
                e.printStackTrace();
            }
            System.exit(1);
        }
        /* try {
            File DNFile= new File(DNFileName);
            LineNumberReader in=new LineNumberReader (new FileReader(DNFile) );
            while ( in.ready() ) {
                DNList.add(in.readLine());
            }
        } catch (IOException e) {
            println ("ERROR", e.toString());
            System.exit(1);
        }*/
        // DNList.trimToSize();
        //println("INFO", "Found " + DNList.size() + " DNs");
        try {
            // reinitialize startup
            startup=System.currentTimeMillis();
            long t1=System.currentTimeMillis();
            if ( maxDuration != 0 ) {
                maxDuration= t1 + maxDuration * 1000;
            }
            for (int i=0; i < nb_threads; i++ ) {
                Worker w=new Worker(this, server);
            }
            println ("INFO", nb_threads + " threads connected to server " + server );
            println ("INFO", "Will replace attribute " + attr + " (MAX =" + NB_MAX_MODS + ")" );
            int seconds=0;
            while (true) {
                long new_t1=System.currentTimeMillis();
                if ( ( maxDuration != 0 ) && ( new_t1 > maxDuration ) ) { break; }
                if ( (new_t1 - t1) >= 1000 ) {
                    println("INFO",  nb_mods_done + " mods/sec."); // (time = "+(new_t1-t1) + "ms)");
                    // println("DEBUG",  nb_mods_started + " mods/sec started");
                    total_nb_mods+=nb_mods_done;
                    nb_mods_started=0;
                    nb_mods_done=0;
                    synchronized (lock) {
                        lock.notifyAll();
                    }
                    if ( (seconds++) >= 9 ) {
                        duration=((new_t1-startup)/1000);
                        println("INFO",  "Avg rate: " + (total_nb_mods/duration) + " mods/sec. after " + getTime(duration));
                        seconds=0;
                    }
                    t1=new_t1;
                }
            }
            System.exit(0);
        }
        catch( Exception e ) {
            e.printStackTrace();
            System.exit(1);
        }
    }
    public static String getTime(long d) {
        String time=new String (d + " sec.");
        if ( d > 10000 ) {
            time=new String ((d/3600) + " hours");
        } else if ( d > 300 ) {
            time=new String ((d/60) + " min.");
        }
        return time;
    }
    public static void main( String[] args )
    {
        String usage = "Usage: java Main [-h <host>] [-p <port>]  -b <base_dn> "
                        + "[-D <bindDN> ] [-w <bindPW> ] [-t <nb_threads>] [-M <nb_max_mods>] [-a <attribute>] [-d duration (seconds)]";
        int portnumber = LDAPv2.DEFAULT_PORT;
        // Check for these options. -H means to print out a usage message.
        GetOpt options = new GetOpt( "h:p:b:d:D:w:H:t:M:a:", args );
        // Get the arguments specified for each option.
        hostname = options.getOptionParam( 'h' );
        String port = options.getOptionParam( 'p' );
        bindDN = options.getOptionParam( 'D' );
        bindPW = options.getOptionParam( 'w' );
        suffix = options.getOptionParam( 'b' );
        if ( options.hasOption( 't' ) ) {
            nb_threads=Integer.parseInt(options.getOptionParam( 't' ));
        }
        if ( options.hasOption( 'M' ) ) {
            NB_MAX_MODS=Integer.parseInt(options.getOptionParam( 'M' ));
        }
        if ( options.hasOption( 'a' ) ) {
            attr=options.getOptionParam( 'a' );
        }
        if ( options.hasOption( 'd' ) ) {
            String sMaxDuration=options.getOptionParam( 'd' );
            maxDuration = Long.parseLong(sMaxDuration);
        }
        //  option -DM to use default QA settings for Directory manager
        if ( bindDN != null && bindDN.equals("M") ) {
            bindDN="cn=Directory Manager";
            bindPW="secret12";
        }
        // Check to see if the hostname (which is mandatory)
        // is not specified or if the user simply wants to
        // see the usage message (-H).
        if ( options.hasOption( 'H' ) || ( suffix == null ) ) {
            System.out.println( usage );
            System.exit( 1 );
        }
        if ( hostname == null ) hostname="localhost";
        // If a port number was specified, convert the port value
        //  to an integer.
        if ( port != null ) {
            try {
                portnumber = java.lang.Integer.parseInt( port );
            } catch ( java.lang.Exception e ) {
                System.out.println( "Invalid port number: " + port );
                System.out.println( usage );
                System.exit( 1 );
            }
        }
        else {
            portnumber=1389;
        }
        server=new Server(hostname,portnumber);
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                duration=((System.currentTimeMillis()-startup)/1000);
                if ( duration != 0 )
                    println("INFO", "TOTAL: " + total_nb_mods + " mods (Avg rate: " + (total_nb_mods/duration) + " mods/sec.) after " + getTime(duration));
            }
        });
        Client c = new Client();
    }
   public static void inc_mods_started() {
        check_mods_started();
        nb_mods_started++;
   }
   public static void inc_mods_done() {
        nb_mods_done++;
   }
   public static void check_mods_started() {
        if ( nb_mods_started>=NB_MAX_MODS ) {
            //println("DEBUG", "Mods=" + nb_mods);
            try {
                synchronized (lock) {
                    lock.wait();
                }
            } catch ( InterruptedException e ) {
                e.printStackTrace();
            }
        }
    }
    public static void wait_after_error() {
        try {
            synchronized (lock) {
                lock.wait();
            }
        } catch ( InterruptedException e ) {
            e.printStackTrace();
        }
   }
   public static void sleep(int time) {
        try {
            Thread.sleep(time);
        }
        catch ( InterruptedException e )
        {
             println( "ERROR" ,  e.toString() );
        }
    }
    public static String getDate() {
        // Initialize the today's date string
        String DATE_FORMAT = "yyyy/MM/dd:HH:mm:ss";
        java.text.SimpleDateFormat sdf =
            new java.text.SimpleDateFormat(DATE_FORMAT);
        Calendar c1 = Calendar.getInstance(); // today
        return("[" + sdf.format(c1.getTime()) + "]");
   }
   public static void println(String level, String msg) {
        System.out.println (getDate() + " - " + level + ": " + msg );
   }
}
opends/tests/system-tests/clients/modifyLoad/src/Server.java
New file
@@ -0,0 +1,46 @@
// 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
// information:
//      Portions Copyright [yyyy] [name of copyright owner]
//
// CDDL HEADER END
//
//
//      Copyright 2008 Sun Microsystems, Inc.
import java.util.*;
public class Server {
    public String host;
    public int port;
    public Server (String host, int port) {
        this.host=host;
        this.port=port;
    }
    public Server (String hostPort) {
        StringTokenizer st = new StringTokenizer(hostPort, ":");
        this.host=st.nextToken();
        this.port=Integer.parseInt(st.nextToken());
    }
    public String toString() {
        return (host + ":" + port);
    }
}
opends/tests/system-tests/clients/modifyLoad/src/Worker.java
New file
@@ -0,0 +1,107 @@
// 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
// information:
//      Portions Copyright [yyyy] [name of copyright owner]
//
// CDDL HEADER END
//
//
//      Copyright 2008 Sun Microsystems, Inc.
import netscape.ldap.*;
import netscape.ldap.util.*;
import java.util.*;
import java.io.*;
import java.lang.Thread;
public class Worker extends Thread {
    Server server;
    Client client;
    public Worker (Client client, Server server) {
        super();
        try {
            this.server = server;
            this.client = client;
            this.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void run () {
        while (true) {
            try {
                LDAPConnection connection = new LDAPConnection();
                connection.connect( server.host, server.port);
                // bind if needed
                if ( client.bindDN != null ) {
                    // println ("INFO", "Binding as \"" + client.bindDN + "\"");
                    connection.bind(client.bindDN, client.bindPW);
                }
                while (true) {
                    try {
                        client.inc_mods_started();
                        String value=String.valueOf(client.random.nextInt(10000));
                        String myDN=(String) client.DNList.get(client.random.nextInt(client.DNList.size()));
                        //println ("INFO", "Modifying \""+myDN+"\" (replace "+ attribute + ":" + value + ") on master " + master.toString());
                        connection.modify(myDN, new LDAPModification (LDAPModification.REPLACE, new LDAPAttribute(client.attribute, value )));
                        client.inc_mods_done();
                    } catch (LDAPException e) {
                            // println("ERROR", e.toString());
                            // Client.wait_after_error();
                            try {
                                synchronized (client.lock) {
                                    client.lock.wait();
                                }
                            } catch ( InterruptedException ie ) {
                                ie.printStackTrace();
                            }
                    }
                }
            }
            catch( LDAPException e ) {
              println( "ERROR" , e.toString() );
//                System.exit(1);
            }
        }
    }
    private String getDate() {
        // Initialize the today's date string
        String DATE_FORMAT = "yyyy/MM/dd:HH:mm:ss";
        java.text.SimpleDateFormat sdf =
            new java.text.SimpleDateFormat(DATE_FORMAT);
        Calendar c1 = Calendar.getInstance(); // today
        return("[" + sdf.format(c1.getTime()) + "]");
   }
   private void println(String level, String msg) {
        System.out.println (getDate() + " - " + level + ": (" + server + ") " + msg );
   }
}
opends/tests/system-tests/clients/restartDs/restartDs.xml
New file
@@ -0,0 +1,125 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <defaultcall function="restartDs"/>
  <!-- ************************************************************ -->
  <function name="restartDs">
    <function-map-args>
      <function-arg-def name="client" type="required">
      </function-arg-def>
      <function-arg-def name="instances" type="required">
      </function-arg-def>
      <function-arg-def name="duration" type="required">
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- ===================   Comments   =================== -->
      <!-- client is run under paralleliterate tag              -->
      <!-- each variables defined are internal                  -->
      <!-- client should have its own err_num variable in order -->
      <!-- to inform scheduler if it has pass/fail status       -->
      <script>
        errNum = 0
      </script>
      <!-- ==================    Preamble   =================== -->
      <!-- parse the client parameters :                        -->
      <!-- params is [[param1,val1],[param2,val2],...]          -->
      <!-- get the ldap instance parameters                     -->
      <script>
        cParams = client.getParams()
        serverInstanceFromClient = cParams[0][1]
        sys.path.append("%s/phases/scheduler" % TESTS_DIR )
        from scheduler import getInstance
        serverInstance = getInstance(serverInstanceFromClient,instances)
        if (serverInstance == 'ERROR'):
          msg = 'ERROR: cant find client instance named'
          msg = '%s %s in server instance list' %(msg,serverInstanceFromClient)
      </script>
      <if expr="msg.find('ERROR') != -1">
        <sequence>
          <message>'%s' % msg</message>
          <call function="'writeOperationResult'">
            {
              'returncode' : '1',
              'expected'   : '0',
              'result'     : msg,
              'status'     : 'ERROR',
              'fileFd'     : fileFd
            }
          </call>
        </sequence>
      <else>
        <sequence>
          <!-- ==== Stop DS ==== -->
          <call function="'StopDsWithScript'">
            { 'location'  : serverInstance.getHost(),
              'dsPath'    : serverInstance.getInstallDir(),
              'fileFd'    : fileFd
            }
          </call>
          <script>
            errNum += STAXResult[0]
          </script>
          <!-- ==== Start DS ==== -->
          <call function="'StartDsWithScript'">
            { 'location'  : serverInstance.getHost(),
              'dsPath'    : serverInstance.getInstallDir(),
              'fileFd'    : fileFd
            }
          </call>
          <script>
            errNum += STAXResult[0]
          </script>
        </sequence>
      </else>
      </if>
      <return> errNum </return>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/clients/searchLoad/build.ksh
New file
@@ -0,0 +1,36 @@
#!/bin/ksh
# 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
# information:
#      Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#      Copyright 2008 Sun Microsystems, Inc.
export CLASSPATH=$CLASSPATH:../LDAPjdk/ldapjdk.jar
echo "Compiling classes..."
javac src/*.java -d .
[ $? -ne 0 ] && return 1
echo "Creating jarfile"
jar cvf search.jar *.class
[ $? -ne 0 ] && return 1
echo "Cleanup"
rm -f *.class
opends/tests/system-tests/clients/searchLoad/run.ksh
New file
@@ -0,0 +1,28 @@
#!/bin/ksh
# 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
# information:
#      Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#      Copyright 2008 Sun Microsystems, Inc.
java -client -Xmx1G -Xms1G -XX:NewRatio=1 -XX:SurvivorRatio=100 -cp ../LDAPjdk/ldapjdk.jar:search.jar Client $@
opends/tests/system-tests/clients/searchLoad/searchLoad.xml
New file
@@ -0,0 +1,258 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE stax SYSTEM "../../../functional-tests/shared/stax.dtd">
<stax>
  <defaultcall function="searchLoad"/>
  <!-- ************************************************************ -->
  <function name="searchLoad">
    <function-map-args>
      <function-arg-def name="client" type="required">
      </function-arg-def>
      <function-arg-def name="instances" type="required">
      </function-arg-def>
      <function-arg-def name="duration" type="required">
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- ===================   Comments   =================== -->
      <!-- client is run under paralleliterate tag              -->
      <!-- each variables defined are internal                  -->
      <!-- client should have its own err_num variable in order -->
      <!-- to inform scheduler if it has pass/fail status       -->
      <script>
        errNum = 0
      </script>
      <!-- ==================    Preamble   =================== -->
      <!-- parse the client parameters :                        -->
      <!-- params is [[param1,val1],[param2,val2],...]          -->
      <!-- get the ldap instance parameters                     -->
      <script>
        outFile = '%s/client_searchLoad_%s.txt' % (LOG_DIR,client.getId())
        cParams = client.getParams()
        serverInstanceFromClient = cParams[0][1]
        baseDn = cParams[1][1]
        nbCnx = cParams[2][1]
        nbMaxSearch = cParams[3][1]
        attributeName = cParams[4][1]
        sys.path.append("%s/phases/scheduler" % TESTS_DIR )
        from scheduler import getInstance
        serverInstance = getInstance(serverInstanceFromClient,instances)
        if (serverInstance == 'ERROR'):
          msg = 'ERROR: cant find client instance named'
          msg = '%s %s in server instance list' %(msg,serverInstanceFromClient)
        else:
          # remove sec, try to finish before timer kill -9 the client
          duration = duration - 10
          parms=[]
          parms.append('-h %s -p %s' % \
                      (serverInstance.getHost(),serverInstance.getLDAPPort()))
          parms.append('-b "%s"' % baseDn)
          parms.append('-D "%s" -w "%s"' % \
                      (DIRECTORY_INSTANCE_DN,DIRECTORY_INSTANCE_PSWD))
          parms.append('-t %s -M %s -a %s -d %s' % \
                      (nbCnx,nbMaxSearch,attributeName,duration))
          parms = ' '.join(parms)
      </script>
      <if expr="msg.find('ERROR') != -1">
        <sequence>
          <message>'%s' % msg</message>
          <call function="'writeOperationResult'">
            {
              'returncode' : '1',
              'expected'   : '0',
              'result'     : msg,
              'status'     : 'ERROR',
              'fileFd'     : fileFd
            }
          </call>
          <script>
            errNum += 1
          </script>
        </sequence>
      <else>
        <sequence>
          <!-- ==== Add execute permission to build.ksh file ==== -->
          <call function="'writeStartTagOperation'">
          { 'tagName' : 'chmod',
            'fileFd'  : fileFd }
          </call>
          <call function="'writeMessage'">
          {'content' : 'Add execute permission to build.ksh file',
           'fileFd'  : fileFd}
          </call>
          <process name="'%s: chmod +x build.ksh' % client.getHost()">
            <location>client.getHost()</location>
            <command mode="'shell'">'chmod +x build.ksh'</command>
            <parms/>
            <workdir>'%s/clients/searchLoad' % LOG_DIR</workdir>
            <envs>['PATH=/bin:/usr/bin']</envs>
            <stderr mode="'stdout'"/>
            <stdout/>
            <returnstdout/>
          </process>
          <call function="'checkRC'">
            { 'returncode' : RC,
              'result'     : STAXResult[0][1],
              'fileFd'     : fileFd }
          </call>
          <script>
            errNum += STAXResult
          </script>
          <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
          <!-- ==== build client : run build.ksh file ==== -->
          <call function="'writeStartTagOperation'">
          { 'tagName' : 'build',
            'fileFd'  : fileFd }
          </call>
          <call function="'writeMessage'">
          {'content' : 'Build client',
           'fileFd'  : fileFd}
          </call>
          <process name="'%s: build %s' % (client.getHost(),client.getName())">
            <location>client.getHost()</location>
            <command mode="'shell'">'./build.ksh'</command>
            <parms/>
            <workdir>'%s/clients/searchLoad' % LOG_DIR</workdir>
            <envs>['PATH=/bin:/usr/bin']</envs>
            <stderr mode="'stdout'"/>
            <stdout/>
            <returnstdout/>
          </process>
          <call function="'checkRC'">
            { 'returncode' : RC,
              'result'     : STAXResult[0][1],
              'fileFd'     : fileFd }
          </call>
          <if expr="RC != 0">
            <message>
              'FAILED to build client %s on %s' % \
              (client.getHost(),client.getName())
            </message>
          </if>
          <script>
            errNum += STAXResult
          </script>
          <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
          <!-- ========== Run the client ========== -->
          <call function="'writeStartTagOperation'">
          { 'tagName' : 'run',
            'fileFd'  : fileFd }
          </call>
          <call function="'writeMessage'">
          { 'fileFd'  : fileFd,
            'content' : 'Do ldapsearchs on %s:%s' % \
                        (serverInstance.getHost(),serverInstance.getLDAPPort())
          }
          </call>
          <script>
            cParam = '-client -Xmx1G -Xms1G'
            cParam = '%s -XX:NewRatio=1 -XX:SurvivorRatio=100' % cParam
            cParam = '%s -cp %s/clients/LDAPjdk/ldapjdk.jar' % (cParam,LOG_DIR)
            cParam = '%s:%s/clients/searchLoad/search.jar' % (cParam,LOG_DIR)
            cParam = '%s Client %s' % (cParam,parms)
            titleName = '%s: run %s on %s' % \
                        (client.getHost(),client.getName(),
                         serverInstance.getName())
          </script>
          <process name="'%s' % titleName">
            <location>client.getHost()</location>
            <command>'java'</command>
            <parms>cParam </parms>
            <workdir>'%s/clients/searchLoad' % LOG_DIR</workdir>
            <envs>['PATH=/bin:/usr/bin']</envs>
            <stderr mode="'stdout'"/>
            <stdout>outFile</stdout>
            <returnstdout/>
          </process>
          <!-- TBD : result should be STAXResult[0][1] : problem when
                     javaexception, with carac " and < >-->
          <call function="'checkRC'">
            { 'returncode' : RC ,
              'result'     : '',
              'fileFd'     : fileFd }
          </call>
          <script>
            errNum += STAXResult
          </script>
          <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
          <!-- ========== Postamble ========== -->
          <call function="'writeMessage'">
          {'content' : 'Output file %s' % outFile,
           'fileFd'  : fileFd}
          </call>
          <process name="'%s:%s: Grep' % (client.getHost(),client.getName())">
            <location>client.getHost()</location>
            <command mode="'shell'">
              "grep 'TOTAL' %s | cut -d ' ' -f3-" % outFile
            </command>
            <envs>['PATH=/bin:/usr/bin']</envs>
            <stderr mode="'stdout'"/>
            <stdout/>
            <returnstdout/>
          </process>
          <script>
            summary = STAXResult[0][1]
          </script>
          <call function="'writeMessage'">
          {'content' : 'Summary %s' % (summary),
           'fileFd'  : fileFd}
          </call>
          <!-- ==== Copy output file in main log directory ==== -->
          <script>
            clientHostFullName = '%s%s' % (client.getHost(),DOMAIN[0])
          </script>
          <if expr="clientHostFullName != STAXServiceMachine">
            <sequence>
              <call function="'copyFile'">
                {
                  'location'   : client.getHost(),
                  'remoteHost' : STAXServiceMachine,
                  'srcFile'    : outFile,
                  'destFile'   : outFile,
                  'fileFd'     : fileFd
                }
              </call>
              <script>
                errNum += STAXResult[0]
              </script>
            </sequence>
          </if>
        </sequence>
      </else>
      </if>
      <return> errNum </return>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/clients/searchLoad/src/Client.java
New file
@@ -0,0 +1,355 @@
// 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
// information:
//      Portions Copyright [yyyy] [name of copyright owner]
//
// CDDL HEADER END
//
//
//      Copyright 2008 Sun Microsystems, Inc.
import netscape.ldap.*;
import netscape.ldap.util.*;
import java.util.*;
import java.io.*;
import java.lang.Thread;
public class Client {
//    static String dn="cn=Directory Manager";
//    static String password="secret12";
    static int NB_MAX_srchs=100;
    static Object lock;
    static int nb_srchs_started=0;
    static int nb_srchs_done=0;
    static int total_nb_srchs=0;
    static int nb_threads=3;
    public ArrayList<String> ValueList;
    // String dn="cn=admin,dc=com";
//    String dn="cn=Directory Manager";
//    String password="secret12";
    Random random;
    static String attr="cn";
    public String attribute;
    static String hostname ;
    static int portnumber;
    static String bindDN;
    static String bindPW;
    static String suffix;
    static Server server;
    static String time= new String ("0 sec.");;
    static long duration=0;
    static long maxDuration=0;
    static long startup=System.currentTimeMillis();
    public Client()
    {
        attribute=attr;
        random=new Random();
        lock = new Object();
        ValueList=new ArrayList<String>();
        // println("INFO", "Getting DN from file " + DNFileName);
        try {
            println ("INFO", "Get the DNs on suffix \"" + suffix + "\" from server " + server );
            LDAPConnection  c = new LDAPConnection();
            // no bind
            c.connect( server.host, server.port);
            println ("INFO", "Connected to server " + server );
            // bind if needed
            if ( bindDN != null ) {
                println ("INFO", "Binding as \"" + bindDN + "\"");
                c.bind(bindDN, bindPW);
            }
            else {
                println ("INFO", "Anonymous mode (no bind)");
            }
            // no limit for nb of entries returned by a search
            Integer sizeLimit = new Integer( 0 );
            c.setOption( LDAPv3.SIZELIMIT, sizeLimit );
            LDAPSearchResults results = c.search( suffix, LDAPv3.SCOPE_SUB, "(objectclass=*)" , new String[] {attr} , false );
            while ( results.hasMoreElements() ) {
                Object o=null;
                try {
                    o=results.nextElement();
                    LDAPEntry entry=(LDAPEntry) o;
                    //  hack for oracle
                    if ( entry == null ) {
                        break;
                    }
                    // println("DEBUG", "DN="+entry.getDN());
                    LDAPAttribute a = entry.getAttribute(attr);
                    if ( a == null ) {
                        continue;
                    }
                    for ( String value: a.getStringValueArray()) {
                        ValueList.add( value );
                    }
                }
                catch (java.lang.ClassCastException e) {
                    e.printStackTrace();
                    println ("ERROR", o.toString() );
                }
            }
            ValueList.trimToSize();
            if ( ValueList.size() == 0) {
                println ("ERROR", "No values found for attribute  " + attr + " in suffix \"" + suffix + "\"");
                System.exit(1);
            }
            println("INFO", "Found " + ValueList.size() + " values for attribute " + attr + " in \"" + suffix + "\" on " + server.toString() );
            c.disconnect();
        } catch (LDAPException e) {
            int errorCode = e.getLDAPResultCode();
            if ( errorCode == 32) {
                println ("ERROR", "Base dn \"" + suffix + "\" not found");
            }
            else {
                e.printStackTrace();
            }
            System.exit(1);
        }
        /* try {
            File DNFile= new File(DNFileName);
            LineNumberReader in=new LineNumberReader (new FileReader(DNFile) );
            while ( in.ready() ) {
                ValueList.add(in.readLine());
            }
        } catch (IOException e) {
            println ("ERROR", e.toString());
            System.exit(1);
        }*/
        // ValueList.trimToSize();
        //println("INFO", "Found " + ValueList.size() + " DNs");
        try {
            // reinitialize startup
            startup=System.currentTimeMillis();
            long t1=System.currentTimeMillis();
            if ( maxDuration != 0 ) {
                maxDuration= t1 + maxDuration * 1000;
            }
            for (int i=0; i < nb_threads; i++ ) {
                Worker w=new Worker(this, server);
            }
            println ("INFO", nb_threads + " threads connected to server " + server );
            println ("INFO", "Will search using filter \"(" + attr + " = <value> )\" (MAX =" + NB_MAX_srchs + ")" );
            synchronized (lock) {
                lock.notifyAll();
            }
            int seconds=0;
            while (true) {
                long new_t1=System.currentTimeMillis();
                if ( ( maxDuration != 0 ) && ( new_t1 > maxDuration ) ) { break; }
                if ( (new_t1 - t1) >= 1000 ) {
                    println("INFO",  nb_srchs_done + " srchs/sec."); // (time = "+(new_t1-t1) + "ms)");
                    // println("DEBUG",  nb_srchs_started + " srchs/sec started");
                    total_nb_srchs+=nb_srchs_done;
                    nb_srchs_started=0;
                    nb_srchs_done=0;
                    synchronized (lock) {
                        lock.notifyAll();
                    }
                    if ( (seconds++) >= 9 ) {
                        duration=((new_t1-startup)/1000);
                        println("INFO",  "Avg rate: " + (total_nb_srchs/duration) + " srchs/sec. after " + getTime(duration));
                        seconds=0;
                    }
                    t1=new_t1;
                }
            }
            System.exit(0);
        }
        catch( Exception e ) {
            e.printStackTrace();
            System.exit(1);
        }
    }
    public static String getTime(long d) {
        String time=new String (d + " sec.");
        if ( d > 10000 ) {
            time=new String ((d/3600) + " hours");
        } else if ( d > 300 ) {
            time=new String ((d/60) + " min.");
        }
        return time;
    }
    public static void main( String[] args )
    {
        String usage = "Usage: java Main [-h <host>] [-p <port>]  -b <base_dn> "
                        + "[-D <bindDN> ] [-w <bindPW> ] [-t <nb_threads>] [-M <nb_max_srchs>] [-a <attribute>] [-d duration (seconds)]";
        int portnumber = LDAPv2.DEFAULT_PORT;
        // Check for these options. -H means to print out a usage message.
        GetOpt options = new GetOpt( "h:p:b:d:D:w:H:t:M:a:", args );
        // Get the arguments specified for each option.
        hostname = options.getOptionParam( 'h' );
        String port = options.getOptionParam( 'p' );
        bindDN = options.getOptionParam( 'D' );
        bindPW = options.getOptionParam( 'w' );
        suffix = options.getOptionParam( 'b' );
        if ( options.hasOption( 't' ) ) {
            nb_threads=Integer.parseInt(options.getOptionParam( 't' ));
        }
        if ( options.hasOption( 'M' ) ) {
            NB_MAX_srchs=Integer.parseInt(options.getOptionParam( 'M' ));
        }
        if ( options.hasOption( 'a' ) ) {
            attr=options.getOptionParam( 'a' );
        }
        if ( options.hasOption( 'd' ) ) {
            String sMaxDuration=options.getOptionParam( 'd' );
            maxDuration = Long.parseLong(sMaxDuration);
        }
        //  option -DM to use default QA settings for Directory manager
        if ( bindDN != null && bindDN.equals("M") ) {
            bindDN="cn=Directory Manager";
            bindPW="secret12";
        }
        // Check to see if the hostname (which is mandatory)
        // is not specified or if the user simply wants to
        // see the usage message (-H).
        if ( options.hasOption( 'H' ) || ( suffix == null ) ) {
            System.out.println( usage );
            System.exit( 1 );
        }
        if ( hostname == null ) hostname="localhost";
        // If a port number was specified, convert the port value
        //  to an integer.
        if ( port != null ) {
            try {
                portnumber = java.lang.Integer.parseInt( port );
            } catch ( java.lang.Exception e ) {
                System.out.println( "Invalid port number: " + port );
                System.out.println( usage );
                System.exit( 1 );
            }
        }
        else {
            portnumber=1389;
        }
        server=new Server(hostname,portnumber);
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                duration=((System.currentTimeMillis()-startup)/1000);
                if ( duration != 0 )
                    println("INFO", "TOTAL: " + total_nb_srchs + " srchs (Avg rate: " + (total_nb_srchs/duration) + " srchs/sec.) after " + getTime(duration));
            }
        });
        Client c = new Client();
    }
   public static void inc_srchs_started() {
        check_srchs_started();
        nb_srchs_started++;
   }
   public static void inc_srchs_done() {
        nb_srchs_done++;
   }
   public static void check_srchs_started() {
        if ( nb_srchs_started>=NB_MAX_srchs ) {
            // println("DEBUG", "srchs=" + nb_srchs_started );
            try {
                synchronized (lock) {
                    lock.wait();
                }
            } catch ( InterruptedException e ) {
                e.printStackTrace();
            }
        }
    }
    public static void wait_after_error() {
        try {
            synchronized (lock) {
                lock.wait();
            }
        } catch ( InterruptedException e ) {
            e.printStackTrace();
        }
   }
   public static void sleep(int time) {
        try {
            Thread.sleep(time);
        }
        catch ( InterruptedException e )
        {
             println( "ERROR" ,  e.toString() );
        }
    }
    public static String getDate() {
        // Initialize the today's date string
        String DATE_FORMAT = "yyyy/MM/dd:HH:mm:ss";
        java.text.SimpleDateFormat sdf =
            new java.text.SimpleDateFormat(DATE_FORMAT);
        Calendar c1 = Calendar.getInstance(); // today
        return("[" + sdf.format(c1.getTime()) + "]");
   }
   public static void println(String level, String msg) {
        System.out.println (getDate() + " - " + level + ": " + msg );
   }
}
opends/tests/system-tests/clients/searchLoad/src/Server.java
New file
@@ -0,0 +1,46 @@
// 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
// information:
//      Portions Copyright [yyyy] [name of copyright owner]
//
// CDDL HEADER END
//
//
//      Copyright 2008 Sun Microsystems, Inc.
import java.util.*;
public class Server {
    public String host;
    public int port;
    public Server (String host, int port) {
        this.host=host;
        this.port=port;
    }
    public Server (String hostPort) {
        StringTokenizer st = new StringTokenizer(hostPort, ":");
        this.host=st.nextToken();
        this.port=Integer.parseInt(st.nextToken());
    }
    public String toString() {
        return (host + ":" + port);
    }
}
opends/tests/system-tests/clients/searchLoad/src/Worker.java
New file
@@ -0,0 +1,127 @@
// 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
// information:
//      Portions Copyright [yyyy] [name of copyright owner]
//
// CDDL HEADER END
//
//
//      Copyright 2008 Sun Microsystems, Inc.
import netscape.ldap.*;
import netscape.ldap.util.*;
import java.util.*;
import java.io.*;
import java.lang.Thread;
public class Worker extends Thread {
    Server server;
    Client client;
    public Worker (Client client, Server server) {
        super();
        try {
            this.server = server;
            this.client = client;
            this.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void run () {
        String value="";
        String[] attributes =  new String []{client.attr};
        LDAPConnection connection = new LDAPConnection();
        while (true) {
            try {
                connection.connect( server.host, server.port);
                // bind if needed
                if ( client.bindDN != null ) {
                    // println ("INFO", "Binding as \"" + client.bindDN + "\"");
                    connection.bind(client.bindDN, client.bindPW);
                }
                /* try {
                    synchronized (client.lock) {
                        client.lock.wait();
                    }
                } catch ( InterruptedException ie ) {
                    ie.printStackTrace();
                }*/
            while (true) {
                    //try {
                        client.inc_srchs_started();
                        value=(String) client.ValueList.get(client.random.nextInt(client.ValueList.size()));
                        //println ("INFO", "Modifying \""+myDN+"\" (replace "+ attribute + ":" + value + ") on master " + master.toString());
                        //connection.search(client.suffix, LDAPv3.SCOPE_SUB, new String (client.attr + "=" + value ), new String []{}, false );
                        //connection.search(client.suffix, LDAPv3.SCOPE_SUB, new String (client.attr + "=" + value ), new String []{client.attr}, false );
                        LDAPSearchResults results=connection.search(client.suffix, LDAPv3.SCOPE_SUB, new String (client.attr + "=" + value ), attributes, false );
                        while ( results.hasMoreElements() ) {
                            LDAPEntry entry=results.next();
                        }
                        client.inc_srchs_done();
                        results=null;
                    //} catch (LDAPException e) {
                    //        println("ERROR", e.toString());
                            // Client.wait_after_error();
                    /*        try {
                                synchronized (client.lock) {
                                    client.lock.wait();
                                }
                            } catch ( InterruptedException ie ) {
                                ie.printStackTrace();
                            }  */
                    //}
                }
            }
            catch( LDAPException e ) {
                println( "ERROR" , e.toString() );
                // make sure we are disconnected
                try {
                    connection.disconnect();
                }
                catch( LDAPException e2 ) {
                    println( "ERROR" , e2.toString() );
                }
//                System.exit(1);
            }
        }
    }
    private String getDate() {
        // Initialize the today's date string
        String DATE_FORMAT = "yyyy/MM/dd:HH:mm:ss";
        java.text.SimpleDateFormat sdf =
            new java.text.SimpleDateFormat(DATE_FORMAT);
        Calendar c1 = Calendar.getInstance(); // today
        return("[" + sdf.format(c1.getTime()) + "]");
   }
   private void println(String level, String msg) {
        System.out.println (getDate() + " - " + level + ": (" + server + ") " + msg );
   }
}
opends/tests/system-tests/config.py
New file
@@ -0,0 +1,36 @@
# 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
# information:
#      Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#      Copyright 2008 Sun Microsystems, Inc.
# Before running system-tests, you need to replace all NEED_VALUE
STAF_LOCAL_HOSTNAME         = 'localhost'
STAF_REMOTE_HOSTNAME        = 'localhost'
TMPDIR                      = 'NEED_VALUE'
OPENDSDIR                   = 'NEED_VALUE'
TESTS_ROOT                  = '%s/tests' % OPENDSDIR
TESTS_DIR                   = '%s/system-tests' % TESTS_ROOT
DIRECTORY_INSTANCE_DN       = 'cn=directory manager'
DIRECTORY_INSTANCE_PSWD     = 'secret12'
JAVA_HOME                   = 'NEED_VALUE'
opends/tests/system-tests/phases/.main_run.xml.marks
New file
@@ -0,0 +1 @@
!t;9599;9599
opends/tests/system-tests/phases/configuration/configuration.xml
New file
@@ -0,0 +1,140 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <defaultcall function="configuration"/>
  <!-- ************************************************************ -->
  <function name="configuration">
    <function-map-args>
      <function-arg-def name="instances" type="required">
        <function-arg-description>
          list of instances classes
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="suffix" type="required">
        <function-arg-description>
          suffix class
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- == Call preambule == -->
      <call function="'phasePreamble'">
      { 'phaseName' : 'configuration' ,
        'fileFd'    : LOG_MAIN_FD }
      </call>
      <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
      file="'%s/phases/configuration/configuration_opends.xml' % (TESTS_DIR)"/>
      <script>
        prefix = "phase_cfg"
        fileList = STAXGlobal([])
      </script>
      <!-- == Get the list of opends instances in the topology == -->
      <script>
        opendsInstances = []
        msg = ''
        topoInstances = suffix.getTopology()
        sys.path.append("%s/phases/parser" % TESTS_DIR )
        from parser import getRefObjectByName
        for topoInstance in topoInstances:
          result = getRefObjectByName(topoInstance.getName(),instances)
          if result[0] != '':
            msg = '%s\n%s' % (msg,result[0])
          currentInstance = result[1]
          if currentInstance.getProduct() == 'opends':
            opendsInstances.append(currentInstance)
      </script>
      <if expr="msg != ''">
        <sequence>
          <message>'%s' % msg</message>
          <call function="'writeMessage'">
          { 'fileFd'  : fileFd,
            'content' : msg
          }
          </call>
          <script>ERR_NUM[0] += 1</script>
        </sequence>
      </if>
      <!-- == Configure opends == -->
      <call function="'configureOpends'">
        {
          'topoInstances' : opendsInstances,
          'filePrefix'    : prefix,
          'suffix'        : suffix
        }
      </call>
      <!-- ==  Merge files == -->
      <call function="'mergeFiles'">
        {
          'fileList' : fileList,
          'fileFd'   : LOG_MAIN_FD
        }
      </call>
      <!-- == Compare entries == -->
      <iterate in="opendsInstances" var="instance">
        <sequence>
          <call function="'verifyTrees'">
            {
              'location'   : instance.getHost(),
              'instance'   : instance,
              'instances'  : opendsInstances,
              'suffixDn'   : suffix.getSuffixDn(),
              'filePrefix' : 'init',
              'fileFd'     : LOG_MAIN_FD
            }
          </call>
        </sequence>
      </iterate>
      <!-- ==  Call postphase == -->
      <call function="'phasePostamble'">
      {
        'phaseName' : 'configuration',
        'fileFd'    : LOG_MAIN_FD
      }
      </call>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/phases/configuration/configuration_opends.xml
New file
@@ -0,0 +1,680 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <!--==============================================================-->
  <!--=================  CONFIGURE OPENDS ==========================-->
  <!--==============================================================-->
  <function name="configureOpends">
    <function-map-args>
      <function-arg-def name="topoInstances" type="required">
        <function-arg-description>
          list of opends in current suffix topology
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="filePrefix" type="required">
        <function-arg-description>
          prefix for output files
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="suffix" type="required">
        <function-arg-description>
          suffix class
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- ===== Start instances ===== -->
      <paralleliterate in="topoInstances" var="instance">
        <sequence>
          <script>
            logName = '%s_%s' % (instance.getHost(),instance.getName())
            logFile = '%s/%s_%s.xml' % (LOG_XML_TMP_DIR,filePrefix,logName)
            fileList.append(logFile)
            cFileFd = open(logFile,'w')
            str = '\n&lt;instance name=\"%s\"' % instance.getName()
            str = '%s host=\"%s\"' % (str, instance.getHost())
            str = '%s port=\"%s\"' % (str, instance.getLDAPPort())
            str = '%s product=\"opends\"&gt;\n' % str
            cFileFd.write(str)
          </script>
          <call function="'isAlive'">
            { 'location'         : instance.getHost(),
              'noOfLoops'        : 1,
              'noOfMilliSeconds' : 2000,
              'dsPath'           : instance.getInstallDir(),
              'dsInstanceHost'   : instance.getHost(),
              'dsInstancePort'   : instance.getLDAPPort(),
              'fileFd'           : cFileFd
            }
          </call>
          <script>isAliveResult = STAXResult</script>
          <if expr="isAliveResult == FALSE">
            <call function="'StartDsWithScript'">
              { 'location'  : instance.getHost(),
                 'dsPath'   : instance.getInstallDir(),
                 'fileFd'   : cFileFd
              }
            </call>
          </if>
          <script>
            cFileFd.close()
            cFileFd = ''
          </script>
        </sequence>
      </paralleliterate>
      <!-- ==== Configure sequentially replication on intances     ==== -->
      <!--      configure replication with topoInstances[0] and each    -->
      <!--      other instances in the topoInstances list               -->
      <!--      do not use parrallel run                                -->
      <iterate in="topoInstances" var="instance">
        <sequence>
          <script>
            found = FALSE
            i = 0
            while found == FALSE:
              if topoInstances[i].getREPLPort() != NOT_DEFINED:
                found = TRUE
              else:
                i += 1
            instanceSource = topoInstances[i]
            logName = '%s_%s' % (instance.getHost(),instance.getName())
            logFile = '%s/%s_%s.xml' % (LOG_XML_TMP_DIR,filePrefix,logName)
            # reopen existing files, no need to add in fileList variable
            # as it has already been added
            cFileFd = open(logFile,'a')
          </script>
          <if expr="instanceSource.getName() == instance.getName()">
            <sequence>
              <!-- Wait ref server to start -->
              <call function="'isAlive'">
                { 'location'         : instanceSource.getHost(),
                  'noOfLoops'        : 50,
                  'noOfMilliSeconds' : 2000,
                  'dsPath'           : instanceSource.getInstallDir(),
                  'dsInstanceHost'   : instanceSource.getHost(),
                  'dsInstancePort'   : instanceSource.getLDAPPort(),
                  'fileFd'           : cFileFd
                }
              </call>
            </sequence>
          <else>
            <sequence>
              <!-- ==  create Replication Provider == -->
              <if expr="instance.getREPLPort() != NOT_DEFINED">
                <sequence>
                  <!-- Wait ref server to start -->
                  <call function="'isAlive'">
                    { 'location'         : instance.getHost(),
                      'noOfLoops'        : 50,
                      'noOfMilliSeconds' : 2000,
                      'dsPath'           : instance.getInstallDir(),
                      'dsInstanceHost'   : instance.getHost(),
                      'dsInstancePort'   : instance.getLDAPPort(),
                      'fileFd'           : cFileFd
                    }
                  </call>
                  <message>
                    ' ** Enable replication between %s and %s' % \
                     (instance.getName(),instanceSource.getName())
                  </message>
                  <call function="'enableReplication'">
                    {
                      'location'          : instance.getHost(),
                      'dsPath'            : instance.getInstallDir(),
                      'dsInstanceHost'    : instance.getHost(),
                      'dsInstancePort'    : instance.getLDAPPort(),
                      'dsInstanceDn'      : DIRECTORY_INSTANCE_DN,
                      'dsInstancePswd'    : DIRECTORY_INSTANCE_PSWD,
                      'dsReplicationPort' : instance.getREPLPort(),
                      'refInstanceHost'   : instanceSource.getHost(),
                      'refInstancePort'   : instanceSource.getLDAPPort(),
                      'refInstanceDn'     : DIRECTORY_INSTANCE_DN,
                      'refInstancePswd'   : DIRECTORY_INSTANCE_PSWD,
                      'refReplicationPort': instanceSource.getREPLPort(),
                      'replicationDnList' : [suffix.getSuffixDn()],
                      'expectedRC'        : [0,5],
                      'fileFd'            : cFileFd
                    }
                  </call>
                </sequence>
              </if>
            </sequence>
          </else>
          </if>
          <script>
            cFileFd.close()
            cFileFd = ''
          </script>
        </sequence>
      </iterate>
      <!--== Initialize replication (totalUpdate) ==-->
      <iterate in="topoInstances" var="instance">
        <sequence>
          <script>
            logName = '%s_%s' % (instance.getHost(),instance.getName())
            logFile = '%s/%s_%s.xml' % (LOG_XML_TMP_DIR,filePrefix,logName)
            # reopen existing files, no need to add in fileList variable
            # as it has already been added
            cFileFd = open(logFile,'a')
          </script>
          <script>
            foundInstance = FALSE
            foundTotalUpdate = FALSE
            # try to get the instance objectclass
            # of the current instance suffix topology
            result = suffix.getElementFromTopology(instance.getName())
            foundInstance = result[0]
            topoElement = result[1]
            # if the current instance is in the suffix topology,
            # then check if need to do a totalupdate
            if foundInstance == TRUE:
              if topoElement.getInitRule().lower() == "totalupdate":
                foundTotalUpdate = TRUE
                sourceInstanceName = topoElement.getInstanceSourceName()
                for tmpInstance in topoInstances:
                  if sourceInstanceName == tmpInstance.getName():
                    sourceInstance = tmpInstance
                    break
          </script>
          <!--== If sourceInstanceName is defined ==-->
          <!--== then we have to run totalupdate  ==-->
          <if expr="foundTotalUpdate == TRUE">
            <sequence>
              <message>
                ' ** Initialize replication between %s and %s (source)' % \
                (instance.getName(),sourceInstance.getName())
              </message>
              <call function="'initializeReplication'">
              {
                'location'           : instance.getHost(),
                'dsPath'             : instance.getInstallDir(),
                'dsInstanceHost'     : instance.getHost(),
                'dsInstancePort'     : instance.getLDAPPort(),
                'sourceInstanceHost' : sourceInstance.getHost(),
                'sourceInstancePort' : sourceInstance.getLDAPPort(),
                'replicationDnList'  : [suffix.getSuffixDn()],
                'fileFd'             : cFileFd
              }
              </call>
            </sequence>
          </if>
          <!-- == Post operations == -->
          <message>
            '%s on %s : configuration done' % \
            (instance.getName(),instance.getHost())
          </message>
          <script>
            cFileFd.write('&lt;/instance&gt;\n')
            cFileFd.close()
            cFileFd = ''
          </script>
        </sequence>
      </iterate>
    </sequence>
  </function>
  <!-- Enable replication between servers using dsreplication -->
  <function name="enableReplication">
    <function-prolog>
      This function enables replication between servers using dsreplication.
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional"
                        default="STAF_REMOTE_HOSTNAME">
        <function-arg-description>
          Location of target host
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="dsPath" type="required">
        <function-arg-description>
          Pathname to installation root
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="dsInstanceHost" type="optional"
                        default="STAF_REMOTE_HOSTNAME">
        <function-arg-description>
          Directory server hostname or IP address
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="dsInstancePort" type="required">
        <function-arg-description>
          Directory server port number
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="dsInstanceDn" type="required">
        <function-arg-description>
          Bind DN
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="dsInstancePswd" type="required">
        <function-arg-description>
          Bind password
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="dsReplicationPort" type="required">
        <function-arg-description>
          Replication port number
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="refInstanceHost" type="optional"
                        default="STAF_REMOTE_HOSTNAME">
        <function-arg-description>
          Reference Directory server hostname or IP address
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="refInstancePort" type="required">
        <function-arg-description>
          Reference Directory server port number
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="refInstanceDn" type="required">
        <function-arg-description>
          Reference server Bind DN
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="refInstancePswd" type="required">
        <function-arg-description>
          Reference server Bind password
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="refReplicationPort" type="required">
        <function-arg-description>
          Reference server Replication port number
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="replicationDnList" type="required">
        <function-arg-description>
          DN of the replicated suffix
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="adminUID" type="optional"
                        default="DIRECTORY_INSTANCE_DN">
        <function-arg-description>
          Global Administrator UID
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="adminPswd" type="optional"
                        default="DIRECTORY_INSTANCE_PSWD">
        <function-arg-description>
          Global Administrator password
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="expectedRC" type="optional" default="[0]">
        <function-arg-description>
        Expected return code value. Default value is 0
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          output file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- Local variables -->
      <script>
        mylocation=location
        STAFCmdParams=''
        STAFCmd=''
        if dsPath:
          dsBinPath='%s/bin' % (dsPath)
          STAFCmd='%s/dsreplication' % (dsBinPath)
        STAFCmdParamsList=[]
        STAFCmdParamsList.append('enable')
        STAFCmdParamsList.append('-n')
        STAFCmdParamsList.append('-Q')
        if dsInstanceHost:
          STAFCmdParamsList.append('-h %s' % dsInstanceHost)
        if dsInstancePort:
          STAFCmdParamsList.append('-p %s' % dsInstancePort)
        if dsInstanceDn:
          STAFCmdParamsList.append('-D "%s"' % dsInstanceDn)
        if dsInstancePswd:
          STAFCmdParamsList.append('--bindPassword1 "%s"' % dsInstancePswd)
        if dsReplicationPort:
          STAFCmdParamsList.append('-r %s' % dsReplicationPort)
        if refInstanceHost:
          STAFCmdParamsList.append('-O %s' % refInstanceHost)
        if refInstancePort:
          STAFCmdParamsList.append('--port2 %s' % refInstancePort)
        if refInstanceDn:
          STAFCmdParamsList.append('--bindDN2 "%s"' % refInstanceDn)
        if refInstancePswd:
          STAFCmdParamsList.append('--bindPassword2 "%s"' % refInstancePswd)
        if refReplicationPort:
          STAFCmdParamsList.append('-R %s' % refReplicationPort)
        if replicationDnList:
          for dn in replicationDnList:
            STAFCmdParamsList.append('-b "%s"' % dn)
        if adminUID:
          STAFCmdParamsList.append('-I "%s"' % adminUID)
        if adminPswd:
          STAFCmdParamsList.append('-w "%s"' % adminPswd)
        STAFCmdParams=' '.join(STAFCmdParamsList)
      </script>
      <!-- Log info for xml report -->
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'enableReplication',
        'fileFd'  : fileFd }
      </call>
      <call function="'writeMessage'">
      { 'fileFd'  : fileFd,
        'content' : 'Enable replication between %s:%s and %s:%s' % \
                    (dsInstanceHost,dsInstancePort,\
                     refInstanceHost,refInstancePort)
      }
      </call>
      <call function="'writeMessage'">
      { 'fileFd'  : fileFd,
        'content' : '%s %s' % (STAFCmd, STAFCmdParams)
      }
      </call>
      <!-- Run the command -->
      <process name="'enable replication'">
        <location>'%s' % location</location>
        <command>'%s' % STAFCmd</command>
        <parms>'%s' % STAFCmdParams</parms>
        <workdir>'%s' % dsBinPath</workdir>
        <envs>
          ['PATH=/bin:/usr/bin:%s' % dsBinPath]
        </envs>
        <console use="'same'"/>
        <stderr mode="'stdout'"/>
        <returnstdout/>
      </process>
      <script>
        STAXCode=RC
        STAXReason=STAXResult
      </script>
      <call function="'checkRC'">
        { 'returncode' : STAXCode ,
          'result'     : STAXReason ,
          'expected'   : expectedRC,
          'fileFd'     : fileFd
        }
      </call>
      <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
      <return>
        STAXReason
      </return>
    </sequence>
  </function>
  <!-- Initialize replicated suffix with the contents -->
  <!-- of a source server using dsreplication -->
  <function name="initializeReplication">
    <function-prolog>
      This function initializes replicated suffixes with the contents
      of a source server using dsreplication.
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional"
                        default="STAF_REMOTE_HOSTNAME">
        <function-arg-description>
          Location of target host
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="dsPath" type="required">
        <function-arg-description>
          Pathname to installation root
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="dsInstanceHost" type="optional"
                        default="STAF_REMOTE_HOSTNAME">
        <function-arg-description>
          Directory server hostname or IP address
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="dsInstancePort" type="required">
        <function-arg-description>
          Directory server port number
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="sourceInstanceHost" type="optional"
                        default="STAF_REMOTE_HOSTNAME">
        <function-arg-description>
          Source Directory server hostname or IP address
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="sourceInstancePort" type="required">
        <function-arg-description>
          Source Directory server port number
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="replicationDnList" type="required">
        <function-arg-description>
          DN of the replicated suffix
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="adminUID"  type="optional"
                        default="DIRECTORY_INSTANCE_DN">
        <function-arg-description>
          Global Administrator UID
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="adminPswd" type="optional"
                        default="DIRECTORY_INSTANCE_PSWD">
        <function-arg-description>
          Global Administrator password
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="expectedRC" type="optional" default="[0]">
        <function-arg-description>
        Expected return code value. Default value is 0
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          output file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- Local variables -->
      <script>
        mylocation=location
        STAFCmdParams=''
        STAFCmd=''
        if dsPath:
          dsBinPath='%s/bin' % dsPath
          STAFCmd='%s/dsreplication' % dsBinPath
        STAFCmdParamsList=[]
        STAFCmdParamsList.append('initialize')
        STAFCmdParamsList.append('-n')
        STAFCmdParamsList.append('-Q')
        if dsInstanceHost:
          STAFCmdParamsList.append('-O %s' % dsInstanceHost)
        if dsInstancePort:
          STAFCmdParamsList.append('--portDestination %s' % dsInstancePort)
        if sourceInstanceHost:
          STAFCmdParamsList.append('-h %s' % sourceInstanceHost)
        if sourceInstancePort:
          STAFCmdParamsList.append('-p %s' % sourceInstancePort)
        if replicationDnList:
          for dn in replicationDnList:
            STAFCmdParamsList.append('-b "%s"' % dn)
        if adminUID:
          STAFCmdParamsList.append('-I "%s"' % adminUID)
        if adminPswd:
          STAFCmdParamsList.append('-w "%s"' % adminPswd)
        STAFCmdParams=' '.join(STAFCmdParamsList)
      </script>
      <!-- Log info for xml report -->
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'initializeReplication',
        'fileFd'  : fileFd }
      </call>
      <call function="'writeMessage'">
      { 'fileFd'  : fileFd,
        'content' : 'Initialize replication between %s:%s and %s:%s (source)'%\
                     (dsInstanceHost,dsInstancePort,\
                      sourceInstanceHost,sourceInstancePort)
      }
      </call>
      <call function="'writeMessage'">
      { 'fileFd'  : fileFd,
        'content' : '%s %s' % (STAFCmd, STAFCmdParams)
      }
      </call>
      <!-- Run the command -->
      <process name="'initialize replication'">
        <location>'%s' % location</location>
        <command>'%s' % STAFCmd</command>
        <parms>'%s' % STAFCmdParams</parms>
        <workdir>'%s' % dsBinPath</workdir>
        <envs>
          ['PATH=/bin:/usr/bin:%s' % dsBinPath]
        </envs>
        <console use="'same'"/>
        <stderr mode="'stdout'"/>
        <returnstdout/>
      </process>
      <script>
        STAXCode=RC
        STAXReason=STAXResult
      </script>
      <call function="'checkRC'">
        { 'returncode' : STAXCode ,
          'result'     : STAXReason ,
          'expected'   : expectedRC,
          'fileFd'     : fileFd
        }
      </call>
      <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
      <return>
        STAXReason
      </return>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/phases/generateLdif/generateLdif.xml
New file
@@ -0,0 +1,299 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <defaultcall function="generateLdif"/>
  <!-- ************************************************************ -->
  <function name="generateLdif">
    <function-map-args>
      <function-arg-def name="suffix" type="required">
        <function-arg-description>
          suffix
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!--==========  Call preambule  =========-->
      <call function="'phasePreamble'">
      { 'phaseName' : 'generateLdif' ,
        'fileFd'    : LOG_MAIN_FD }
      </call>
      <!--==========  Define variables  =========-->
      <script>
        fileList = STAXGlobal([])
      </script>
      <!--== Get the list of instance used in the topology for this suffix -->
      <!--== that use importLDIF                                       ====-->
      <script>
        topoElements = []
        mainTopoElements = suffix.getTopology()
      </script>
      <iterate in="mainTopoElements" var="topoElement">
        <sequence>
          <script>
            initRule = topoElement.getInitRule()
            product  = topoElement.getInstanceRef().getProduct()
            if ( product == 'opends' and initRule == 'importLdif'):
              topoElements.append(topoElement)
          </script>
        </sequence>
      </iterate>
      <if expr="topoElements == []">
        <sequence>
          <message>
            'ERROR : no instance using importLdif, should have one at least'
          </message>
          <call function="'writeMessage'">
          { 'content' : 'ERROR : no instance using importLdif for initRule, \
                         should have one at least' % msg ,
            'fileFd'  : LOG_MAIN_FD }
          </call>
        </sequence>
      <!-- Some instances use importLdif -->
      <else>
        <sequence>
          <!--===========  Generate template  ==========-->
          <script>
            sys.path.append("%s/phases/parser" % TESTS_DIR )
            from parser import *
            localTemplateFile = '%s/template.ldif' % (LOG_DIR)
          </script>
          <call function="'generateTemplate'">
          { 'templateFile' : localTemplateFile }
          </call>
          <!--===========  For the first host, copy and run makeldif  ======-->
          <script>
            str = '\n&lt;instance name=\"%s\"' % topoElements[0].getName()
            str = '%s host=\"%s\"' % (str, \
                                    topoElements[0].getInstanceRef().getHost())
            str = '%s product=\"opends\"&gt;\n' % str
            LOG_MAIN_FD.write(str)
            templateFile = '%s/template.ldif' % \
                            topoElements[0].getInstanceRef().getInstallDir()
            ldifFile = '%s/data.ldif' % \
                        topoElements[0].getInstanceRef().getInstallDir()
          </script>
          <call function="'copyFile'">
          { 'location'   : topoElements[0].getInstanceRef().getHost(),
            'srcFile'    : localTemplateFile,
            'destFile'   : templateFile,
            'remoteHost' : topoElements[0].getInstanceRef().getHost(),
            'fileFd'     : LOG_MAIN_FD
          }
          </call>
          <call function="'makeLdif'">
          { 'location'     : topoElements[0].getInstanceRef().getHost(),
            'dsPath'       : topoElements[0].getInstanceRef().getInstallDir(),
            'templateFile' : templateFile,
            'ldifFile'     : ldifFile,
            'fileFd'       : LOG_MAIN_FD
          }
          </call>
          <call function="'ImportLdifWithScript'">
          {
            'location'     : topoElements[0].getInstanceRef().getHost(),
            'dsPath'       : topoElements[0].getInstanceRef().getInstallDir(),
            'dsLdifFile'   : ldifFile,
            'dsRejectFile' : '%s/importLdif_rejectedfile.txt' % LOG_TMP_DIR,
            'fileFd'       : LOG_MAIN_FD
          }
          </call>
          <message>
            '%s : makeLDIF done' % topoElements[0].getInstanceRef().getHost()
          </message>
          <script>LOG_MAIN_FD.write('&lt;/instance&gt;\n')</script>
          <!--========  For each other hosts, copy and import ldif  ========-->
          <paralleliterate in="topoElements" var="topoElement">
            <sequence>
              <if expr="topoElement.getName() != topoElements[0].getName()">
                <sequence>
                  <script>
                    cHost = topoElement.getInstanceRef().getHost()
                    cName = topoElement.getInstanceRef().getName()
                    cInstallDir = topoElement.getInstanceRef().getInstallDir()
                    cLdifFile = '%s/data.ldif' % (cInstallDir)
                    logName = '%s_%s' % (cHost,cName)
                    logFile = '%s/phase_genldif_%s.xml' % \
                              (LOG_XML_TMP_DIR,logName)
                    fileList.append(logFile)
                    # Write start tag
                    cFileFd = open(logFile,'w')
                    str = '\n&lt;instance name=\"%s\"' % cName
                    str = '%s host=\"%s\"' % (str,cHost)
                    str = '%s product=\"opends\"&gt;\n' % str
                    cFileFd.write(str)
                  </script>
                  <!--== Copy ldif data file on all instances directory ==-->
                  <call function="'copyFile'">
                    { 'location'   : topoElements[0].getHost(),
                      'srcFile'    : ldifFile,
                      'destFile'   : cLdifFile,
                      'remoteHost' : cHost,
                      'fileFd'     : cFileFd
                    }
                  </call>
                  <!--========== Import Ldif =============-->
                  <call function="'ImportLdifWithScript'">
                  {
                    'location'    : cHost ,
                    'dsPath'      : cInstallDir,
                    'dsLdifFile'  : cLdifFile,
                    'fileFd'      : cFileFd
                  }
                  </call>
                  <!--========== Post operations ======-->
                  <message>'%s : makeLDIF done' % cHost</message>
                  <script>
                    cFileFd.write('&lt;/instance&gt;\n')
                    cFileFd.close()
                    cFileFd = ''
                  </script>
                </sequence>
              </if>
            </sequence>
          </paralleliterate>
          <!--==========   Merge files    ==========-->
          <if expr="len(topoElements) > 1">
            <call function="'mergeFiles'">
            {
              'fileList' : fileList,
              'fileFd'   : LOG_MAIN_FD
            }
            </call>
          </if>
        </sequence>
      </else>
      </if>
      <!--==========  Call postphase =========-->
      <call function="'phasePostamble'">
      {
        'phaseName' : 'generateLdif',
        'fileFd'    : LOG_MAIN_FD
      }
      </call>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="generateTemplate">
    <function-map-args>
      <function-arg-def name="templateFile" type="required">
        <function-arg-description>
          suffix
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'generateTemplate',
        'fileFd'  : LOG_MAIN_FD }
      </call>
      <call function="'writeMessage'">
      { 'fileFd'  : LOG_MAIN_FD,
        'content' : 'Create template file : %s' % (templateFile)
      }
      </call>
      <script>
        cTemplateFd = open(templateFile,'w')
        # write needed variables
        cTemplateFd.write('define maildomain=example.com\n')
        tree = getSuffixDataForMakeLDIF(suffix.getSuffixDn(),\
                                        suffix.getNbOfEntries(),\
                                        suffix.getTree())
        cTemplateFd.write('%s' % tree)
        sys.path.append("%s/phases/generateLdif" % TESTS_DIR )
        from person import writePersonTemplate
        writePersonTemplate(cTemplateFd)
        from inetOrgPerson import writeInetOrgPersonTemplate
        writeInetOrgPersonTemplate(cTemplateFd)
        from organizationalPerson import writeOrganizationalPersonTemplate
        writeOrganizationalPersonTemplate(cTemplateFd)
        from inetOrgPersonJpeg1Mb import writeInetOrgPersonJpeg1MbTemplate
        writeInetOrgPersonJpeg1MbTemplate(cTemplateFd)
        # scalablePerson not in opends schema (so comment it) :
        # "invalid because it violates the server's schema configuration"
        # from scalablePerson import writeScalablePersonTemplate
        # writeScalablePersonTemplate(cTemplateFd)
        cTemplateFd.close()
      </script>
      <call function="'isFile'">
        { 'fileName' : templateFile }
      </call>
      <call function="'checkRC'">
        { 'returncode' : RC ,
          'result'     : STAXResult,
          'fileFd'     : LOG_MAIN_FD }
      </call>
      <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/phases/generateLdif/inetOrgPerson.py
New file
@@ -0,0 +1,79 @@
#!/usr/bin/python
# 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
# information:
#      Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#      Copyright 2008 Sun Microsystems, Inc.
def writeInetOrgPersonTemplate(fileFd):
  fileFd.write('\n\n\
template: inetOrgPerson\n\
rdnAttr: cn\n\
objectclass: top\n\
objectclass: person\n\
objectclass: organizationalPerson\n\
objectclass: inetOrgPerson\n\
givenName: <first>\n\
sn: <last>\n\
cn: {givenName} {sn}\n\
initials: {givenName:1}{sn:1}\n\
uid: {givenName}.{sn}\n\
mail: {uid}@[suffix]\n\
userPassword: <random:alphanumeric:8>\n\
telephoneNumber: <random:telephone>\n\
homePhone: <random:telephone>\n\
pager: <random:telephone>\n\
mobile: <random:telephone>\n\
employeeNumber: <sequential>\n\
l: <file:cities>\n\
st: <file:states>\n\
street: <random:numeric:5> <file:streets> Street\n\
postalCode: <random:numeric:5>\n\
postalAddress: {cn}${street}${l}, {st}  {postalCode}\n\
description: This is the description for {cn}.\n\
carLicense: <presence:50><random:alphanumeric:8>\n\
seeAlso: cn=<random:alphanumeric:8>\n\
destinationIndicator: <random:alphanumeric:8>\n\
facsimileTelephoneNumber: <random:telephone>\n\
internationaliSDNNumber: <random:numeric:8>\n\
ou: <random:alphanumeric:8>\n\
physicalDeliveryOfficeName: <random:alphanumeric:8>\n\
postOfficeBox: <random:alphanumeric:8>\n\
preferredDeliveryMethod: mhs $ telephone\n\
registeredAddress: <presence:50>{cn}${street}${l}, {st}  {postalCode}\n\
teletexTerminalIdentifier: <random:alphanumeric:8>\n\
telexNumber: <random:numeric:8> $ <random:numeric:8> $ <random:numeric:8>\n\
title: <random:alphanumeric:8>\n\
x121Address: <random:numeric:8>\n\
businessCategory: <random:alphanumeric:8>\n\
carLicense: <random:alphanumeric:8>\n\
departmentNumber: <random:numeric:2>\n\
displayName: {cn}\n\
employeeType: <random:alphanumeric:8>\n\
homePostalAddress: {postalAddress}\n\
manager: cn=manager,<parentdn>\n\
preferredLanguage: <list:english,french,german,spanish,chinese>\n\
roomNumber: <random:alphanumeric:4>\n\
secretary: cn=secretary,<parentdn>\n\
\n')
opends/tests/system-tests/phases/generateLdif/inetOrgPersonJpeg1Mb.py
New file
@@ -0,0 +1,79 @@
#!/usr/bin/python
# 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
# information:
#      Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#      Copyright 2008 Sun Microsystems, Inc.
def writeInetOrgPersonJpeg1MbTemplate(fileFd):
  fileFd.write('\n\n\
template: inetOrgPerson_Jpeg_1MB\n\
rdnAttr: uid\n\
objectclass: top\n\
objectclass: person\n\
objectclass: organizationalPerson\n\
objectclass: inetOrgPerson\n\
givenName: <first>\n\
sn: <last>\n\
cn: {givenName} {sn}\n\
initials: {givenName:1}{sn:1}\n\
uid: {givenName}.{sn}\n\
mail: {uid}@[suffix]\n\
userPassword: <random:alphanumeric:8>\n\
telephoneNumber: <random:telephone>\n\
homePhone: <random:telephone>\n\
pager: <random:telephone>\n\
mobile: <random:telephone>\n\
employeeNumber: <sequential>\n\
l: <file:cities>\n\
st: <file:states>\n\
street: <random:numeric:5> <file:streets> Street\n\
postalCode: <random:numeric:5>\n\
postalAddress: {cn}${street}${l}, {st}  {postalCode}\n\
description: This is the description for {cn}.\n\
carLicense: <presence:50><random:alphanumeric:8>\n\
seeAlso: cn=<random:alphanumeric:8>\n\
destinationIndicator: <random:alphanumeric:8>\n\
facsimileTelephoneNumber: <random:telephone>\n\
internationaliSDNNumber: <random:numeric:8>\n\
ou: <random:alphanumeric:8>\n\
physicalDeliveryOfficeName: <random:alphanumeric:8>\n\
postOfficeBox: <random:alphanumeric:8>\n\
preferredDeliveryMethod: mhs $ telephone\n\
registeredAddress: <presence:50>{cn}${street}${l}, {st}  {postalCode}\n\
teletexTerminalIdentifier: <random:alphanumeric:8>\n\
telexNumber: <random:numeric:8> $ <random:numeric:8> $ <random:numeric:8>\n\
title: <random:alphanumeric:8>\n\
x121Address: <random:numeric:8>\n\
businessCategory: <random:alphanumeric:8>\n\
carLicense: <random:alphanumeric:8>\n\
departmentNumber: <random:numeric:2>\n\
displayName: {cn}\n\
employeeType: <random:alphanumeric:8>\n\
homePostalAddress: {postalAddress}\n\
manager: cn=manager,<parentdn>\n\
preferredLanguage: <list:english,french,german,spanish,chinese>\n\
roomNumber: <random:alphanumeric:4>\n\
secretary: cn=secretary,<parentdn>\n\
jpegPhoto: <random:base64:1000000>\n\
\n')
opends/tests/system-tests/phases/generateLdif/organizationalPerson.py
New file
@@ -0,0 +1,57 @@
#!/usr/bin/python
# 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
# information:
#      Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#      Copyright 2008 Sun Microsystems, Inc.
def writeOrganizationalPersonTemplate(fileFd):
  fileFd.write('\n\n\
template: organizationalPerson\n\
rdnAttr: cn\n\
objectClass: organizationalPerson\n\
objectClass: person\n\
objectClass: top\n\
sn: <last>\n\
cn: <first> {sn}\n\
userPassword: <random:alphanumeric:8>\n\
description: This is the description for {cn}.\n\
telephoneNumber: <random:telephone>\n\
destinationIndicator: <random:alphanumeric:8>\n\
facsimileTelephoneNumber: <random:telephone>\n\
internationaliSDNNumber: <random:numeric:8>\n\
l: <file:cities>\n\
physicalDeliveryOfficeName: <random:alphanumeric:8>\n\
postOfficeBox: <random:alphanumeric:8>\n\
st: <file:states>\n\
street: <random:numeric:5> <file:streets> Street\n\
postalCode: <random:numeric:5>\n\
postalAddress: {cn}${street}${l}, {st}  {postalCode}\n\
preferredDeliveryMethod: mhs $ telephone\n\
registeredAddress: registeredAddress: <presence:50>{postalAddress}\n\
teletexTerminalIdentifier: <random:alphanumeric:8>\n\
telexNumber: <random:numeric:8> $ <random:numeric:8> $ <random:numeric:8>\n\
title: <list:manager,secretary,engineer>\n\
x121Address: <random:numeric:8>\n\
\n')
opends/tests/system-tests/phases/generateLdif/person.py
New file
@@ -0,0 +1,40 @@
#!/usr/bin/python
# 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
# information:
#      Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#      Copyright 2008 Sun Microsystems, Inc.
def writePersonTemplate(fileFd):
  fileFd.write('\n\n\
template: person\n\
rdnAttr: cn\n\
objectClass: person\n\
objectClass: top\n\
sn: <last>\n\
cn: <first> {sn}\n\
description: This is the description for {cn}.\n\
telephoneNumber: <random:telephone>\n\
userPassword: <random:alphanumeric:8>\n\
\n')
opends/tests/system-tests/phases/generateLdif/scalablePerson.py
New file
@@ -0,0 +1,50 @@
#!/usr/bin/python
# 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
# information:
#      Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#      Copyright 2008 Sun Microsystems, Inc.
def writeScalablePersonTemplate(fileFd):
  fileFd.write('\n\n\
template: scalablePerson\n\
rdnAttr: cn\n\
uid: <sequential>\n\
objectclass: top\n\
objectclass: scalablePerson\n\
sn: <last>\n\
givenName: <first>\n\
cn: {givenName} {sn}\n\
displayName: {cn}\n\
preferredLanguage: <list:english,french,german,spanish,chinese>\n\
telephoneNumber: <random:telephone>\n\
postalAddress: {cn}$<random:numeric:5> <file:streets> Street$<file:cities>, <file:states> <random:numeric:5>\n\
labeledURI: http://www.france.sun.com/{uid}\n\
mobile: <random:telephone>\n\
userPassword: <random:alphanumeric:8>\n\
jpegPhoto:: <random:base64:500>\n\
ntUserDomainId: <list:IPLANET,SUNONE,SUNLABS,SARATOGA>\n\
ntUserFlags: <random:numeric:1>\n\
ntUserUnitsPerWeek:  <random:numeric:1>\n\
\n')
opends/tests/system-tests/phases/installation/installation.xml
New file
@@ -0,0 +1,107 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <defaultcall function="installation"/>
  <!-- ************************************************************ -->
  <function name="installation">
    <function-map-args>
      <function-arg-def name="instances" type="required">
        <function-arg-description>
          list of instances
        </function-arg-description>
        <function-arg-property name="type" value="list of instance class"/>
      </function-arg-def>
      <function-arg-def name="suffix" type="required">
        <function-arg-description>
          suffix class
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!--==========  Call preambule  =========-->
      <call function="'phasePreamble'">
      { 'phaseName' : 'installation' ,
        'fileFd'    : LOG_MAIN_FD }
      </call>
      <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
      file="'%s/phases/installation/installation_opends.xml' % (TESTS_DIR)"/>
      <script>
        prefix = "phase_inst"
        fileList = STAXGlobal([])
      </script>
      <!--==== get the list of hosts to install opends ====-->
      <script>
        opendsInstances = []
        for instance in instances:
          product = instance.getProduct()
          #host = instance.getHost()
          if product == 'opends':
            #if host not in opendsInstances:
            opendsInstances.append(instance)
      </script>
      <!--==== install opends ====-->
      <call function="'installOpends'">
        {
          'instances'  : opendsInstances,
          'filePrefix' : prefix,
          'suffixDn'   : suffix.getSuffixDn()
        }
      </call>
      <!--==========  Merge files    ==========-->
      <call function="'mergeFiles'">
        {
          'fileList' : fileList,
          'fileFd'   : LOG_MAIN_FD
        }
      </call>
      <!--==========  Call postphase =========-->
      <call function="'phasePostamble'">
      {
        'phaseName' : 'installation',
        'fileFd'    : LOG_MAIN_FD
      }
      </call>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/phases/installation/installation_opends.xml
New file
@@ -0,0 +1,435 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <!--==============================================================-->
  <!--=================  INSTALL OPENDS   ==========================-->
  <!--==============================================================-->
  <function name="installOpends">
    <function-map-args>
      <function-arg-def name="instances" type="required">
        <function-arg-description>
          list of instances
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="filePrefix" type="required">
        <function-arg-description>
          prefix for output files
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="suffixDn" type="required">
        <function-arg-description>
          suffix dn
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!--==== install opends in parallel ====-->
      <paralleliterate in="instances" var="instance">
        <sequence>
          <!-- parallel process, all variables defined and values set below -->
          <!-- are local to this sequence -->
          <script>
            cHost = instance.getHost()
            cLDAPPort = instance.getLDAPPort()
            cName = instance.getName()
            cInstallDir = instance.getInstallDir()
            logName = '%s_%s' % (cHost,cName)
            logFile = '%s/%s_%s.xml' % (LOG_XML_TMP_DIR,filePrefix,logName)
            fileList.append(logFile)
            # Write start instance tag
            cFileFd = open(logFile,'w')
            str = '\n&lt;instance name=\"%s\"' % cName
            str = '%s host=\"%s\" product=\"opends\"&gt;\n' % (str, cHost)
            cFileFd.write(str)
          </script>
          <!--== clean previous installation if needed ==-->
          <call function="'cleanPreviousOpendsInstall'">
          {
            'host'               : cHost,
            'instanceInstallDir' : cInstallDir,
            'fileFd'             : cFileFd
          }
          </call>
          <!--== install -->
          <call function="'installSetupOpends'">
          {
            'instance'           : instance,
            'fileFd'             : cFileFd,
            'suffixDn'           : suffixDn
          }
          </call>
          <!--== Post operations ======-->
          <message>'%s : %s : installation complete'% (cHost,cName)</message>
          <script>
            cFileFd.write('&lt;/instance&gt;\n')
            cFileFd.close()
            cFileFd = ''
          </script>
        </sequence>
      </paralleliterate>
      <!--== Update missing parameters -->
      <call function="'updateMissingParameters'">
      {'instances' : instances}
      </call>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="cleanPreviousOpendsInstall">
    <function-map-args>
      <function-arg-def name="host" type="required">
        <function-arg-description>
          host name
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="instanceInstallDir" type="required">
        <function-arg-description>
          installdir path
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor, wildcard : NO_FILE to not write into a file
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <call function="'writeStartTagStep'">
      {'tagName' : 'cleanPreviousOpendsInstall',
       'fileFd'  : fileFd }
      </call>
      <!--== Check if installDir exist ==-->
      <call function="'isFile'">
      {
        'location' : host,
        'fileName' : instanceInstallDir
      }
      </call>
      <script>
        installDirExist = STAXResult
      </script>
      <!--== if installDir exists, stop instance and remove directories ==-->
      <if expr="installDirExist == TRUE">
        <sequence>
          <call function="'writeMessage'">
          {
            'content' : 'installdir %s EXISTs on %s, clean it' % \
                        (instanceInstallDir,host),
            'fileFd'  : fileFd
          }
          </call>
          <call function="'StopDsWithScript'">
          {
            'location'  : host ,
            'dsPath'    : instanceInstallDir,
            'fileFd'    : fileFd
          }
          </call>
          <call function="'deleteFolder'">
          {
            'location'   : host,
            'foldername' : instanceInstallDir,
            'fileFd'     : fileFd
          }
          </call>
        </sequence>
      </if>
      <!-- Try to remove process if needed -->
      <!-- TBD -->
<!--
      <call function="'removeProcessIfNeeded'">
      {
        'location'   : host,
        'fileFd'     : fileFd
      }
      </call>
-->
      <call function="'writeEndTagStep'">{'fileFd' : fileFd}</call>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="installSetupOpends">
    <function-map-args>
      <function-arg-def name="instance" type="required">
        <function-arg-description>
          instance class
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="suffixDn" type="required">
        <function-arg-description>
          suffix dn
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <call function="'writeStartTagStep'">
      { 'tagName' : 'installSetupOpends',
        'fileFd'  : fileFd }
      </call>
      <!--== Create directory and unzip the product ==-->
      <call function="'createFolder'">
      {
        'location'   : instance.getHost(),
        'foldername' : instance.getInstallDir(),
        'fileFd'     : fileFd
      }
      </call>
      <!--== Copy opends archive to host ==-->
      <!-- TBD do
        1- copy evenif cHost = localhost
        2- do not do multiple cp if several instances on same host-->
      <call function="'copyFile'">
      {
        'srcFile'    : instance.getTarball(),
        'destFile'   : '%s/%s_opends.zip' % (LOG_DIR,instance.getName()),
        'remoteHost' : instance.getHost(),
        'fileFd'     : fileFd
      }
      </call>
      <!--== Unzip product ==-->
      <call function="'unZipFile'">
      {
        'location' : instance.getHost(),
        'zipfile'  : '%s/%s_opends.zip' % (LOG_DIR,instance.getName()),
        'unzipdir' : '%s/..' % instance.getInstallDir(),
        'fileFd'   : fileFd
      }
      </call>
      <!--== Setup product ==-->
      <call function="'SetUpDsWithScript'">
        {
          'location'      : instance.getHost(),
          'dsPath'        : instance.getInstallDir(),
          'dsPort'        : instance.getLDAPPort(),
          'dsJmxPort'     : instance.getJMXPort(),
          'dsBindDN'      : DIRECTORY_INSTANCE_DN,
          'dsBindPwd'     : DIRECTORY_INSTANCE_PSWD,
          'dsBaseDN'      : suffixDn,
          'dsDoNotStart'  : 'TRUE',
          'fileFd'        : fileFd
        }
      </call>
      <call function="'writeEndTagStep'">{ 'fileFd' : fileFd}</call>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="removeProcessIfNeeded">
    <function-map-args>
      <function-arg-def name="location" type="required">
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <script>
        pid = ''
      </script>
      <!--== Get uid running the test ==-->
      <!-- TBD replace sed by jython dictionary -->
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'getUid',
        'fileFd'  : fileFd }
      </call>
      <call function="'writeMessage'">
      {'content' : 'Get uid running the test',
       'fileFd'  : fileFd}
      </call>
      <process name="'Get uid running the test'">
        <location>location</location>
        <command mode="'shell'">
          "id\|sed 's/uid=.*(\(.*\)) gid=.*/\1/'"
        </command>
        <parms/>
        <workdir>'/'</workdir>
        <envs>['PATH=/bin:/usr/bin']</envs>
        <stderr mode="'stdout'"/>
        <stdout/>
        <returnstdout/>
      </process>
      <script>
        user = STAXResult
      </script>
      <call function="'checkRC'">
        { 'returncode' : RC,
          'result'     : user,
          'fileFd'     : fileFd }
      </call>
      <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
      <message>'TRACE : user = %s' % user </message>
      <script>
        import commands
        a = commands.getoutput('ps')
      </script>
      <message>'TRACE : ps = %s' % a </message>
      <!--== Search running opends process on the machine ==-->
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'psOpends',
        'fileFd'  : fileFd }
      </call>
      <call function="'writeMessage'">
      {'content' : 'Search running opends process on %s owned by %s' % \
                    (location,user),
       'fileFd'  : fileFd}
      </call>
      <process name="'Search running opends process'">
        <location>location</location>
        <command mode="'shell'">
          "ps -edf | grep opends | grep start-ds | grep -v grep | grep %s| awk -F' ' '{print $2}'" % user
        </command>
        <parms/>
        <workdir>'/'</workdir>
        <envs>['PATH=/bin:/usr/bin']</envs>
        <stderr mode="'stdout'"/>
        <stdout/>
        <returnstdout/>
      </process>
      <script>
        pid = STAXResult[0][1]
      </script>
      <call function="'checkRC'">
        { 'returncode' : RC,
          'result'     : pid,
          'fileFd'     : fileFd }
      </call>
      <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
      <!--== Try to kill them if found ==-->
      <message>'TRACE : pid = %s' % pid </message>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="updateMissingParameters">
    <function-map-args>
      <function-arg-def name="instances" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!--========  Update missing parameters   ======-->
      <iterate in="instances" var="instance">
        <sequence>
          <!--== Get instance informations ==-->
          <process name="'%s: Get server infos' % instance.getName()">
            <location>instance.getHost()</location>
            <command mode="'shell'">
              "%s/bin/start-ds -s" % instance.getInstallDir()
            </command>
            <envs>['PATH=/bin:/usr/bin:']</envs>
            <stderr mode="'stdout'"/>
            <stdout/>
            <returnstdout/>
          </process>
          <!--== Parse and store the outputs returned by the CLI  ==-->
          <script>
            instanceInfos = STAXResult[0][1].split('\n')
            version = instanceInfos[0].replace("OpenDS Directory Server ","")
            dict = {}
            for line in instanceInfos:
              key = line[0:line.find(':')].strip()
              value= line[line.find(':')+1:len(line)].strip()
              dict[key]=value
            build = dict['Build ID']
            os = dict['Operating System']
            os = os.replace("generic ","")
            jvmVersion   = dict['JVM Version']
            jvmVendor    = dict['JVM Vendor']
            if jvmVendor == 'Sun Microsystems Inc.':
              jvmVendor  = 'sun'
            jvmArch      = dict['JVM Architecture'].replace("-bit","")
            jvm = '%s-%s-server-%s' % (jvmVersion,jvmVendor,jvmArch)
            # Store infos in instance object
            instance.setJavaVersion(jvm)
            instance.setBuildId(build)
            instance.setOs(os)
          </script>
        </sequence>
      </iterate>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/phases/log/log.py
New file
@@ -0,0 +1,48 @@
#!/usr/bin/python
# 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
# information:
#      Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#      Copyright 2008 Sun Microsystems, Inc.
def htmlTransformation(myString):
  if (myString != '' ):
    myString = '%s' % myString
    # convert myString to a string is it is a list
    #if ( myString.__class__.toString().count('PyList') == 1 ):
    #  tmpList = []
    #  for element in myString:
    #    tmpList.append('%s' % element)
    #  myString = ",".join(tmpList)
    myString = myString.replace('&','&amp;')
    myString = myString.replace('"','&quot;')
    myString = myString.replace('<','&lt;')
    myString = myString.replace('>','&gt;')
  return myString
opends/tests/system-tests/phases/log/log.xml
New file
@@ -0,0 +1,634 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <defaultcall function="main_log"/>
  <!-- ************************************************************ -->
  <function name="main_log">
    <sequence>
      <message log="1">'main_log() do nothing'</message>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="createLogDir">
   <function-prolog>
      'Create log directories for system test, using LOG_DIR variable'
    </function-prolog>
    <sequence>
      <script>
        logsClientDir = '%s/client' % LOG_DIR
        logsConfDir = '%s/configuration' % LOG_DIR
      </script>
      <message log="1">
        'Logs output set to %s' % LOG_DIR
      </message>
      <!-- Create folders -->
      <call function="'createFolder'">
        { 'location'   : STAF_LOCAL_HOSTNAME,
          'foldername' : '%s' % LOG_DIR ,
          'fileFd'     : NO_FILE
        }
      </call>
      <call function="'createFolder'">
        { 'location'   : STAF_LOCAL_HOSTNAME,
          'foldername' : '%s' % LOG_TMP_DIR ,
          'fileFd'     : NO_FILE
        }
      </call>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="getLogFileName">
    <function-prolog>
      'return a log file name'
    </function-prolog>
    <function-map-args>
      <function-arg-def name="type" type="required">
      </function-arg-def>
      <function-arg-def name="object" type="required">
      </function-arg-def>
      <function-arg-def name="prefix" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <if expr="type == 'client'">
        <script>
          logFile = '%s/%s_%s_%s_%s.xml' % \
                    ( LOG_XML_TMP_DIR,\
                      prefix,\
                      object.getName(),\
                      object.getHost(),\
                      object.getId() )
        </script>
      <elseif expr="type == 'host'">
        <script>
          logFile = '%s/%s_%s.xml' % (LOG_XML_TMP_DIR,prefix,object)
        </script>
      </elseif>
      </if>
      <return>
        logFile
      </return>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="writeSummary">
    <function-prolog>
      ''
    </function-prolog>
    <function-map-args>
      <function-arg-def name="scenario" type="required">
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <script>
        fileFd.write('&lt;summary&gt;\n')
        # write scenario informations into summary part
        str = '&lt;scenario name=\"%s\"' % scenario.getName()
        str = '%s duration=\"%s%s\" &gt;\n' % \
              (str,scenario.getDurationTime(),scenario.getDurationUnit())
        str = '%s %s \n&lt;/scenario&gt;' % \
              (str,scenario.getDescription())
        fileFd.write(str)
        if ERR_NUM_PARSER != '':
          str = '&lt;phaseSummmary name=\"parser\" result=\"%s\"/&gt;\n' % \
                ERR_NUM_PARSER
          fileFd.write(str)
        if ERR_NUM_INSTALL != '':
          str = '&lt;phaseSummmary name=\"installation\" result=\"%s\"/&gt;\n'%\
                ERR_NUM_INSTALL
          fileFd.write(str)
        if ERR_NUM_GEN_LDIF != '':
          str = '&lt;phaseSummmary name=\"generateLdif\" result=\"%s\"/&gt;\n'%\
                ERR_NUM_GEN_LDIF
          fileFd.write(str)
        if ERR_NUM_CONFIGURATION != '':
          str = '&lt;phaseSummmary name=\"configuration\" result=\"%s\"/&gt;\n'%\
                ERR_NUM_CONFIGURATION
          fileFd.write(str)
        if ERR_NUM_SCHEDULER != '':
          str = '&lt;phaseSummmary name=\"scheduler\" result=\"%s\"/&gt;\n' % \
                ERR_NUM_SCHEDULER
          fileFd.write(str)
        if ERR_NUM_VERDICT != '':
          str = '&lt;phaseSummmary name=\"verdict\" result=\"%s\"/&gt;\n' % \
                ERR_NUM_VERDICT
          fileFd.write(str)
        fileFd.write('&lt;/summary&gt;\n')
      </script>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="mergeClientsFiles">
   <function-prolog>
      ''
    </function-prolog>
    <function-map-args>
      <function-arg-def name="scheduler" type="required">
        <function-arg-description>
          scheduler object
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <iterate in="scheduler" var="module">
        <sequence>
          <!--== If module is disabled, just write it in xml result ==-->
          <if expr="module.getEnabled() == 'false'">
            <script>
              fileFd.write('\n&lt;module name=\"%s\" enabled=\"false\"/&gt;\n'\
                            % module.getName() )
            </script>
          <!--== Module is enabled and have clients log files ==-->
          <else>
            <sequence>
              <!--== Write module tag ==-->
              <script>
                fileFd.write('\n&lt;module name=\"%s\" enabled=\"true\"&gt;\n'\
                              % module.getName() )
              </script>
              <!--== Concat each module's clients log files ==-->
              <script>
                cFileList = []
              </script>
              <iterate in="module.getClients()" var="client">
                <sequence>
                  <call function="'getLogFileName'">
                    {
                      'type'   : 'client',
                      'object' : client,
                      'prefix' : 'client'
                    }
                  </call>
                  <script>
                    cFileList.append(STAXResult)
                  </script>
                </sequence>
              </iterate>
              <!--== Merge files ==-->
              <call function="'mergeFiles'">
                {
                  'fileList' : cFileList,
                  'fileFd'   : fileFd
                }
                </call>
              <!--== Write end module tag ==-->
              <script>
                fileFd.write('\n&lt;/module&gt;\n')
              </script>
            </sequence>
          </else>
          </if>
        </sequence>
      </iterate>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="mergeFiles">
   <function-prolog>
      ''
    </function-prolog>
    <function-map-args>
      <function-arg-def name="fileList" type="required">
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <script>
        msg = ''
      </script>
      <if expr="len(fileList) != 0">
        <iterate in="fileList" var="cFile">
          <sequence>
            <script>
              try:
                cFd = open(cFile,'r')
                try:
                  fileFd.write(cFd.read())
                except IOError:
                  msg = '%s\n ERROR concat file % in main file' % (msg,cFile)
                try:
                  cFd.close()
                except IOError:
                  msg = '%s\n ERROR cant close file %' % (msg,cFile)
              except IOError:
                msg = '%s\n ERROR cant open file %' % (msg,cFile)
            </script>
            <if expr="msg != ''">
              <sequence>
                <message>
                  'ERROR when merging files : %s' % msg
                </message>
                <call function="'writeMessage'">
                { 'content' : 'ERROR when merging files : %s' % msg,
                  'fileFd'  : fileFd }
                </call>
              </sequence>
              <!-- no error during merge, remove original file -->
<!--            <else>
              <script>
                import os
                os.remove(cFile)
              </script>
            </else> -->
            </if>
          </sequence>
        </iterate>
      <else>
        <message>'WARNING : no file to merge'</message>
      </else>
      </if>
      <return> msg </return>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="writeTag">
   <function-prolog>
      ''
    </function-prolog>
    <function-map-args>
      <function-arg-def name="tagName" type="required">
        <function-arg-description>
          name of the tag
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="tagAttr" type="required">
        <function-arg-description>
          attribute/value of the tag [[attr1,val1],[attr2,val2],...]
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="content" type="optional" default="''">
        <function-arg-description>
          content of the tag
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor
        </function-arg-description>
      </function-arg-def>
     </function-map-args>
    <sequence>
      <script>
       myString = ''
       for attr in tagAttr:
         myString = '%s %s=\"%s\"' % (myString,attr[0],attr[1])
      </script>
      <if expr="fileFd == NO_FILE">
        <message>'%s %s : %s' % (tagName,myString,content)</message>
      <else>
       <script>
         fileFd.write('&lt;%s %s&gt; %s &lt;/%s&gt;\n' % \
                     (tagName,myString,content,tagName))
       </script>
      </else>
      </if>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="writeMessage">
    <function-prolog>
      write content in file
    </function-prolog>
    <function-map-args>
      <function-arg-def name="content" type="required">
        <function-arg-description>
          string to write in a file
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <if expr="fileFd != NO_FILE">
        <script>
          sys.path.append("%s/phases/log" % TESTS_DIR )
          from log import htmlTransformation
          content = htmlTransformation(content)
          fileFd.write('&lt;message&gt;%s&lt;/message&gt;\n' % content)
        </script>
      <else>
        <message>content</message>
      </else>
      </if>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="writeOperationResult">
   <function-prolog>
      ''
    </function-prolog>
    <function-map-args>
      <function-arg-def name="returncode" type="required">
      </function-arg-def>
      <function-arg-def name="expected" type="required">
      </function-arg-def>
      <function-arg-def name="result" type="required">
      </function-arg-def>
      <function-arg-def name="status" type="required">
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <if expr="fileFd == NO_FILE">
        <message>
          '%s return code %s (expected %s) : %s' % \
          (status,returncode,expected,result)
        </message>
      <else>
      <sequence>
        <script>
          sys.path.append("%s/phases/log" % TESTS_DIR )
          from log import htmlTransformation
          result = htmlTransformation(result)
          str = '&lt;operationResult returncode=\"%s\"' % returncode
          str = '%s expected=\"%s\" status=\"%s\"'  % (str,expected,status)
          str = '%s&gt; %s &lt;/operationResult&gt;\n'  % (str,result)
          fileFd.write(str)
        </script>
      </sequence>
      </else>
      </if>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="writeStartTagStep">
   <function-prolog>
      ''
    </function-prolog>
    <function-map-args>
      <function-arg-def name="tagName">
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <if expr="fileFd != NO_FILE">
        <script>
          fileFd.write('&lt;step name=\"%s\"&gt;\n' % tagName)
        </script>
      </if>
    </sequence>
  </function>
  <function name="writeEndTagStep">
   <function-prolog>
      ''
    </function-prolog>
    <function-map-args>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <if expr="fileFd != NO_FILE">
        <script>
          fileFd.write('&lt;/step&gt;\n\n')
        </script>
      </if>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="writeStartTagOperation">
   <function-prolog>
      ''
    </function-prolog>
    <function-map-args>
      <function-arg-def name="tagName">
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <if expr="fileFd != NO_FILE">
        <script>
          fileFd.write('&lt;operation name=\"%s\"&gt;\n' % tagName)
        </script>
      </if>
    </sequence>
  </function>
  <function name="writeEndTagOperation">
   <function-prolog>
      ''
    </function-prolog>
    <function-map-args>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <if expr="fileFd != NO_FILE">
        <script>
          fileFd.write('&lt;/operation&gt;\n\n')
        </script>
      </if>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="writeStartTagPhase">
   <function-prolog>
      ''
    </function-prolog>
    <function-map-args>
      <function-arg-def name="tagName" type="required">
      </function-arg-def>
      <function-arg-def name="tagAttr" type="optional" default='[]'>
        <function-arg-description>
          attribute/value of the tag [[attr1,val1],[attr2,val2],...]
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <if expr="fileFd != NO_FILE">
        <sequence>
          <script>
            fileFd.write('&lt;phase name=\"%s\"' % tagName)
          </script>
          <if expr="tagAttr != []">
            <sequence>
              <script>
                str = ''
                for attr in tagAttr:
                  str = '%s %s=\"%s\"' % (str,attr[0],attr[1])
                fileFd.write(str)
              </script>
            </sequence>
          </if>
          <script>
            fileFd.write('&gt;\n')
          </script>
        </sequence>
      </if>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="writeEndTagPhase">
   <function-prolog>
      ''
    </function-prolog>
    <function-map-args>
      <function-arg-def name="fileFd" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <if expr="fileFd != NO_FILE">
        <script>
          fileFd.write('&lt;/phase&gt;\n\n')
        </script>
      </if>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="writeStartTag">
   <function-prolog>
      ''
    </function-prolog>
    <function-map-args>
      <function-arg-def name="nodeName" type="required">
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <if expr="fileFd != NO_FILE">
        <script>
          fileFd.write('&lt;%s&gt;\n' % nodeName)
        </script>
      </if>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="writeEndTag">
   <function-prolog>
      ''
    </function-prolog>
    <function-map-args>
      <function-arg-def name="nodeName" type="required">
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <if expr="fileFd != NO_FILE">
        <script>
          fileFd.write('&lt;/%s&gt;\n' % nodeName)
        </script>
      </if>
    </sequence>
  </function>
  </stax>
opends/tests/system-tests/phases/log/topology.xml
New file
@@ -0,0 +1,296 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <!-- ************************************************************ -->
  <function name="writeTopology" scope="local">
    <function-map-args>
      <function-arg-def name="instances" type="required">
        <function-arg-description>
          instance object
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="suffix" type="required">
        <function-arg-description>
          suffix object
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="scheduler" type="required">
        <function-arg-description>
          scheduler object
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!--==========  Write node  =========-->
      <script>
        fileFd.write('&lt;topology&gt;\n')
      </script>
      <!-- Write instances informations -->
      <call function="'writeInstances'">
      {
        'instanceList' : instances,
        'fileFd'       : LOG_MAIN_FD
      }
      </call>
      <!-- Write SUFFIX informations -->
      <call function="'writeSuffix'">
      {
        'suffix' : suffix,
        'fileFd' : LOG_MAIN_FD
      }
      </call>
      <!-- Write SCHEDULER informations -->
      <call function="'writeScheduler'">
      {
        'scheduler' : scheduler,
        'fileFd'    : LOG_MAIN_FD
      }
      </call>
      <!--==========  close node =========-->
      <script>
        fileFd.write('&lt;/topology&gt;\n')
      </script>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="writeInstances" scope="local">
  <function-map-args>
      <function-arg-def name="instanceList" type="required">
        <function-arg-description>
          List of instances class to write in xml report file
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor of the output file
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <call function="'writeStartTag'">
      {
        'nodeName' : 'instances',
        'fileFd'   : fileFd
      }
      </call>
      <iterate var="a" in="instanceList">
        <sequence>
          <script>
            str = '\n &lt;id&gt;%s&lt;/id&gt;\n'     % a.getId()
            str = '%s &lt;host&gt;%s&lt;/host&gt;\n' % (str,a.getHost())
            str = '%s &lt;installDir&gt;%s&lt;/installDir&gt;\n' % \
                  (str,a.getInstallDir())
            str = '%s &lt;port&gt;\n'                  % str
            str = '%s &lt;ldap&gt;%s&lt;/ldap&gt;\n'   % (str,a.getLDAPPort())
            str = '%s &lt;ldaps&gt;%s&lt;/ldaps&gt;\n' % (str,a.getLDAPSPort())
            str = '%s &lt;jmx&gt;%s&lt;/jmx&gt;\n'     % (str,a.getJMXPort())
            str = '%s &lt;replicationServer&gt;%s&lt;/replicationServer&gt;\n'%\
                  (str,a.getREPLPort())
            str = '%s &lt;/port&gt;\n' % str
            str = '%s &lt;buildId&gt;%s&lt;/buildId&gt;\n' % \
                  (str,a.getBuildId())
            str = '%s &lt;jvm&gt;%s&lt;/jvm&gt;\n' % \
                  (str,a.getJavaVersion())
            str = '%s &lt;os&gt;%s&lt;/os&gt;\n' % \
                  (str,a.getOs())
            str = '%s &lt;synchroDate&gt;%s&lt;/synchroDate&gt;\n' % \
                  (str,a.getSynchroDate())
          </script>
          <call function="'writeTag'">
          {
            'tagName' : 'instance',
            'tagAttr' : [['name',a.getName()],['product',a.getProduct()]] ,
            'fileFd'  : fileFd ,
            'content' : str
          }
          </call>
        </sequence>
      </iterate>
      <call function="'writeEndTag'">
      {
        'nodeName' : 'instances',
        'fileFd'   : fileFd
      }
      </call>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="writeScheduler" scope="local">
  <function-map-args>
      <function-arg-def name="scheduler" type="required">
        <function-arg-description>
          scheduler object
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor of the output file
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <call function="'writeStartTag'">
      {
        'nodeName' : 'schedulerParser',
        'fileFd'   : fileFd
      }
      </call>
      <if expr="scheduler == []">
        <message log="1">'topology.xml : ERROR NO SCHEDULER DEFINED'</message>
      <else>
        <iterate var="module" in="scheduler">
          <sequence>
            <script>
              msgClients = ''
              clients = module.getClients()
              for client in clients:
                str1 = 'id=\"%s\"' % client.getId()
                str1 = '%s name=\"%s\"' % (str1,client.getName())
                str1 = '%s host=\"%s\"' % (str1,client.getHost())
                str1 = '%s start=\"%s\"' % (str1,client.getStart())
                str1 = '%s stop=\"%s\"' % (str1,client.getStop())
                str1 = '%s dependency=\"%s\"' % (str1,client.getDependency())
                msgClients = '%s&lt;client %s &gt; %s &lt;/client&gt;\n' % \
                             (msgClients,str1,client.getParams())
            </script>
            <call function="'writeTag'">
            {
              'tagName' : 'module',
              'tagAttr' : [['name',module.getName()],['enabled',module.getEnabled()]],
              'fileFd'  : fileFd ,
              'content' : msgClients
            }
            </call>
          </sequence>
        </iterate>
      </else>
      </if>
      <call function="'writeEndTag'">
      {
        'nodeName' : 'schedulerParser',
        'fileFd'   : fileFd
      }
      </call>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="writeSuffix" scope="local">
  <function-map-args>
      <function-arg-def name="suffix" type="required">
        <function-arg-description>
          suffix object
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor of the output file
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- Write Suffix informations -->
      <script>
        # SUFFIX TOPOLOGY
        topoMsg = ''
        topology = suffix.getTopology()
        if topology == '':
          topology = 'ERROR:cant find topology'
        topoMsg = '%s\n&lt;topology&gt;' % topoMsg
        for topoInstance in topology:
          instance = topoInstance.getInstanceRef()
          topoMsg = '%s\n &lt;instance name=\"%s\"' % \
                    (topoMsg,instance.getName())
          topoMsg = '%s initRule=\"%s\"&gt;&lt;/instance&gt;' % \
                    (topoMsg,topoInstance.getInitRule())
        topoMsg = '%s\n&lt;/topology&gt;\n' % topoMsg
        # SUFFIX DATA
        suffixDataForXml = NOT_DEFINED
        root = suffix.getTree()
        suffixDataForXml = getSuffixDataForXML(suffix.getSuffixDn(),root)
      </script>
      <call function="'writeStartTag'">
      {
        'nodeName' : 'suffixes',
        'fileFd'   : fileFd
      }
      </call>
      <call function="'writeTag'">
      {
        'tagName' : 'suffix',
        'tagAttr' : [['name',suffix.getSuffixDn()]] ,
        'fileFd'  : LOG_MAIN_FD ,
        'content' : '\n %s \
&lt;numberOfEntries&gt;%s&lt;/numberOfEntries&gt;\n \
%s \n \
' % (topoMsg,suffix.getNbOfEntries(),suffixDataForXml)
      }
      </call>
      <call function="'writeEndTag'">
      {
        'nodeName' : 'suffixes',
        'fileFd'   : fileFd
      }
      </call>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/phases/main_run.xml
New file
@@ -0,0 +1,301 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <defaultcall function="main_run"/>
  <function name="main_run">
    <function-map-args>
      <function-arg-def name="configurationFile" type="required">
        <function-arg-description>
          configuration file path
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="runInstallation" type="optional"
                                               default="'true'">
        <function-arg-description>
          run installation phase
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="runGenerateLdif" type="optional"
                                               default="'true'">
        <function-arg-description>
          run generateLdif phase
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="runConfiguration" type="optional"
                                                default="'true'">
        <function-arg-description>
          run configuration phase
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="runScheduler" type="optional" default="'true'">
        <function-arg-description>
          run scheduler phase
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
       <!-- ============ GLOBAL VARIABLES ============================ -->
       <!-- Warning : some of global variables are also defined in     -->
       <!-- parser.py file, be sure to update both files               -->
      <script>
        STAXLogMessage  = 1
        TRUE            = 0
        FALSE           = 1
        NO_FILE         = 'do_not_write_in_file'
        NOT_DEFINED     = 'ERROR_not_defined'
        MultimasterSync = 'Multimaster Synchronization'
        MultimasterType = 'multimaster'
        DSCONFIG        = 'dsconfig'
        DIRECTORY_INSTANCE_BE = 'userRoot'
        DOMAIN          = STAXGlobal([0])
        DOMAIN[0]       = ''
        ERR_NUM = STAXGlobal([0])
        ERR_NUM_PARSER        = ''
        ERR_NUM_INSTALL       = ''
        ERR_NUM_GEN_LDIF      = ''
        ERR_NUM_CONFIGURATION = ''
        ERR_NUM_SCHEDULER     = ''
        ERR_NUM_VERDICT       = ''
        ERR_NUM_TOTAL         = 0
      </script>
      <!-- ============ LOAD LIB ===================================== -->
      <!-- Load in any standard python libraries -->
      <script>
        import re
        import posixpath
        import sys
        from time import localtime,strftime
      </script>
      <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
        file="'%s/phases/main_run_lib.xml' % (TESTS_DIR)"/>
      <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
        file="'%s/phases/shared/utils.xml' % (TESTS_DIR)"/>
      <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
        file="'%s/phases/shared/stafcmd.xml' % (TESTS_DIR)"/>
      <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
        file="'%s/phases/shared/dsadm.xml' % (TESTS_DIR)"/>
      <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
        file="'%s/phases/shared/ldap.xml' % (TESTS_DIR)"/>
      <!-- TDB : should not have dependency with functional test suite -->
      <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
        file="'%s/../functional-run/staf/services/stax/libraries/STAXUtil.xml'
               % (TESTS_DIR)"/>
      <!-- ============ CREATE LOG STUFF ============================= -->
      <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
        file="'%s/phases/log/log.xml' % (TESTS_DIR)"/>
      <script>
        logsDate        = strftime("%Y%m%d-%H%M%S",localtime())
        LOG_DIR         = '%s/%s' % (TMPDIR,logsDate)
        LOG_TMP_DIR     = '%s/tmp' % LOG_DIR
        LOG_XML_TMP_DIR = '%s/xmltmp' % LOG_DIR
      </script>
      <call function="'createLogDir'"/>
      <!-- Write xml result header -->
      <script>
        LOG_FILE    = '%s/result.xml' % (LOG_DIR)
        LOG_MAIN_FD = open(LOG_FILE,'w')
        str = '&lt;?xml version=\"1.0\" encoding=\"UTF-8\"'
        str = '%s standalone=\"no\"?&gt;\n' % str
        str = '%s &lt;?xml-stylesheet type="text/xsl" href="result.xsl"?>\n' \
               % str
        str = '%s &lt;systemTestRoot&gt;\n' % str
        LOG_MAIN_FD.write(str)
      </script>
      <!-- ============ PARSER ======================================= -->
      <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
        file="'%s/phases/parser/parser.xml' % (TESTS_DIR)"/>
      <call function="'parser'">configurationFile</call>
      <script>
        result    = STAXResult
        msg       = result[0]
        instances = result[1]
        suffix    = result[2]
        scheduler = result[3]
        scenario  = result[4]
        ERR_NUM_PARSER = ERR_NUM[0]
        ERR_NUM_TOTAL  = ERR_NUM_TOTAL + ERR_NUM[0]
      </script>
      <if expr="ERR_NUM_PARSER != 0">
        <return/>
      </if>
      <!-- ============ PREAMBLE ===================================== -->
      <call function="'mainPreamble'">
        {
          'instances' : instances,
          'scheduler' : scheduler
        }
      </call>
      <!-- ============ INSTALLATION ================================= -->
      <if expr="runInstallation == 'true'">
        <sequence>
          <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
            file="'%s/phases/installation/installation.xml' % (TESTS_DIR)"/>
          <call function="'installation'">
            {
              'instances' : instances,
              'suffix'    : suffix
            }
          </call>
          <script>
            ERR_NUM_INSTALL = ERR_NUM[0]
            ERR_NUM_TOTAL   = ERR_NUM_TOTAL + ERR_NUM[0]
          </script>
        </sequence>
      </if>
      <!-- ============ GENERATE LDIF & IMPORT LDIF  ================== -->
      <if expr="runGenerateLdif == 'true'">
        <sequence>
          <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
            file="'%s/phases/generateLdif/generateLdif.xml' % (TESTS_DIR)"/>
          <call function="'generateLdif'">
            { 'suffix'       : suffix }
          </call>
          <script>
            ERR_NUM_GEN_LDIF = ERR_NUM[0]
            ERR_NUM_TOTAL    = ERR_NUM_TOTAL + ERR_NUM[0]
          </script>
        </sequence>
      </if>
      <!-- ============ PRE-CONFIGURATION ============================ -->
      <!-- ============ CONFIGURATION  =============================== -->
      <if expr="runConfiguration == 'true'">
        <sequence>
          <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
            file="'%s/phases/configuration/configuration.xml' % (TESTS_DIR)"/>
          <call function="'configuration'">
            {
              'instances' : instances ,
              'suffix'    : suffix
            }
          </call>
          <script>
            ERR_NUM_CONFIGURATION = ERR_NUM[0]
            ERR_NUM_TOTAL         = ERR_NUM_TOTAL + ERR_NUM[0]
          </script>
        </sequence>
      </if>
      <!-- ============ POST-CONFIGURATION =========================== -->
      <!-- ============ MONITORING =================================== -->
      <!-- ============ scheduler ==================================== -->
      <if expr="runScheduler == 'true'">
        <sequence>
          <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
            file="'%s/phases/scheduler/scheduler.xml' % (TESTS_DIR)"/>
          <call function="'scheduler'">
            {
              'instances' : instances,
              'suffix'    : suffix,
              'scheduler' : scheduler,
              'scenario'  : scenario
            }
          </call>
          <script>
            ERR_NUM_SCHEDULER = ERR_NUM[0]
            ERR_NUM_TOTAL     = ERR_NUM_TOTAL + ERR_NUM[0]
          </script>
        </sequence>
      </if>
      <!-- ============ TOPOLOGY ===================================== -->
      <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
        file="'%s/phases/log/topology.xml' % (TESTS_DIR)"/>
      <call function="'writeTopology'">
      {
        'instances' : instances,
        'suffix'    : suffix,
        'scheduler' : scheduler
      }
      </call>
      <!-- ============ VERDICT ====================================== -->
      <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
        file="'%s/phases/verdict/verdict.xml' % (TESTS_DIR)"/>
      <call function="'verdict'">
        { 'instances'        : instances,
          'suffix'           : suffix,
          'runConfiguration' : runConfiguration,
          'runScheduler'     : runScheduler
        }
      </call>
      <script>
        ERR_NUM_VERDICT = ERR_NUM[0]
        ERR_NUM_TOTAL   = ERR_NUM_TOTAL + ERR_NUM[0]
      </script>
      <!-- ====== Write information phases to xml report ============ -->
      <!-- == Write phase summary == -->
      <!-- (this function is in log phase and use ERR_NUM_* variables) -->
      <call function="'writeSummary'">
        {
          'scenario' : scenario,
          'fileFd'   : LOG_MAIN_FD
        }
      </call>
      <!-- ============ POSTAMBLE ==================================== -->
      <call function="'mainPostamble'">
        {
          'instances' : instances,
          'scheduler' : scheduler
        }
      </call>
    </sequence>
    </function>
</stax>
opends/tests/system-tests/phases/main_run_lib.xml
New file
@@ -0,0 +1,341 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <!-- ************************************************************ -->
  <function name="mainPreamble">
   <function-prolog>
      'preamble before running the system test'
    </function-prolog>
    <function-map-args>
      <function-arg-def name="instances" type="required">
        <function-arg-description>
          instances list
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="scheduler" type="required">
        <function-arg-description>
          clients list
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <message log="1">
        '=================== PREAMBLE  ========================='
      </message>
      <!--== Do some stuff on instances machines ==-->
      <paralleliterate in="instances" var="instance">
        <sequence>
          <!-- Check that date/hour are synchronised beetween machines -->
          <!-- TBD -->
          <!-- Create folders on remote hosts -->
          <call function="'createFolder'">
            { 'location'   : instance.getHost(),
              'foldername' : '%s' % LOG_DIR ,
              'fileFd'     : NO_FILE
            }
          </call>
          <call function="'createFolder'">
            { 'location'   : instance.getHost(),
              'foldername' : '%s' % LOG_TMP_DIR ,
              'fileFd'     : NO_FILE
            }
          </call>
          <call function="'createFolder'">
            { 'location'   : instance.getHost(),
              'foldername' : '%s' % LOG_XML_TMP_DIR ,
              'fileFd'     : NO_FILE
            }
          </call>
        </sequence>
      </paralleliterate>
      <!--== Get the clients list from all modules ==-->
      <script>
        clients = []
        for module in scheduler:
          if (module.getEnabled() == "true"):
            clients.extend(module.getClients())
      </script>
      <paralleliterate in="clients" var="client">
        <sequence>
          <if expr="client.getHost() != NOT_DEFINED">
            <sequence>
              <!--== Create folders on remote hosts ==-->
              <call function="'createFolder'">
                { 'location'   : client.getHost(),
                  'foldername' : '%s' % LOG_DIR ,
                  'fileFd'     : NO_FILE
                }
              </call>
              <call function="'createFolder'">
                { 'location'   : client.getHost(),
                  'foldername' : '%s' % LOG_TMP_DIR ,
                  'fileFd'     : NO_FILE
                }
              </call>
              <call function="'createFolder'">
                { 'location'   : client.getHost(),
                  'foldername' : '%s' % LOG_XML_TMP_DIR ,
                  'fileFd'     : NO_FILE
                }
              </call>
            </sequence>
          </if>
        </sequence>
      </paralleliterate>
      <message log="1">
        '== Found %s Error(s) during this phase' % (ERR_NUM[0])
      </message>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="mainPostamble">
   <function-prolog>
      'postamble after running the system test'
    </function-prolog>
    <function-map-args>
      <function-arg-def name="instances" type="required">
        <function-arg-description>
          instances list
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="scheduler" type="required">
        <function-arg-description>
          clients list
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <message log="1">
        '=================== POSTAMBLE  ========================='
      </message>
      <script> hosts = [] </script>
      <iterate in="instances" var="instance">
        <sequence>
          <!--== Create instance directory on main host ==-->
          <call function="'createFolder'">
            { 'location'   : STAXServiceMachine,
              'foldername' : '%s/%s' % (LOG_DIR,instance.getName()) ,
              'fileFd'     : NO_FILE
            }
          </call>
          <!--== Log cn=monitor replication stuff ==-->
          <script>
            clientHostFullName = '%s%s' % (instance.getHost(),DOMAIN[0])
            if (clientHostFullName != STAXServiceMachine):
              outputFile = '%s/cnMonitor.txt' % LOG_DIR
            else:
              outputFile = '%s/%s/cnMonitor.txt' % (LOG_DIR,instance.getName())
          </script>
          <call function="'ldapSearch'">
            { 'location'       : instance.getHost(),
              'dsPath'         : instance.getInstallDir(),
              'dsInstanceHost' : instance.getHost(),
              'dsInstancePort' : instance.getLDAPPort(),
              'dsInstanceDn'   : DIRECTORY_INSTANCE_DN,
              'dsInstancePswd' : DIRECTORY_INSTANCE_PSWD,
              'dsScope'        : 'sub',
              'dsBaseDN'       : 'cn=monitor',
              'dsFilter'       : 'objectclass=*',
              'expectedRC'     : 0,
              'fileFd'         : NO_FILE,
              'outputFile'     : outputFile
            }
          </call>
          <if expr="clientHostFullName != STAXServiceMachine">
            <call function="'copyFile'">
            {
              'srcFile'    : '%s/cnMonitor.txt' % LOG_DIR,
              'destFile'   : '%s/%s/cnMonitor.txt'%(LOG_DIR,instance.getName()),
              'location'   : instance.getHost(),
              'remoteHost' : STAXServiceMachine,
              'fileFd'     : NO_FILE
            }
            </call>
          </if>
          <!--== Save conf.ldif file ==-->
          <call function="'copyFile'">
          {
            'srcFile'    : '%s/config/config.ldif'%(instance.getInstallDir()),
            'destFile'   : '%s/%s/config.ldif' % (LOG_DIR,instance.getName()),
            'location'   : instance.getHost(),
            'remoteHost' : STAXServiceMachine,
            'fileFd'     : NO_FILE
          }
          </call>
          <!--== Move tmp folder from remote hosts to main host ==-->
          <call function="'moveFolder'">
          {
            'sourceHost' : instance.getHost(),
            'directory'  : '%s/tmp' % LOG_DIR,
            'hosts'      : hosts
          }
          </call>
          <script> hosts = STAXResult </script>
        </sequence>
      </iterate>
      <!--== Get the clients list from all modules ==-->
      <script>
        clients = []
        for module in scheduler:
          if (module.getEnabled() == "true"):
            clients.extend(module.getClients())
      </script>
      <iterate in="clients" var="client">
        <sequence>
          <call function="'moveFolder'">
          {
            'sourceHost' : client.getHost(),
            'directory'  : '%s/tmp' % LOG_DIR,
            'hosts'      : hosts
          }
          </call>
          <script> hosts = STAXResult </script>
        </sequence>
      </iterate>
      <!--== Copy xsl file needed to read the report ==-->
      <call function="'copyFile'">
      {
        'srcFile'    : '%s/report/result.xsl' % (TESTS_DIR),
        'destFile'   : '%s/result.xsl' % LOG_DIR,
        'remoteHost' : STAXServiceMachine,
        'fileFd'     : NO_FILE
      }
      </call>
      <!--== Copy css file needed to read the report ==-->
      <call function="'copyFile'">
      {
        'srcFile'    : '%s/report/result.css' % (TESTS_DIR),
        'destFile'   : '%s/result.css' % LOG_DIR,
        'remoteHost' : STAXServiceMachine,
        'fileFd'     : NO_FILE
      }
      </call>
      <!--== Close main output file ==-->
      <script>
        LOG_MAIN_FD.write('&lt;/systemTestRoot&gt;\n')
        LOG_MAIN_FD.close()
      </script>
      <message>'***************************************************'</message>
      <message>'******   RUN IS FINISHED '                          </message>
      <message>'****** Results stored on %s ' % STAXServiceMachine  </message>
      <message>'****** %s' % LOG_DIR                                </message>
      <message>'****** Found %s ERROR(S)' % ERR_NUM_TOTAL           </message>
      <message>'***************************************************'</message>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="moveFolder">
   <function-prolog>
      'copy remote directory to STAXServiceMachine and delete it'
    </function-prolog>
    <function-map-args>
      <function-arg-def name="sourceHost" type="required">
        <function-arg-description>
          remote source host name where directory will be get
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="directory" type="required">
        <function-arg-description>
          directory path
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="hosts" type="optional" default="[]">
        <function-arg-description>
          if sourceHost is in the hosts list, then do nothing
          add the sourceHost in the list if operations are done
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <script>
        sourceHostFullName = '%s%s' % (sourceHost,DOMAIN[0])
      </script>
      <if expr="sourceHost not in hosts
                and sourceHostFullName != STAXServiceMachine
                and sourceHost != NOT_DEFINED">
        <sequence>
          <call function="'copyFolder'">
          {
            'location'      : sourceHost,
            'fromDirectory' : directory,
            'toDirectory'   : directory,
            'remoteHost'    : STAXServiceMachine,
            'fileFd'        : NO_FILE
          }
          </call>
          <!--
          <call function="'deleteFolder'">
            { 'location'   : sourceHost,
              'foldername' : '%s' % directory,
              'fileFd'     : NO_FILE,
              'expectedRC' : [0]
            }
          </call>
          -->
          <script>
            hosts.append(sourceHost)
          </script>
        </sequence>
      </if>
      <return> hosts </return>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/phases/parser/parser.py
New file
@@ -0,0 +1,1107 @@
#!/usr/bin/python
# 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
# information:
#      Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#      Copyright 2008 Sun Microsystems, Inc.
from java.io import File
from java.io import StringReader
from org.xml.sax import InputSource
from org.xml.sax import SAXParseException
from org.xml.sax.helpers import DefaultHandler
from javax.xml.parsers import DocumentBuilderFactory
from javax.xml.parsers import DocumentBuilder
from org.w3c.dom import Document
from org.w3c.dom import Element
from org.w3c.dom import Node
from org.w3c.dom import NodeList
#============================================================================
#
# GLOBAL VARIABLES
# Warning : some of global variables are also defined in main_run.xml file
NOT_DEFINED = 'ERROR_not_defined'
TRUE = 0
FALSE = 1
#============================================================================
#
# CLASS DEFINITION
#
# Class for suffix
#
###########################
class Scenario:
  "Describes the scenario main informations"
  def __init__(self, name, description):
    self.name         = name
    self.description  = description
    self.durationUnit = NOT_DEFINED
    self.durationTime = NOT_DEFINED
  def getName(self):
    return self.name
  def getDescription(self):
    return self.description
  def getDurationUnit(self):
    return self.durationUnit
  def setDurationUnit(self,durationUnit):
    self.durationUnit = durationUnit
  def getDurationTime(self):
    return self.durationTime
  def setDurationTime(self,durationTime):
    self.durationTime = durationTime
###########################
class SubordinateTemplate:
  "Describes entry data information for ldif file"
  def __init__(self, cType, cNb):
    self.cType = cType
    self.cNb   = cNb
  def getType(self):
    return self.cType
  def getNb(self):
    return self.cNb
###########################
class Branch:
  """Describes branch data information for ldif file :
   [name, [list_of_branch], [list_of_leaf]]"""
  def __init__(self, name, subtrees, subordinateTemplates):
    self.name = name
    self.subtrees = subtrees
    self.subordinateTemplates = subordinateTemplates
  def getName(self):
    return self.name
  def getSubtrees(self):
    return self.subtrees
  def getSubordinateTemplates(self):
    return self.subordinateTemplates
###########################
class SuffixTopology:
  "Describes the topology (list of instances,..) of a suffix"
  def __init__(self, name, initRule, instanceSourceName):
    self.name               = name
    self.initRule           = initRule
    self.instanceSourceName = instanceSourceName
    self.instanceRef        = NOT_DEFINED
  def getName(self):
    return self.name
  def getInstanceRef(self):
    return self.instanceRef
  def setInstanceRef(self,instanceRef):
    self.instanceRef = instanceRef
  def getInitRule(self):
    return self.initRule
  def getInstanceSourceName(self):
    return self.instanceSourceName
###########################
class Suffix:
  """Describes suffix information,
   tree is a list of Branch objectclasses
   topology is a list of SuffixTopology objectclasses"""
  def __init__(self, sid, dn, topology, nbOfEntries, tree):
    self.sid         = sid
    self.dn          = dn
    self.topology    = topology
    self.nbOfEntries = nbOfEntries
    self.tree        = tree
  def getId(self):
    return self.sid
  def getSuffixDn(self):
    return self.dn
  def getTopology(self):
    return self.topology
  def setTopology(self,topology):
    self.topology = topology
  def getElementFromTopology(self, instanceName):
    "Return the instance objectclass of the instance name given in parameter"
    found = FALSE
    for cElement in self.topology:
      if cElement.getName() == instanceName:
        found = TRUE
        break
    return [found,cElement]
  def getNbOfEntries(self):
    return self.nbOfEntries
  def getTree(self):
    return self.tree
#
# Class for instance
#
###########################
class Instance:
  "Describes a generic LDAP instance"
  def __init__(self, iid, name, host, installDir, tarball, portLDAP):
    self.iid         = iid
    self.name        = name
    self.host        = host
    self.installDir  = installDir
    self.tarball     = tarball
    self.portLDAP    = portLDAP
    self.os          = NOT_DEFINED
    self.buildId     = NOT_DEFINED
    self.binDir      = NOT_DEFINED
    self.synchroDate = NOT_DEFINED
  def getId(self):
    return self.iid
  def setId(self,iid):
    self.iid = iid
  def getName(self):
    return self.name
  def getHost(self):
    return self.host
  def setHost(self,host):
    self.host = host
  def getInstallDir(self):
    return self.installDir
  def getTarball(self):
    return self.tarball
  def getLDAPPort(self):
    return self.portLDAP
  def getOs(self):
    return self.os
  def setOs(self,os):
    self.os = os
  def getBuildId(self):
    return self.buildId
  def setBuildId(self,buildId):
    self.buildId = buildId
  def getBinDir(self):
    return self.binDir
  def setBinDir(self,binDir):
    self.binDir = binDir
  def getSynchroDate(self):
    return self.synchroDate
  def setSynchroDate(self,synchroDate):
    self.synchroDate = synchroDate
###########################
class OpendsInstance(Instance):
  "Describes an opends Instance"
  def __init__(self, iid, name, host, installDir, tarball, portLDAP, \
               product, portLDAPS, portJMX, portREPL):
    self.iid         = iid
    self.name        = name
    self.product     = product
    self.host        = host
    self.installDir  = installDir
    self.tarball     = tarball
    self.portLDAP    = portLDAP
    self.portLDAPS   = portLDAPS
    self.portJMX     = portJMX
    self.portREPL    = portREPL
    self.javaVersion = NOT_DEFINED
  def getProduct(self):
    return self.product
  def getLDAPSPort(self):
    return self.portLDAPS
  def getJMXPort(self):
    return self.portJMX
  def getREPLPort(self):
    return self.portREPL
  def getJavaVersion(self):
    return self.javaVersion
  def setJavaVersion(self,javaVersion):
    self.javaVersion = javaVersion
#
# Class for client
#
###########################
class Client:
  "Describes a ldap client"
  def __init__(self, iid, name, host, params):
    self.iid        = iid
    self.name       = name
    self.host       = host
    self.params     = params
    self.start      = NOT_DEFINED
    self.stop       = NOT_DEFINED
    self.dependency = NOT_DEFINED
    self.result     = NOT_DEFINED
  def getId(self):
    return self.iid
  def getName(self):
    return self.name
  def getHost(self):
    return self.host
  def getParams(self):
    return self.params
  def getStart(self):
    return self.start
  def setStart(self,start):
    self.start = start
  def getStop(self):
    return self.stop
  def setStop(self,stop):
    self.stop = stop
  def getDependency(self):
    return self.dependency
  def setDependency(self,dependency):
    self.dependency = dependency
  def getResult(self):
    return self.result
  def setResult(self,result):
    self.result = result
###########################
class Module:
  "Describes a module that contains clients"
  def __init__(self, name, enabled, clients):
    self.name    = name
    self.enabled = enabled
    self.clients = clients
  def getName(self):
    return self.name
  def getEnabled(self):
    return self.enabled
  def getClients(self):
    return self.clients
#============================================================================
#
# FUNCTIONS
#
def getRefObjectByName(myName,myList):
  """This function returns the reference of a object specified
     by myName if it exist in myList"""
  found = FALSE
  msg = ''
  for myObject in myList:
    if myObject.getName() == myName:
      found = TRUE
      break
  if found == FALSE:
    msg = 'ERROR, getRefObjectByName(): cant find object reference for name %s'%\
          myName
  return [msg,myObject]
def _getPropValue(myNode):
  "This function get the first node text value of a node"
  propValueNode = myNode.getFirstChild()
  if (propValueNode.getNodeType() == Node.TEXT_NODE or
      propValueNode.getNodeType() == Node.COMMENT_NODE):
    #out = '%s' % (myNode.getNodeName())
    out = '%s' % (propValueNode.getNodeValue())
  else:
    out = 'ERROR %s has not a text children node type, should be' % \
          (myNode.getNodeName())
  return out
def _getAttributeNode(myNode,myAttributeName):
  cAttrNodes = myNode.getAttributes()
  cAttrNode = cAttrNodes.getNamedItem(myAttributeName)
  if (myNode.hasAttributes() and cAttrNode != None):
    cAttrValue = cAttrNode.getNodeValue()
  else:
    cAttrValue = NOT_DEFINED
  return cAttrValue
#============================================================================
#
# PARSER
#
def main(document):
  #document = STAXResult
  # Change code here to parse the document as you desire.
  # The code shown here is just an example for parsing a STAX xml document
  root = document.getDocumentElement()
  children = root.getChildNodes()
  msg              = ''
  globalParameters = []
  instances        = []
  suffix           = []
  clientPhases     = []
  cId              = 0
  for i in range(children.getLength()):
    cId += 1
    thisChild = children.item(i)
    #
    # Parsing global parameters node
    #
    if (thisChild.getNodeType() == Node.ELEMENT_NODE and
        thisChild.getNodeName() == 'globalParameters'):
      result = parseGlobalParameters(thisChild)
      msg = '%s \n %s' % (msg,result[0])
      scenario   = result[1]
      opendsName = result[2]
      opendsZip  = result[3]
      domain     = result[4]
    #
    # Parsing instance node
    #
    elif (thisChild.getNodeType() == Node.ELEMENT_NODE and
        thisChild.getNodeName() == 'instance'):
      cName = _getAttributeNode(thisChild,'name')
      if cName == NOT_DEFINED:
        msg = '%s\n ERROR: cant get instance name attribute, required' % msg
        return [msg,[],[]]
      cProduct = _getAttributeNode(thisChild,'product')
      if cProduct == NOT_DEFINED:
        msg = '%s\n ERROR: cant get instance product attribute, required'% msg
        return [msg,[],[]]
      #
      # opends instance parsing
      #
      if cProduct == 'opends':
        result = parseOpenDs(cId,cName,cProduct,opendsName,opendsZip,thisChild)
        msg = '%s \n %s' % (msg,result[0])
        instances.append(result[1])
      else:
        msg = '%s\n ERROR: unknown product %s' % (msg, cProduct)
    #
    # Parsing suffix node
    #
    elif (thisChild.getNodeType() == Node.ELEMENT_NODE and
        thisChild.getNodeName() == 'suffix'):
      cSuffixName = _getAttributeNode(thisChild,'dn')
      result = parseSuffix(cId,cSuffixName,thisChild)
      msg = '%s \n %s' % (msg,result[0])
      # restriction 1 suffix node
      suffix = result[1]
    #
    # Parsing scheduler node : should be only one node
    #
    elif (thisChild.getNodeType() == Node.ELEMENT_NODE and
        thisChild.getNodeName() == 'scheduler'):
      result       = parseScheduler(thisChild)
      msg          = '%s \n %s' % (msg,result[0])
      phases       = result[1]
      durationUnit = result[2]
      durationTime = result[3]
    #
    # Parsing other nodes...
    #
    elif thisChild.getNodeType() == Node.COMMENT_NODE:
      # Do nothing
      continue
    elif thisChild.getNodeType() == Node.ELEMENT_NODE:
      msg = '%s\n Found %s element' % (msg, thisChild.getNodeName())
  # End of parsing
  #
  # Set duration time and unit to scenario object
  #
  scenario.setDurationTime(durationTime)
  scenario.setDurationUnit(durationUnit)
  #
  # Set replication server host/port/installdir used by this suffix
  #
  for cSuffixInstance in suffix.getTopology():
    for cInstance in instances:
      if cInstance.getName() == cSuffixInstance.getName():
        cSuffixInstance.setInstanceRef(cInstance)
  return [msg,instances,suffix,phases,scenario,domain]
  # end of main function
#============================================================================
#
# Parse children and get information for opends instance
#
def parseOpenDs(cId,cName,cProduct,opendsName,opendsZip,thisChild):
  msg         = ''
  cHost       = 'localhost'
  cInstallDir = NOT_DEFINED
  cPortLDAP   = '1389'
  cPortLDAPS  = '1636'
  cPortJMX    = '1390'
  cPortREPL   = '1391'
  #
  # Parsing second level : host,ports,...
  #
  if thisChild.hasChildNodes():
    subChildren = thisChild.getChildNodes()
    for j in range(subChildren.getLength()):
      thisSubChild = subChildren.item(j)
      if (thisSubChild.getNodeType() == Node.ELEMENT_NODE and
          thisSubChild.getNodeName() == 'host'):
        cHost = _getPropValue(thisSubChild)
      elif (thisSubChild.getNodeType() == Node.ELEMENT_NODE and
          thisSubChild.getNodeName() == 'installDir'):
        cInstallDir = _getPropValue(thisSubChild)
      elif (thisSubChild.getNodeType() == Node.ELEMENT_NODE and
          thisSubChild.getNodeName() == 'ports'):
        # Get instance port values
        if thisSubChild.hasChildNodes():
          portList = thisSubChild.getChildNodes()
          for k in range(portList.getLength()):
            thisPort = portList.item(k)
            if (thisPort.getNodeType() == Node.ELEMENT_NODE and
                thisPort.getNodeName() == 'ldap'):
              cPortLDAP = _getPropValue(thisPort)
            elif (thisPort.getNodeType() == Node.ELEMENT_NODE and
                thisPort.getNodeName() == 'ldaps'):
              cPortLDAPS = _getPropValue(thisPort)
            elif (thisPort.getNodeType() == Node.ELEMENT_NODE and
                thisPort.getNodeName() == 'jmx'):
              cPortJMX = _getPropValue(thisPort)
            elif (thisPort.getNodeType() == Node.ELEMENT_NODE and
                thisPort.getNodeName() == 'replicationServer'):
              cPortREPL = _getPropValue(thisPort)
            # must be at the end of the if case
            elif (thisPort.getNodeType() == Node.TEXT_NODE or
                  thisPort.getNodeType() == Node.COMMENT_NODE):
              # text node information,skip, no need
              continue
            else:
              msg = '%s\n ERROR: instance %s : unknown port node name %s' % \
                    (msg, cName, thisPort.getNodeName())
      # must be at the end of the if case
      elif (thisSubChild.getNodeType() == Node.TEXT_NODE or
            thisSubChild.getNodeType() == Node.COMMENT_NODE):
        # text node information,skip, no need
        continue
      else:
        msg = '%s\n ERROR: instance %s : unknown instance property named %s' %\
              (msg, cName, thisSubChild.getNodeName())
    # end for
  #
  # no second level
  #
  else:
    msg = '%s\n ERROR: instance %s : no children for instance node' % \
          (msg,cName)
  cInstallDir = '%s/%s/%s' % (cInstallDir,cName,opendsName)
  return [msg,OpendsInstance(cId,cName,cHost,cInstallDir,opendsZip,cPortLDAP,\
                             cProduct,cPortLDAPS,cPortJMX,cPortREPL)]
#============================================================================
#
# Parse children and get information for suffix node
#
def parseSuffix(cId,cSuffixName,thisChild):
  msg                = ''
  cSuffixReplServers = NOT_DEFINED
  cNbOfEntries       = NOT_DEFINED
  #
  # Parsing second level : instanceList,numberOfEntries,...
  #
  if thisChild.hasChildNodes():
    subChildren = thisChild.getChildNodes()
    for j in range(subChildren.getLength()):
      cInstanceSourceName = NOT_DEFINED
      thisSubChild = subChildren.item(j)
      if (thisSubChild.getNodeType() == Node.ELEMENT_NODE and
          thisSubChild.getNodeName() == 'topology'):
        cSuffixReplServers = []
        # Get instance names
        if thisSubChild.hasChildNodes():
          instanceList = thisSubChild.getChildNodes()
          for k in range(instanceList.getLength()):
            thisInstance = instanceList.item(k)
            if (thisInstance.getNodeType() == Node.ELEMENT_NODE and
                thisInstance.getNodeName() == 'element'):
              cInstanceName = _getAttributeNode(thisInstance,'instanceName')
              cInstanceInitRule = _getAttributeNode(thisInstance,'initRule')
              cInstanceSourceName = _getAttributeNode(thisInstance, \
                                                      'instanceSourceName')
              if cInstanceInitRule.lower() == "totalupdate":
                if cInstanceSourceName == NOT_DEFINED:
                  msg = '%s\n ERROR: parseSuffix(): initRule=totalUpdate' % msg
                  msg = '%s, and should have also instanceSource attribute'%msg
                  msg = '%s which has been not found' % msg
              cSuffixReplServers.append(SuffixTopology(cInstanceName,\
                                                       cInstanceInitRule,\
                                                       cInstanceSourceName))
            # must be at the end of the if case
            elif (thisInstance.getNodeType() == Node.TEXT_NODE or
                  thisInstance.getNodeType() == Node.COMMENT_NODE):
              # text node information,skip, no need
              continue
            else:
              msg = '%s\n ERROR: parseSuffix(): unknown node named %s' % \
                    (msg, thisInstance.getNodeName())
        else:
          msg = '%s\n ERROR: parseSuffix(): %s node should have child node %s'%\
                (msg,thisSubChild.getNodeName())
      elif (thisSubChild.getNodeType() == Node.ELEMENT_NODE and
            thisSubChild.getNodeName() == 'numberOfEntries'):
        cNbOfEntries = _getPropValue(thisSubChild)
      # parsing suffix TREE
      elif (thisSubChild.getNodeType() == Node.ELEMENT_NODE and
            thisSubChild.getNodeName() == 'tree'):
        if thisSubChild.hasChildNodes():
          cNbOfEntries = _getAttributeNode(thisSubChild,'nbOfEntries')
          cResult = getSuffixTree('root',cNbOfEntries,thisSubChild)
          cBranches = cResult[1]
          msg = '%s\n%s' % (msg,cResult[0])
        else:
          msg = '%s\n ERROR: parseSuffix(): %s node should have child node %s'%\
                (msg,thisSubChild.getNodeName())
      # must be at the end of the if case
      elif (thisSubChild.getNodeType() == Node.TEXT_NODE or
            thisSubChild.getNodeType() == Node.COMMENT_NODE):
        # text node information,skip, no need
        continue
      else:
        msg = '%s\n ERROR: parseSuffix(): unknown suffix property named %s' % \
              (msg, thisSubChild.getNodeName())
  #
  # no subchildren for suffix node
  #
  else:
    msg = '%s\n ERROR: parseSuffix() : no children for suffix node' % msg
  return [msg,Suffix(cId,cSuffixName,cSuffixReplServers,cNbOfEntries,cBranches)]
#============================================================================
#
# Get tree information
# a branch has :
#   a name
#   some branches (0 or more)
#   some subordinateTemplate (0 or more)
def getSuffixTree(cBranchName,nbOfEntries,cNode):
  msg = ''
  # cSubordinateTemplates is a list of subordinateTemplates a node can have
  cSubordinateTemplates = []
  # cBranches is a list of branches a node can have
  cBranches = []
  nodeList = cNode.getChildNodes()
  for n in range(nodeList.getLength()):
    thisNode = nodeList.item(n)
    if (thisNode.getNodeType() == Node.ELEMENT_NODE and
        thisNode.getNodeName() == 'branch'):
      cResult = getSuffixTree(_getAttributeNode(thisNode,'name'),\
                              nbOfEntries,thisNode)
      cBranches.append(cResult[1])
      msg = '%s\n%s' % (msg,cResult[0])
    # get subordinateTemplate if exist
    # if percentage, calculate the nb of entries,
    # else get nb of entries directly
    elif (thisNode.getNodeType() == Node.ELEMENT_NODE and
          thisNode.getNodeName() == 'subordinateTemplate'):
      cPerc = NOT_DEFINED
      cType = _getAttributeNode(thisNode,'type')
      cPerc = _getAttributeNode(thisNode,'percentage')
      if cPerc != NOT_DEFINED:
        cPerc = (int(cPerc) * int(nbOfEntries)) / 100
      else:
        cPerc = _getAttributeNode(thisNode,'nb')
      cSubordinateTemplates.append(SubordinateTemplate(cType,cPerc))
    # must be at the end of the if case
    elif (thisNode.getNodeType() == Node.TEXT_NODE or
          thisNode.getNodeType() == Node.COMMENT_NODE):
      # text node information,skip, no need
      continue
    else:
      msg = '%s\n ERROR: getSuffixTree() : unknown node named %s' % \
            (msg, thisNode.getNodeName())
  if cBranches == []:
    cBranches = [NOT_DEFINED]
  if cSubordinateTemplates == []:
    cSubordinateTemplates = [NOT_DEFINED]
  return [msg,Branch(cBranchName,cBranches,cSubordinateTemplates)]
#============================================================================
#
# displayTree : display the data tree of a suffix with XML format
def getSuffixDataForXML(suffixName,cBranch):
  msg         = ''
  cBranchName = cBranch.getName()
  if cBranchName == 'root':
    msg = "%s\n <tree>" % msg
  else:
    msg = "%s\n <branch name=\"%s\">" %(msg,cBranchName)
  # leaf
  cLeafs = cBranch.getSubordinateTemplates()
  if (cLeafs[0] != NOT_DEFINED):
    for cLeaf in cLeafs:
      msg = '%s\n<subordinateTemplate type=\"%s\"' % (msg,cLeaf.getType())
      msg = '%s nb=\"%s\"></subordinateTemplate>'  % (msg,cLeaf.getNb())
  # subBranches
  subBranches = cBranch.getSubtrees()
  if subBranches[0] != NOT_DEFINED:
    for cSubBranch in subBranches:
      msg = '%s\n%s' % (msg,getSuffixDataForXML(suffixName,cSubBranch))
  if cBranchName == 'root':
    msg = "%s\n </tree>" % msg
  else:
    msg = "%s\n </branch>" % msg
  return msg
#============================================================================
#
# getSuffixDataForMakeLDIF : display the data tree of a suffix
# using makedlif format
def getSuffixDataForMakeLDIF(suffixName,nbOfEntries,cBranch):
  msg = ''
  cBranchName = cBranch.getName()
  if cBranchName == 'root':
    cBranchName = suffixName
  msg = "%s\nbranch: %s " % (msg,cBranchName)
  # leaf
  cLeafs = cBranch.getSubordinateTemplates()
  if (cLeafs[0] != NOT_DEFINED):
    for cLeaf in cLeafs:
      msg = '%s\nsubordinateTemplate: %s:%s' % (msg,cLeaf.getType(), \
                                                cLeaf.getNb())
  # subBranches
  subBranches = cBranch.getSubtrees()
  if subBranches[0] != NOT_DEFINED:
    for cSubBranch in subBranches:
      msg = '%s\n%s' % (msg,\
            getSuffixDataForMakeLDIF(suffixName,nbOfEntries,cSubBranch))
  return msg
#============================================================================
#
# Parse children and get information for scheduler node
#
def parseScheduler(thisChild):
  msg = ''
  scheduler = []
  #
  # Parsing second level : duration,module,...
  #
  if thisChild.hasChildNodes():
    subChildren = thisChild.getChildNodes()
    for j in range(subChildren.getLength()):
      cClients = NOT_DEFINED
      thisSubChild = subChildren.item(j)
      if (thisSubChild.getNodeType() == Node.ELEMENT_NODE and
          thisSubChild.getNodeName() == 'duration'):
        durationUnit = _getAttributeNode(thisSubChild,'unit')
        durationTime = _getPropValue(thisSubChild)
      elif (thisSubChild.getNodeType() == Node.ELEMENT_NODE and
          thisSubChild.getNodeName() == 'module'):
        cClients = []
        cModuleName = _getAttributeNode(thisSubChild,'name')
        cModuleEnabled = _getAttributeNode(thisSubChild,'enabled')
        result = parseClients(thisSubChild)
        msg = '%s \n %s' % (msg,result[0])
        cClients = result[1]
        scheduler.append(Module(cModuleName,cModuleEnabled,cClients))
      # must be at the end of the if case
      elif (thisSubChild.getNodeType() == Node.TEXT_NODE or
            thisSubChild.getNodeType() == Node.COMMENT_NODE):
        # text node information,skip, no need
        continue
      else:
        msg = '%s\n ERROR: parseScheduler() : unknown property named %s' % \
              (msg, thisSubChild.getNodeName())
  #
  # no subchildren
  #
  else:
    msg = '%s\n ERROR: parseScheduler() : no children for scheduler node' % msg
  return [msg,scheduler,durationUnit,durationTime]
#============================================================================
#
# Parse children and get information for a list of clients
#
def parseClients(thisChild):
  msg = ''
  clients = []
  #
  # Parsing second level : phase,...
  #
  if thisChild.hasChildNodes():
    subChildren = thisChild.getChildNodes()
    for j in range(subChildren.getLength()):
      thisSubChild = subChildren.item(j)
      if (thisSubChild.getNodeType() == Node.ELEMENT_NODE and
          thisSubChild.getNodeName() == 'client'):
        name       = NOT_DEFINED
        host       = NOT_DEFINED
        start      = NOT_DEFINED
        stop       = NOT_DEFINED
        dependency = NOT_DEFINED
        clientId   = NOT_DEFINED
        params     = []
        name       = _getAttributeNode(thisSubChild,'name')
        host       = _getAttributeNode(thisSubChild,'host')
        start      = _getAttributeNode(thisSubChild,'start')
        stop       = _getAttributeNode(thisSubChild,'stop')
        dependency = _getAttributeNode(thisSubChild,'dependencyId')
        clientId   = _getAttributeNode(thisSubChild,'id')
        # Get phase sub-nodes information
        if thisSubChild.hasChildNodes():
          nodeList = thisSubChild.getChildNodes()
          for k in range(nodeList.getLength()):
            thisNode = nodeList.item(k)
            if (thisNode.getNodeType() == Node.ELEMENT_NODE):
              param = [ thisNode.getNodeName(), _getPropValue(thisNode) ]
              params.append(param)
            # must be at the end of the if case
            elif (thisNode.getNodeType() == Node.TEXT_NODE or
                  thisNode.getNodeType() == Node.COMMENT_NODE):
              # text node information,skip, no need
              continue
            else:
              msg = '%s\n ERROR: parseClients(): unknown node named %s' % \
                    (msg, thisNode.getNodeName())
        else:
          msg = '%s\n ERROR: parseClients(): %s node should have child %s' % \
                (msg,thisSubChild.getNodeName())
        cClient = Client(clientId,name,host,params)
        if (start == NOT_DEFINED):
          msg = '%s\n ERROR: parseClients(): client %s:' % (msg,name)
          msg = '%s start attribute required' % msg
        else:
          cClient.setStart(start)
        if (stop != NOT_DEFINED):
          cClient.setStop(stop)
        if (dependency != NOT_DEFINED):
          cClient.setDependency(dependency)
        clients.append(cClient)
      # must be at the end of the if case
      elif (thisSubChild.getNodeType() == Node.TEXT_NODE or
            thisSubChild.getNodeType() == Node.COMMENT_NODE):
        # text node information,skip, no need
        continue
      else:
        msg = '%s\n ERROR: parseClients() : unknown property named %s' % \
              (msg, thisSubChild.getNodeName())
  #
  # no subchildren for suffix node
  #
  else:
    msg = '%s\n ERROR: parseClients() : no children for clients node' % (msg)
  return [msg,clients]
#============================================================================
#
# Parse global parameters node
#
def parseGlobalParameters(thisChild):
  msg        = ''
  result     = []
  scenario   = NOT_DEFINED
  opendsName = NOT_DEFINED
  opendsZip  = NOT_DEFINED
  domain     = NOT_DEFINED
  #
  # Parsing second level : opendsName,...
  #
  if thisChild.hasChildNodes():
    subChildren = thisChild.getChildNodes()
    for j in range(subChildren.getLength()):
      thisSubChild = subChildren.item(j)
      if (thisSubChild.getNodeType() == Node.ELEMENT_NODE and
          thisSubChild.getNodeName() == 'opendsName'):
        opendsName = _getPropValue(thisSubChild)
      elif (thisSubChild.getNodeType() == Node.ELEMENT_NODE and
          thisSubChild.getNodeName() == 'opendsZip'):
        opendsZip = _getPropValue(thisSubChild)
      elif (thisSubChild.getNodeType() == Node.ELEMENT_NODE and
          thisSubChild.getNodeName() == 'domain'):
        domain = _getPropValue(thisSubChild)
      elif (thisSubChild.getNodeType() == Node.ELEMENT_NODE and
          thisSubChild.getNodeName() == 'scenario'):
        cResult = parseScenario(thisSubChild)
        scenario = cResult[1]
        msg = '%s\n%s' % (msg,cResult[0])
      # must be at the end of the if case
      elif (thisSubChild.getNodeType() == Node.TEXT_NODE or
            thisSubChild.getNodeType() == Node.COMMENT_NODE):
        # text node information,skip, no need
        continue
      else:
        msg = '%s\n ERROR: parseGlobalParameters(): unknown node named %s' % \
              (msg, thisSubChild.getNodeName())
  #
  # no subchildren for globalParameters node
  #
  else:
    msg = '%s\n ERROR: parseGlobalParameters(): no child for this node' % msg
  if (opendsName == NOT_DEFINED):
    msg = '%s\n ERROR: parseGlobalParameters() : opendsName not defined' % (msg)
  if (opendsZip == NOT_DEFINED):
    msg = '%s\n ERROR: parseGlobalParameters() : opendsZip not defined' % (msg)
  return [msg,scenario,opendsName,opendsZip,domain]
#============================================================================
#
# Parse global parameters node
#
def parseScenario(thisChild):
  preMsg      = 'ERROR: parseGlobalParameters():'
  msg         = ''
  result      = []
  name        = NOT_DEFINED
  description = NOT_DEFINED
  #
  # Parsing second level : opendsName,...
  #
  if thisChild.hasChildNodes():
    subChildren = thisChild.getChildNodes()
    for j in range(subChildren.getLength()):
      thisSubChild = subChildren.item(j)
      if (thisSubChild.getNodeType() == Node.ELEMENT_NODE and
          thisSubChild.getNodeName() == 'name'):
        name = _getPropValue(thisSubChild)
      elif (thisSubChild.getNodeType() == Node.ELEMENT_NODE and
          thisSubChild.getNodeName() == 'description'):
        description = _getPropValue(thisSubChild)
      # must be at the end of the if case
      elif (thisSubChild.getNodeType() == Node.TEXT_NODE or
            thisSubChild.getNodeType() == Node.COMMENT_NODE):
        # text node information,skip, no need
        continue
      else:
        msg = '%s\n ERROR: parseGlobalParameters(): unknown node named %s' % \
              (msg, thisSubChild.getNodeName())
  #
  # no subchildren for globalParameters node
  #
  else:
    msg = '%s\n %s no child for this node' % (preMsg,msg)
  if (name == NOT_DEFINED):
    msg = '%s\n %s scenario name not defined' % (preMsg,msg)
  if (description == NOT_DEFINED):
    msg = '%s\n %s scenario description not defined' % (preMsg,msg)
  return [msg,Scenario(name,description)]
opends/tests/system-tests/phases/parser/parser.xml
New file
@@ -0,0 +1,302 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <!-- ************************************************************ -->
  <function name="parser" scope="local">
    <function-list-args>
      <function-required-arg name="configurationFile">
        Name of file containing XML to be parsed
      </function-required-arg>
    </function-list-args>
    <sequence>
      <!--==========  Load XML file  =========-->
      <message log="1">
        'configuration file is : %s' % configurationFile
      </message>
      <call function="'parseXML'">configurationFile</call>
      <!--==========  Parse xml  =========-->
      <script>
        instances = []
        suffix = []
        scheduler = []
        sys.path.append("%s/phases/parser" % TESTS_DIR )
        from parser import *
        parserResult = main(STAXResult)
        msg          = parserResult[0]
        instances    = parserResult[1]
        suffix       = parserResult[2]
        scheduler    = parserResult[3]
        scenario     = parserResult[4]
        if (parserResult[5] != NOT_DEFINED):
          DOMAIN[0]  = '.%s' % parserResult[5]
      </script>
      <!--========  Set some attributes to add in objects   ======-->
      <paralleliterate in="instances" var="instance">
        <sequence>
          <call function="'getOSvariables'">
            { 'hostname' : instance.getHost() }
          </call>
          <script>
            # Set OS
            OSName = STAXResult
            instance.setOs(OSName)
            # Set bin directory
            OSName = OSName.lower()
            if ( OSName.count('win') == 0 ):
              binDir = '%s/bin' % instance.getInstallDir()
            else:
              binDir = '%s/bat' % instance.getInstallDir()
            instance.setBinDir(binDir)
            # Set synchro date
            #import java.util.Date
            #date = '%s' % (strftime('%Y-%m-%d %H:%M:%S',localtime()))
            #instance.setSynchroDate(date)
          </script>
          <call function="'getOSDate'">
            { 'location' : instance.getHost() }
          </call>
          <script>
            instance.setSynchroDate(STAXResult[0])
          </script>
        </sequence>
      </paralleliterate>
      <!--========  Basic configuration checks       ======-->
      <!-- replace localhost by real host name -->
      <script>
        for instance in instances:
          if (instance.getHost() == 'localhost'):
            instance.setHost(STAXServiceMachine.split('.')[0])
      </script>
      <!-- ports should not be the same           -->
      <!-- if several instances on the same host  -->
      <script>
        for instance in instances:
          product = instance.getProduct()
          if product == 'opends':
            name1      = instance.getName()
            host1      = instance.getHost()
            portLdap1  = instance.getLDAPPort()
            portLdaps1 = instance.getLDAPSPort()
            portJmx1   = instance.getJMXPort()
            for instance2 in instances:
              name2      = instance2.getName()
              product2   = instance2.getProduct()
              host2      = instance2.getHost()
              portLdap2  = instance2.getLDAPPort()
              portLdaps2 = instance2.getLDAPSPort()
              portJmx2   = instance2.getJMXPort()
              if (name2 != name1 and product2 == 'opends' and
                  host1 == host2 and portLdap1 == portLdap2):
                msg = '%s\nWARNING : same LDAP port for %s and %s on %s'%\
                      (msg,name1,name2,host1)
              if (name2 != name1 and product2 == 'opends' and
                  host1 == host2 and portLdaps1 == portLdaps2):
                msg = '%s\nWARNING : same LDAPS port for %s and %s on %s'%\
                       (msg,name1,name2,host1)
              if (name2 != name1 and product2 == 'opends' and
                  host1 == host2 and portJmx1 == portJmx2):
                msg = '%s\nWARNING : same JMX port for %s and %s on %s' % \
                       (msg,name1,name2,host1)
          # end if product = 'opends'
      </script>
      <!-- client id should be unique -->
      <script>
        clients = []
        for g in scheduler:
          if (g.getEnabled() == "true"):
            clients.extend(g.getClients())
        nbClients = len(clients)
        i = 0
        while i &lt; nbClients:
          client1 = clients.pop()
          for client2 in clients:
            if client1.getId() == client2.getId():
              msg = '%s\ERROR: clients %s and %s have same id %s, must NOT!'%\
                     (msg,client1.getName(),client2.getName(),client1.getId())
          i += 1
      </script>
      <!-- check instances have "synchronized" date -->
      <script>
        myInstances = []
        for instance in instances:
          myInstances.append(instance)
        for instance in instances:
          sDate1 = instance.getSynchroDate()
          day1 = sDate1[0:sDate1.find('-')-1].strip()
          time1 = sDate1[sDate1.find('-')+1:len(sDate1)].strip()
          hour1 = time1[0:time1.find(':')-1].strip()
          minute1 = time1[time1.find(':')+1:len(time1)].strip()
          myInstances.remove(instance)
          for instance2 in myInstances:
            sDate2 = instance2.getSynchroDate()
            day2 = sDate2[0:sDate2.find('-')-1].strip()
            time2 = sDate2[sDate2.find('-')+1:len(sDate2)].strip()
            hour2 = time1[0:time2.find(':')-1].strip()
            minute2 = time2[time2.find(':')+1:len(time2)].strip()
            if day1 != day2:
              msg = '%s\nERROR %s (%s) and %s (%s) day dates are not synchronised' % \
                    (msg,instance.getName(),day1,instance2.getName(),day2)
            if hour1 != hour2:
              msg = '%s\nERROR %s (%s) and %s (%s) hours are not synchronised' % \
                    (msg,instance.getName(),hour1,instance2.getName(),hour2)
            if minute1 != minute2:
              msg = '%s\nWARNING %s (%s) and %s (%s) minutes are not synchronised' % \
                    (msg,instance.getName(),minute1,instance2.getName(),minute2)
      </script>
      <!--==========  Display output parsing  =========-->
      <if expr="msg.find('TRACE') != -1">
        <!-- If trace found during parsing, display message -->
         <message log="1">'TRACE found : \"%s\"' % msg</message>
      </if>
      <if expr="msg.find('WARNING') != -1">
        <!-- If warning found during parsing, display message -->
        <message log="1">'WARNING found : \"%s\"' % msg</message>
      </if>
      <if expr="msg.find('ERROR') != -1">
        <!-- If errors found during parsing, exit -->
        <sequence>
           <script>ERR_NUM[0] += 1</script>
           <message log="1">'EXIT as error(s) found : \"%s\"' % msg</message>
           <return>msg</return>
         </sequence>
      </if>
      <return>
        parserResult
      </return>
    </sequence>
  </function>
  <!-- ******************************************************************* -->
  <!-- Following function is used to parse an XML file and return the DOM  -->
  <!-- document object                                                     -->
  <!-- ******************************************************************* -->
  <function name="parseXML" scope="local">
    <function-list-args>
      <function-required-arg name="xmlFileName">
        Name of file containing XML to be parsed
      </function-required-arg>
    </function-list-args>
    <sequence>
      <!-- Parse the XML -->
      <script>
        from java.io import File
        from java.io import StringReader
        from org.xml.sax import InputSource
        from org.xml.sax import SAXParseException
        from org.xml.sax.helpers import DefaultHandler
        from javax.xml.parsers import DocumentBuilderFactory
        from javax.xml.parsers import DocumentBuilder
        from org.w3c.dom import Document
        from org.w3c.dom import Element
        from org.w3c.dom import Node
        from org.w3c.dom import NodeList
        dtdFileName = '../../stax.dtd'
        #********************************************** #
        # private Python classes                        #
        # This class handles XML Parsing exceptions
        class ParserException(Exception):
            pass
        # This class handles the exception raised by XML parser
        class ParserResolver(DefaultHandler):
            def resolveEntity (self, publicId, systemId):
                return InputSource(dtdFileName)
            def error (self, e):
                raise 'error', e
            def warning (self, e):
                raise 'warning', e
            def fatalError (self, e):
                raise 'fatal', e
        factory = DocumentBuilderFactory.newInstance()
        factory.setValidating(1)
        factory.setIgnoringElementContentWhitespace(0)
        try:
          parseError    = 0
          builder  = factory.newDocumentBuilder()
          document = builder.parse(xmlFileName)
        except SAXParseException, spe:
          parseError = 1
      </script>
      <!-- Quit if there is any parsing error -->
      <if expr="parseError">
        <sequence>
          <script>
            errmsg = 'Error occurred parsing file %s\n line: %s\n msg: %s' % \
                      (xmlFileName, spe.getLineNumber(), spe.getMessage())
          </script>
          <log>errmsg</log>
          <message log="1">errmsg</message>
          <terminate/>
        </sequence>
      </if>
      <return>document</return>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/phases/scheduler/scheduler.py
New file
@@ -0,0 +1,36 @@
#!/usr/bin/python
# 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
# information:
#      Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#      Copyright 2008 Sun Microsystems, Inc.
def getInstance(instanceName,instances):
  res = 'ERROR'
  for instance in instances:
    if (instance.getName() == instanceName):
      res = instance
      break
  return res
opends/tests/system-tests/phases/scheduler/scheduler.xml
New file
@@ -0,0 +1,577 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <defaultcall function="scheduler"/>
  <!-- ************************************************************ -->
  <function name="scheduler">
    <function-map-args>
      <function-arg-def name="instances" type="required">
        <function-arg-description>
          instance object
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="suffix" type="required">
        <function-arg-description>
          suffix object
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="scheduler" type="required">
        <function-arg-description>
          scheduler object
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="scenario" type="required">
        <function-arg-description>
          scenario object
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!--==========  Call preambule  =========-->
      <script>
        tagAttr = []
        durationValue = '%s%s' % \
                        (scenario.getDurationTime(),scenario.getDurationUnit())
        tagAttr.append(['duration',durationValue])
      </script>
      <call function="'phasePreamble'">
      { 'phaseName' : 'scheduler' ,
        'tagAttr'   : tagAttr,
        'fileFd'    : LOG_MAIN_FD }
      </call>
      <!--==== Get the clients list from all modules ==============-->
      <script>
        clients = []
        for m in scheduler:
          if (m.getEnabled() == "true"):
            clients.extend(m.getClients())
      </script>
      <!--==== Copy client data into client host ====-->
      <call function="'copyClients'">
      {
        'clients'    : clients
      }
      </call>
      <script>
        MachineList = STAXResult
      </script>
      <if expr="ERR_NUM[0] == 0">
        <sequence>
          <!--==== Start the system test and launch client's process ====-->
          <call function="'runClients'">
          {
            'clients'   : clients,
            'instances' : instances,
            'scenario'  : scenario
          }
          </call>
          <!--==========  Merge files    ==========-->
          <call function="'mergeClientsFiles'">
          {
            'scheduler' : scheduler,
            'fileFd'    : LOG_MAIN_FD
          }
          </call>
        </sequence>
      </if>
      <!--==========  Call postphase =========-->
      <call function="'phasePostamble'">
      {
        'phaseName' : 'scheduler',
        'fileFd'    : LOG_MAIN_FD
      }
      </call>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="copyClients">
    <function-map-args>
      <function-arg-def name="clients" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!--==========  Define variables  =========-->
      <script>
        fileList = STAXGlobal([])
      </script>
      <!--==== Get the list of hosts for each client ====-->
      <script>
        list = NOT_DEFINED
        # for each clients get from conf.xml file
        for client in clients:
          if list == NOT_DEFINED:
            list = '%s' % client.getHost()
          elif list.find(client.getHost()) == -1:
            list = '%s,%s' % (list,client.getHost())
        list = list.split(",")
      </script>
      <!--==========  Copy directory in parallel   ==========-->
      <paralleliterate in="list" var="host">
        <sequence>
          <if expr="host != NOT_DEFINED">
            <sequence>
              <!--==== open logfile ====-->
               <call function="'getLogFileName'">
                {
                  'type'   : 'host',
                  'object' : host,
                  'prefix' : 'client_copy'
                }
              </call>
              <script>
                logFile = STAXResult
                fileList.append(logFile)
                fileFd = open(logFile,'w')
              </script>
              <!--==== copy directory ====-->
              <script>
                fullHostName = '%s%s' % (host,DOMAIN[0])
              </script>
              <call function="'copyFolder'">
                {
                  'remoteHost'    : fullHostName,
                  'fromDirectory' : '%s/clients' % TESTS_DIR,
                  'toDirectory'   : '%s/clients' % LOG_DIR,
                  'fileFd'        : fileFd
                }
              </call>
              <!--==== close logfile ====-->
              <script>
                fileFd.close()
                fileFd = ''
              </script>
            </sequence>
          </if>
        </sequence>
      </paralleliterate>
      <!--==========  Merge files    ==========-->
      <call function="'mergeFiles'">
        {
          'fileList' : fileList,
          'fileFd'   : LOG_MAIN_FD
        }
      </call>
      <return>list</return>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="runClients">
    <function-map-args>
      <function-arg-def name="clients" type="required">
      </function-arg-def>
      <function-arg-def name="instances" type="required">
      </function-arg-def>
      <function-arg-def name="scenario" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!--==========  Define variables  =========-->
      <script>
        fileList = STAXGlobal([])
        finishedClients = STAXGlobal([])
      </script>
      <!--==========  Run clients in parallel  =========-->
      <paralleliterate in="clients" var="client">
        <sequence>
        <!--==== calculate start/stop time, open dedicated logfile ====-->
          <script>
            start = client.getStart()
            stop = client.getStop()
            dependency = client.getDependency()
            if stop == NOT_DEFINED:
              stop = 't100'
            # convert durationTime in second
            if scenario.getDurationUnit() == 's':
              durationTime = int(scenario.getDurationTime())
            elif scenario.getDurationUnit() == 'm':
              durationTime = int(scenario.getDurationTime()) * 60
            elif scenario.getDurationUnit() == 'h':
              durationTime = int(scenario.getDurationTime()) * 3600
            elif scenario.getDurationUnit() == 'd':
              durationTime = int(scenario.getDurationTime()) * 24 * 3600
            if (start != NOT_DEFINED and stop != NOT_DEFINED):
              # remove t for t10, t20...
              start = start.split('t')[1]
              stop = stop.split('t')[1]
              start = int(start) * int(durationTime) / 100
              startms = int(start) * 1000
              stop = int(stop) * int(durationTime) / 100
              clientDuration = stop - start
          </script>
          <!--==== open logfile ====-->
           <call function="'getLogFileName'">
            {
              'type'   : 'client',
              'object' : client,
              'prefix' : 'client'
            }
          </call>
          <script>
            logFile = STAXResult
            fileList.append(logFile)
            fileFd = open(logFile,'w')
            # Write start tag
            str = '\n&lt;client name=\"%s\"' % client.getName()
            str = '%s host=\"%s\"'           % (str,client.getHost())
            str = '%s start=\"%s\"'          % (str,client.getStart())
            str = '%s stop=\"%s\"'           % (str,client.getStop())
            str = '%s dependency=\"%s\"&gt;\n' % (str,client.getDependency())
            fileFd.write(str)
          </script>
          <!--== Start is NOT defined in client attribute ==-->
          <if expr="start == NOT_DEFINED">
            <sequence>
              <if expr="dependency == NOT_DEFINED">
                <sequence>
                  <script>
                    str = 'ERROR: client %s should have' % client.getName()
                    str = '%s start or dependency attribute defined' % str
                  </script>
                  <message> str </message>
                  <call function="'writeMessage'">
                  { 'fileFd'  : fileFd,
                    'content' : str
                  }
                  </call>
                  <script>ERR_NUM[0] += 1</script>
                </sequence>
              <else>
                <sequence>
                  <!--== Start is NOT defined, dependency is defined ==-->
                  <call function="'sleepForDependency'">
                  {
                    'client'       : client,
                    'clients'      : clients,
                    'durationTime' : durationTime,
                    'fileFd'       : fileFd
                  }
                  </call>
                </sequence>
              </else>
              </if>
            </sequence>
          <!--== Start is defined in client attribute ==-->
          <else>
            <sequence>
              <!--=== Sleep and wait to start the client when specified ===-->
              <call function="'sleep'">
              { 'location' : STAXServiceMachine,
                'sleepForMilliSeconds' : startms,
                'fileFd'   : fileFd
              }
              </call>
              <!--=== Wait if client depends on other clients ===-->
              <if expr="dependency != NOT_DEFINED">
                <sequence>
                  <call function="'sleepForDependency'">
                  {
                    'client'       : client,
                    'clients'      : clients,
                    'durationTime' : durationTime,
                    'fileFd'       : fileFd
                  }
                  </call>
                </sequence>
              </if>
            </sequence>
          </else>
          </if>
          <!--== Run the client ==-->
          <call function="'runClient'">
          {
            'client'    : client,
            'duration'  : clientDuration,
            'instances' : instances,
            'fileFd'    : fileFd
          }
          </call>
          <!--==== close logfile ====-->
          <script>
            fileFd.write('&lt;/client&gt;\n')
            fileFd.close()
            fileFd = ''
          </script>
        </sequence>
      </paralleliterate>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="runClient">
    <function-map-args>
      <function-arg-def name="client" type="required">
      </function-arg-def>
      <function-arg-def name="duration" type="required">
      </function-arg-def>
      <function-arg-def name="instances" type="required">
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <script>
        startTime=strftime("%Y%m%d@%H:%M:%S",localtime())
      </script>
      <!--=== log info ===-->
      <if expr="client.getHost() == NOT_DEFINED">
        <sequence>
          <script>
            str = '++ Start client %s'         % (client.getName())
            str = '%s (id=%s)'                 % (str, client.getId())
            str = '%s at %s'                   % (str, startTime)
            str = '%s, max duration is %s sec' % (str, duration)
          </script>
          <message> str </message>
          <call function="'writeMessage'">
          { 'fileFd'  : fileFd,
            'content' : str
          }
          </call>
        </sequence>
      <else>
        <sequence>
          <script>
            str = '++ Start client %s'         % (client.getName())
            str = '%s (id=%s)'                 % (str, client.getId())
            str = '%s running on %s'           % (str, client.getHost())
            str = '%s at %s'                   % (str, startTime)
            str = '%s, max duration is %s sec' % (str, duration)
          </script>
          <message> str </message>
          <call function="'writeMessage'">
          { 'fileFd'  : fileFd,
            'content' : str
          }
          </call>
        </sequence>
      </else>
      </if>
      <!--=== run the client, exit if time exceed duration time ===-->
      <script>
        timerKilled = TRUE
        clientXmlFile = '%s/clients/%s/%s.xml' % \
                        (TESTS_DIR,client.getName(),client.getName())
      </script>
      <timer duration="'%ss' % duration">
        <sequence>
          <!-- check if client exists before launching it-->
          <call function="'isFile'">
          {
            'location' : STAXServiceMachine,
            'fileName' : clientXmlFile
          }
          </call>
          <script>
            fileExist = STAXResult
          </script>
          <if expr="fileExist == TRUE">
            <sequence>
              <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
                      file="'%s' % clientXmlFile"/>
              <call function="'%s' % client.getName()">
              {
                'client'     : client,
                'instances'  : instances,
                'duration'   : duration,
                'fileFd'     : fileFd
              }
              </call>
              <script>
                errNum = STAXResult
                timerKilled = FALSE
              </script>
            </sequence>
          <else>
            <message>'ERROR : cant find file %s' % clientXmlFile </message>
          </else>
          </if>
        </sequence>
      </timer>
      <if expr="timerKilled == TRUE">
        <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
      </if>
      <script>
        finishedClients.append(client.getId())
      </script>
      <!--=== log info ===-->
      <script>
        stopTime=strftime("%Y%m%d@%H:%M:%S",localtime())
      </script>
      <message>
        '-- Stop %s client (id %s) running on %s at %s' %\
        (client.getName(),client.getId(),client.getHost(),stopTime)
      </message>
      <call function="'writeMessage'">
        {
          'content' : 'Stop at %s' % stopTime,
          'fileFd'  : fileFd
        }
      </call>
      <if expr="errNum == 0">
        <script>
          client.setResult('SUCCESS')
          fileFd.write('\n&lt;clientResult status=\"SUCCESS\"/&gt;\n')
        </script>
      <else>
        <script>
          client.setResult('FAIL')
          fileFd.write('\n&lt;clientResult status=\"FAIL\"/&gt;\n')
        </script>
      </else>
      </if>
      <!-- DO NOT record number of error(s) found by clients         -->
      <!-- each should use checkRC and ERR_NUM[0] is already updated -->
      <!-- <script>
        ERR_NUM[0] += errNum
      </script> -->
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="sleepForDependency">
    <function-map-args>
      <function-arg-def name="location" type="optional"
                        default="'%s' % STAXServiceMachine">
      </function-arg-def>
      <function-arg-def name="client" type="required">
      </function-arg-def>
      <function-arg-def name="clients" type="required">
      </function-arg-def>
      <function-arg-def name="durationTime" type="required">
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!--== Convert dependencyId attribute value into a list ==-->
      <script>
        clientOfClientIds = []
        clientOfClientIdsTmp = client.getDependency()
        # if id separated by coma, make the list
        if clientOfClientIdsTmp.count(',') > 0:
          clientOfClientIds = clientOfClientIdsTmp.split(',')
        # if id separated by whitespace, make the list
        elif clientOfClientIdsTmp.count(' ') > 0:
          clientOfClientIds = clientOfClientIdsTmp.split(' ')
        # if id separated by ';', make the list
        elif clientOfClientIdsTmp.count(';') > 0:
          clientOfClientIds = clientOfClientIdsTmp.split(';')
        # sounds like only one id
        else:
          clientOfClientIds.append(clientOfClientIdsTmp)
        # remove whitespace characters
        i=0
        while i &lt; len(clientOfClientIds):
          clientOfClientIds[i] = clientOfClientIds[i].replace(' ','')
          i += 1
      </script>
      <!--== For each clientId, wait it has been completed ==-->
      <iterate in="clientOfClientIds" var="clientOfClientId">
        <sequence>
          <!--== Wait until clientOfClient is finished ==-->
          <!--== TBD : should not be durationTime but  ==-->
          <!--== "durationTime - time already runed"   ==-->
          <timer duration="'%ss' % durationTime">
            <loop until="clientOfClientId in finishedClients">
              <sequence>
                <call function="'sleep'">
                {
                  'location'             : location,
                  'sleepForMilliSeconds' : '3000',
                  'silentMode'           : FALSE ,
                  'fileFd'               : fileFd
                }
                </call>
              </sequence>
            </loop>
          </timer>
        </sequence>
      </iterate>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/phases/shared/dsadm.xml
New file
@@ -0,0 +1,971 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <function name="SetUpDsWithScript">
    <function-prolog>
      This function sets up a Directory Server using a script
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="STAF_REMOTE_HOSTNAME">
        <function-arg-description>
          Location of target host
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
      <function-arg-def name="dsPath" type="required">
        <function-arg-description>
          Pathname to installation root
        </function-arg-description>
        <function-arg-property name="type" value="filepath"/>
      </function-arg-def>
      <function-arg-def name="dsPort" type="optional">
        <function-arg-description>
          Directory server port number
        </function-arg-description>
        <function-arg-property name="type" value="Port number"/>
      </function-arg-def>
      <function-arg-def name="dsJmxPort" type="optional">
        <function-arg-description>
          Directory server JMX port number
        </function-arg-description>
        <function-arg-property name="type" value="Port number"/>
      </function-arg-def>
      <function-arg-def name="dsBaseDN" type="optional">
        <function-arg-description>
          Base DN (only single base DN supported).
        </function-arg-description>
        <function-arg-property name="type" value="DN"/>
      </function-arg-def>
      <function-arg-def name="dsBindDN" type="optional">
        <function-arg-description>
          Bind DN
        </function-arg-description>
        <function-arg-property name="type" value="DN"/>
      </function-arg-def>
      <function-arg-def name="dsBindPwd" type="optional">
        <function-arg-description>
          Bind password
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsBindPwdFile" type="optional">
        <function-arg-description>
          Bind password file
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="dsEnableWindowsService" type="optional">
        <function-arg-description>
          Enable as a Windows Service
        </function-arg-description>
        <function-arg-property name="type" value="boolean"/>
      </function-arg-def>
      <function-arg-def name="dsDoNotStart" type="optional">
        <function-arg-description>
          Do not start server after setup
        </function-arg-description>
        <function-arg-property name="type" value="boolean"/>
      </function-arg-def>
      <function-arg-def name="dsHelp" type="optional">
        <function-arg-description>
          Help option
        </function-arg-description>
        <function-arg-property name="help" value="option"/>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          output file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- Build the Command -->
      <script>
        STAFCmdParamsList=[]
        STAFCmdParams=''
        if dsPath:
          STAFCmd='%s/setup' % (dsPath)
          STAFCmdParamsList.append('--cli')
          STAFCmdParamsList.append('-n')
        if dsPort:
          STAFCmdParamsList.append('-p %s' % dsPort)
        if dsJmxPort:
          STAFCmdParamsList.append('-x %s' % dsJmxPort)
        if dsBaseDN:
          STAFCmdParamsList.append('-b "%s"' % dsBaseDN)
        if dsBindDN:
          STAFCmdParamsList.append('-D "%s"' % dsBindDN)
        if dsBindPwd:
          STAFCmdParamsList.append('-w "%s"' % dsBindPwd)
        if dsBindPwdFile:
          STAFCmdParamsList.append('-j "%s"' % dsBindPwdFile)
        if dsEnableWindowsService:
          STAFCmdParamsList.append('-e')
        if dsDoNotStart:
          STAFCmdParamsList.append('-O')
        if dsHelp:
          STAFCmdParamsList.append('-H')
        STAFCmdParams=' '.join(STAFCmdParamsList)
      </script>
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'SetUpDsWithScript',
        'fileFd'  : fileFd }
      </call>
      <call function="'writeMessage'">
        { 'content'  : 'Setup product : %s %s' % (STAFCmd, STAFCmdParams) ,
          'fileFd'   : fileFd }
      </call>
      <process name="'%s : Setup DS' % location">
        <location>'%s' % location</location>
        <command>'%s' % STAFCmd</command>
        <parms>'%s' % STAFCmdParams</parms>
        <workdir>'%s' % dsPath</workdir>
        <envs>
          ['PATH=/bin:/usr/bin:%s' % dsPath]
        </envs>
        <console use="'same'"/>
        <stderr mode="'stdout'"/>
        <returnstdout/>
      </process>
      <call function="'checkRC'">
        { 'returncode' : RC ,
          'result'     : STAXResult,
          'fileFd'     : fileFd }
      </call>
      <call function="'writeEndTagOperation'">{'fileFd' : fileFd}</call>
    </sequence>
  </function>
  <!-- This function starts DS using the start-ds script -->
  <function name="StartDsWithScript">
    <function-prolog>
      This function starts a Directory Server
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="'%s' % STAXServiceMachine">
        <function-arg-description>
          Location of target host
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
     <function-arg-def name="dsPath" type="required">
        <function-arg-description>
          Pathname to installation root
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
      <function-arg-def name="dsVersion" type="optional">
        <function-arg-description>
          Directory server version
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsSystemInfo" type="optional">
        <function-arg-description>
          Directory server system info
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsNoDetach" type="optional">
        <function-arg-description>
          Do not detach directory server from process
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsHelp" type="optional">
        <function-arg-description>
          Help option
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsBuildInfo" type="optional">
        <function-arg-description>
          Directory server build information
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          output file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- Build the Command -->
      <script>
        STAFCmdParamsList=[]
        STAFCmdParams=''
        if dsPath:
          dsBinPath='%s/bin' % (dsPath)
          STAFCmd='%s/start-ds' % (dsBinPath)
        if dsVersion:
          STAFCmdParamsList.append('-V')
        if dsSystemInfo:
          STAFCmdParamsList.append('-s')
        if dsNoDetach:
          STAFCmdParamsList.append('-N')
        if dsHelp:
          STAFCmdParamsList.append('-H')
        if dsBuildInfo:
          STAFCmdParamsList.append('-F')
        STAFCmdParams=' '.join(STAFCmdParamsList)
      </script>
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'StartDsWithScript',
        'fileFd'  : fileFd }
      </call>
      <call function="'writeMessage'">
      { 'fileFd'  : fileFd,
        'content' : '%s %s' % (STAFCmd, STAFCmdParams)
      }
      </call>
      <process name="'%s: Start DS' % location">
        <location>'%s' % location</location>
        <command>'%s' % STAFCmd</command>
        <parms>'%s' % STAFCmdParams</parms>
        <workdir>'%s' % dsBinPath</workdir>
        <envs>
          ['PATH=/bin:/usr/bin:%s' % dsBinPath]
        </envs>
        <console use="'same'"/>
        <stderr mode="'stdout'"/>
        <returnstdout/>
      </process>
      <script>
        startRC=RC
        startResult=STAXResult
      </script>
      <call function="'checkRC'">
        { 'returncode' : startRC ,
          'result'     : startResult,
          'fileFd'     : fileFd
        }
      </call>
      <call function="'writeEndTagOperation'">{'fileFd'  : fileFd }</call>
      <return>[startRC,startResult]</return>
    </sequence>
  </function>
  <!-- This function stops DS using the stop-ds script -->
  <function name="StopDsWithScript">
    <function-prolog>
      This function starts a Directory Server using the script
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="'%s' % STAXServiceMachine">
        <function-arg-description>
          Location of target host
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
     <function-arg-def name="dsPath" type="required">
        <function-arg-description>
          Pathname to installation root
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
      <function-arg-def name="dsHost" type="optional">
        <function-arg-description>
          Directory server hostname or IP address
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
      <function-arg-def name="dsPort" type="optional">
        <function-arg-description>
          Directory server port number
        </function-arg-description>
        <function-arg-property name="type" value="integer"/>
      </function-arg-def>
      <function-arg-def name="dsUseSSL" type="optional">
        <function-arg-description>
          Use SSL for secure communication with the server
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsUseStartTLS" type="optional">
        <function-arg-description>
          Use StartTLS for secure communication with the server
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsBindDN" type="optional">
        <function-arg-description>
          Bind DN
        </function-arg-description>
        <function-arg-property name="type" value="DN"/>
      </function-arg-def>
      <function-arg-def name="dsBindPwd" type="optional">
        <function-arg-description>
          Bind password
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsBindPwdFile" type="optional">
        <function-arg-description>
          Bind password file
        </function-arg-description>
        <function-arg-property name="type" value="filepath"/>
      </function-arg-def>
      <function-arg-def name="dsSaslOption" type="optional">
        <function-arg-description>
          SASL bind options
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsProxyAuthZID" type="optional">
        <function-arg-description>
          Use the proxied authorization control with the given authorization ID
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsStopReason" type="optional">
        <function-arg-description>
          Reason the server is being stopped or restarted
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsRestart" type="optional">
        <function-arg-description>
          Attempt to automatically restart the server once it has stopped
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsStopTime" type="optional">
        <function-arg-description>
          Time to begin the shutdown in YYYYMMDDhhmmss format (local time)
        </function-arg-description>
        <function-arg-property name="type" value="timestamp"/>
      </function-arg-def>
      <function-arg-def name="dsTrustAll" type="optional">
        <function-arg-description>
          Trust all server SSL certificates
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsKeyStoreFile" type="optional">
        <function-arg-description>
          Certificate keystore path
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="dsKeyStorePwd" type="optional">
        <function-arg-description>
          Certificate keystore PIN
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsKeyStorePwdFile" type="optional">
        <function-arg-description>
          Certificate keystore PIN file
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="dsTrustStoreFile" type="optional">
        <function-arg-description>
          Certificate trust store path
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="dsTrustStorePwd" type="optional">
        <function-arg-description>
          Certificate trust store PIN
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsTrustStorePwdFile" type="optional">
        <function-arg-description>
          Certificate trust store PIN file
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="dsHelp" type="optional">
        <function-arg-description>
          Help option
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="fileFd" type="optional" default="''">
        <function-arg-description>
          file descriptor to write message in if needed
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- Build the Command -->
      <script>
        STAFCmdParamsList=[]
        STAFCmdParams=''
        if dsPath:
          dsBinPath='%s/bin' % (dsPath)
          STAFCmd='%s/stop-ds' % (dsBinPath)
        if dsHost:
          STAFCmdParamsList.append('-h %s' % dsHost)
        if dsPort:
          STAFCmdParamsList.append('-p %s' % dsPort)
        if dsUseSSL:
          STAFCmdParamsList.append('-Z')
        if dsUseStartTLS:
          STAFCmdParamsList.append('-q')
        if dsBindDN:
          STAFCmdParamsList.append('-D "%s"' % dsBindDN)
        if dsBindPwd:
          STAFCmdParamsList.append('-w "%s"' % dsBindPwd)
        if dsBindPwdFile:
          STAFCmdParamsList.append('-j "%s"' % dsBindPwdFile)
        if dsSaslOption:
          STAFCmdParamsList.append('-o "%s"' % dsSaslOption)
        if dsProxyAuthZID:
          STAFCmdParamsList.append('-Y "%s"' % dsProxyAuthZID)
        if dsStopReason:
          STAFCmdParamsList.append('-r "%s"' % dsStopReason)
        if dsRestart:
          STAFCmdParamsList.append('-R')
        if dsStopTime:
          STAFCmdParamsList.append('-t "%s"' % dsStopTime)
        if dsTrustAll:
          STAFCmdParamsList.append('-X')
        if dsKeyStoreFile:
          STAFCmdParamsList.append('-K "%s"' % dsKeyStoreFile)
        if dsKeyStorePwd:
          STAFCmdParamsList.append('-W "%s"' % dsKeyStorePwd)
        if dsKeyStorePwdFile:
          STAFCmdParamsList.append('-u "%s"' % dsKeyStorePwdFile)
        if dsTrustStoreFile:
          STAFCmdParamsList.append('-P "%s"' % dsTrustStoreFile)
        if dsTrustStorePwd:
          STAFCmdParamsList.append('-T "%s"' % dsTrustStorePwd)
        if dsTrustStorePwdFile:
          STAFCmdParamsList.append('-U "%s"' % dsTrustStorePwdFile)
        if dsHelp:
          STAFCmdParamsList.append('-H')
        STAFCmdParams=' '.join(STAFCmdParamsList)
      </script>
      <!-- TBD : check if bin file exists -->
      <call function="'isFile'">
      {
        'location' : location,
        'fileName' : '%s' % STAFCmd
      }
      </call>
      <script>
        STAFCmdExist = STAXResult
      </script>
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'StopDsWithScript',
        'fileFd'  : fileFd }
      </call>
      <!-- if jarfile does not exist, build it, may have problem if several builds are run at the same time... -->
      <if expr="STAFCmdExist == TRUE">
        <sequence>
          <if expr="fileFd == ''">
            <sequence>
              <message>'%s : Stop instance if started' % dsHost</message>
              <message>'%s %s' % (STAFCmd, STAFCmdParams)</message>
            </sequence>
          <else>
            <sequence>
              <call function="'writeMessage'">
              { 'content' : 'Stop instance on %s' % dsHost,
                'fileFd'  : fileFd }
              </call>
              <call function="'writeMessage'">
              { 'content' : 'Run command : %s %s' % (STAFCmd,STAFCmdParams),
                'fileFd'  : fileFd }
              </call>
            </sequence>
          </else>
          </if>
          <process name="'%s: Stop DS' % location">
            <location>'%s' % (location)</location>
            <command>'%s' % (STAFCmd)</command>
            <parms>'%s' % (STAFCmdParams)</parms>
            <workdir>'%s' % dsBinPath</workdir>
            <envs>
              ['PATH=/bin:/usr/bin:%s' % dsBinPath]
            </envs>
            <stderr mode="'stdout'"/>
            <returnstdout/>
          </process>
          <script>
            stopRC=RC
            stopResult=STAXResult
          </script>
          <call function="'checkRC'">
            { 'returncode' : stopRC ,
              'result'     : stopResult,
              'fileFd'     : fileFd }
          </call>
        </sequence>
      <else>
          <if expr="fileFd == ''">
            <message>'WARNING : file does not exist on %s : %s/%s' % (location,dsBinPath,STAFCmd)</message>
          <else>
            <call function="'writeMessage'">
            { 'content' : 'WARNING : file does not exist on %s : %s/%s' % (location,dsBinPath,STAFCmd),
              'fileFd'  : fileFd }
            </call>
          </else>
          </if>
      </else>
      </if>
      <call function="'writeEndTagOperation'">{'fileFd'  : fileFd }</call>
      <return> [stopRC,stopResult]</return>
    </sequence>
  </function>
  <function name="makeLdif">
    <function-prolog>
      This function uses make-ldif to generate ldif file
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="'%s' % STAXServiceMachine">
        <function-arg-description>
          Location of target host
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="dsPath" type="required">
        <function-arg-description>
          Pathname to installation root
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="templateFile" type="required">
        <function-arg-description>
          template ldif file
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="ldifFile" type="required">
        <function-arg-description>
          ldif file to generate
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor to log information
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- Build the Command -->
      <script>
        STAFCmdParamsList=[]
        STAFCmdParams=''
        if dsPath:
          dsBinPath='%s/bin' % (dsPath)
          STAFCmd='%s/make-ldif' % (dsBinPath)
          STAFCmdParamsList.append('-t %s' % templateFile)
          STAFCmdParamsList.append('-o %s' % ldifFile)
        STAFCmdParams=' '.join(STAFCmdParamsList)
      </script>
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'makeLdif',
        'fileFd'  : fileFd }
      </call>
      <call function="'writeMessage'">
      { 'fileFd'  : fileFd,
        'content' : '%s %s' % (STAFCmd, STAFCmdParams)
      }
      </call>
      <process name="'Generate ldif'">
        <location>'%s' % location</location>
        <command>'%s' % STAFCmd</command>
        <parms>'%s' % STAFCmdParams</parms>
        <workdir>'%s' % dsBinPath</workdir>
        <envs>
          ['PATH=/bin:/usr/bin:%s' % dsBinPath]
        </envs>
        <stderr mode="'stdout'"/>
        <returnstdout/>
      </process>
      <call function="'checkRC'">
        { 'returncode' : RC ,
          'result'     : STAXResult,
          'fileFd'     : fileFd }
      </call>
      <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
    </sequence>
  </function>
  <!-- Import Function With Script-->
  <function name="ImportLdifWithScript">
    <function-prolog>
      This function performs an offline import of an ldif file using the script
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="'%s' % STAXServiceMachine">
        <function-arg-description>
          Location of target host
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
      <function-arg-def name="dsPath" type="required">
        <function-arg-description>
          Pathname to installation root
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
      <function-arg-def name="dsLdifFile" type="required">
        <function-arg-description>
          Path to the LDIF file to be imported
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="dsTemplateFile" type="optional">
        <function-arg-description>
          Path to a MakeLDIF template to use to generate the import data
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="dsAppend" type="optional">
        <function-arg-description>
          Append to an existing database rather than overwriting it
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsReplaceExisting" type="optional">
        <function-arg-description>
          Replace existing entries when appending to the database
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsBackEnd" type="optional" default="'%s' % DIRECTORY_INSTANCE_BE">
        <function-arg-description>
          Backend ID for the backend to import
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsBranchDN" type="optional">
        <function-arg-description>
          Base DN of a branch to include in the LDIF import
        </function-arg-description>
        <function-arg-property name="type" value="dn"/>
      </function-arg-def>
      <function-arg-def name="dsIncludeBranch" type="optional">
        <function-arg-description>
          Base DN of a branch to include in the LDIF import
        </function-arg-description>
        <function-arg-property name="type" value="dn"/>
      </function-arg-def>
      <function-arg-def name="dsExcludeBranch" type="optional">
        <function-arg-description>
          Base DN of a branch to exclude from the LDIF import
        </function-arg-description>
        <function-arg-property name="type" value="dn"/>
      </function-arg-def>
      <function-arg-def name="dsIncludeAttribute" type="optional">
        <function-arg-description>
          Attribute to include in the LDIF import
        </function-arg-description>
        <function-arg-property name="type" value="attribute"/>
      </function-arg-def>
      <function-arg-def name="dsExcludeAttribute" type="optional">
        <function-arg-description>
          Attribute to exclude in the LDIF import
        </function-arg-description>
        <function-arg-property name="type" value="attribute"/>
      </function-arg-def>
      <function-arg-def name="dsIncludeFilter" type="optional">
        <function-arg-description>
          Filter to identify entries to include in the LDIF import
        </function-arg-description>
        <function-arg-property name="type" value="filter"/>
      </function-arg-def>
      <function-arg-def name="dsExcludeFilter" type="optional">
        <function-arg-description>
          Filter to identify entries to exclude from the LDIF import
        </function-arg-description>
        <function-arg-property name="type" value="filter"/>
      </function-arg-def>
      <function-arg-def name="dsRejectFile" type="optional">
        <function-arg-description>
          Write rejected entries to the specified file
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="dsOverWriteRejects" type="optional">
        <function-arg-description>
          Overwrite an existing rejects file rather than appending to it
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsRandomSeed" type="optional">
        <function-arg-description>
          Seed for the MakeLDIF random number generator
        </function-arg-description>
        <function-arg-property name="type" value="seed"/>
      </function-arg-def>
      <function-arg-def name="dsSkipSchemaValidation" type="optional">
        <function-arg-description>
          Skip schema validation during the LDIF import
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsIsCompressed" type="optional">
        <function-arg-description>
          LDIF file is compressed
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsIsEncrypted" type="optional">
        <function-arg-description>
          LDIF file is encrypted
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsQuiet" type="optional">
        <function-arg-description>
          Use quiet mode (no output)
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsHelp" type="optional">
        <function-arg-description>
          Display usage information
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          output file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- Build the Command -->
      <script>
        STAFCmdParamsList=[]
        STAFCmdParams=''
        if dsPath:
          dsBinPath='%s/bin' % (dsPath)
          STAFCmd='%s/import-ldif' % (dsBinPath)
        if dsLdifFile:
          STAFCmdParamsList.append('-l %s' % dsLdifFile)
        if dsTemplateFile:
          STAFCmdParamsList.append('-t %s' % dsTemplateFile)
        if dsAppend:
          STAFCmdParamsList.append('-a')
        if dsReplaceExisting:
          STAFCmdParamsList.append('-r')
        if dsBackEnd:
          STAFCmdParamsList.append('-n %s' % dsBackEnd)
        if dsIncludeBranch:
          STAFCmdParamsList.append('-b %s' % dsIncludeBranch)
        if dsExcludeBranch:
          STAFCmdParamsList.append('-B %s' % dsExcludeBranch)
        if dsIncludeAttribute:
          STAFCmdParamsList.append('-i %s' % dsIncludeAttribute)
        if dsExcludeAttribute:
          STAFCmdParamsList.append('-e %s' % dsExcludeAttribute)
        if dsIncludeFilter:
          STAFCmdParamsList.append('-I %s' % dsIncludeFilter)
        if dsExcludeFilter:
          STAFCmdParamsList.append('-E %s' % dsExcludeFilter)
        if dsRejectFile:
          STAFCmdParamsList.append('-R %s' % dsRejectFile)
        if dsOverWriteRejects:
          STAFCmdParamsList.append('-O')
        if dsRandomSeed:
          STAFCmdParamsList.append('-S %s' % dsRandomSeed)
        if dsSkipSchemaValidation:
          STAFCmdParamsList.append('-s')
        if dsIsCompressed:
          STAFCmdParamsList.append('-c')
        if dsIsEncrypted:
          STAFCmdParamsList.append('-y')
        if dsQuiet:
          STAFCmdParamsList.append('-q')
        if dsHelp:
          STAFCmdParamsList.append('-H')
        STAFCmdParams=' '.join(STAFCmdParamsList)
      </script>
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'ImportLdifWithScript',
        'fileFd'  : fileFd }
      </call>
      <call function="'writeMessage'">
      { 'fileFd'  : fileFd,
        'content' : '%s %s' % (STAFCmd, STAFCmdParams)
      }
      </call>
      <process name="'Offline Import Script'">
        <location>'%s' % location</location>
        <command>'%s' % STAFCmd</command>
        <parms>'%s' % STAFCmdParams</parms>
        <workdir>'%s' % dsBinPath</workdir>
        <envs>
          ['PATH=/bin:/usr/bin:%s' % dsBinPath]
        </envs>
        <stderr mode="'stdout'"/>
        <returnstdout/>
      </process>
      <call function="'checkRC'">
        { 'returncode' : RC ,
          'result'     : STAXResult,
          'fileFd'     : fileFd }
      </call>
      <if expr="dsRejectFile">
        <sequence>
          <call function="'isEmptyFile'">
          { 'location' : location,
            'fileName' : dsRejectFile }
          </call>
          <script>
            fileEmpty = STAXResult
          </script>
          <!-- if rejected file exists, log an error -->
          <if expr="fileEmpty == FALSE">
            <sequence>
              <script>
                msg = 'ImportLdifWithScript rejected some entries,'
                msg = '%s check file on %s : %s' % (msg,location,dsRejectFile)
              </script>
              <message>'ERROR, %s' % msg</message>
              <call function="'checkRC'">
              {
                'returncode' : 999,
                'result'     : msg,
                'fileFd'     : fileFd
              }
              </call>
            </sequence>
          </if>
        </sequence>
      </if>
      <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/phases/shared/ldap.xml
New file
@@ -0,0 +1,906 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <!-- ************************************************************ -->
  <function name="isAlive" scope="local">
    <function-prolog>
      Checks that the ldap server is running
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="STAF_REMOTE_HOSTNAME">
        <function-arg-description>
          Location of target host
      </function-arg-description>
      <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
      <function-arg-def name="dsPath" type="required">
        <function-arg-description>
          Pathname to installation root
        </function-arg-description>
        <function-arg-property name="type" value="pathname"/>
      </function-arg-def>
      <function-arg-def name="noOfLoops" type="required">
        <function-arg-description>
          Number of iterations
        </function-arg-description>
        <function-arg-property name="type" value="integer"/>
      </function-arg-def>
      <function-arg-def name="noOfMilliSeconds" type="required">
        <function-arg-description>
          Number of seconds to wait between iterations
        </function-arg-description>
        <function-arg-property name="type" value="seconds"/>
      </function-arg-def>
      <function-arg-def name="dsInstanceHost" type="required">
        <function-arg-description>
          Directory server hostname or IP address
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
      <function-arg-def name="dsInstancePort" type="required">
        <function-arg-description>
          Directory server port number
        </function-arg-description>
        <function-arg-property name="type" value="Port number"/>
      </function-arg-def>
      <function-arg-def name="dsInstanceDn" type="optional" default="DIRECTORY_INSTANCE_DN">
        <function-arg-description>
          Bind DN
        </function-arg-description>
        <function-arg-property name="type" value="DN"/>
      </function-arg-def>
      <function-arg-def name="dsInstancePswd" type="optional" default="DIRECTORY_INSTANCE_PSWD">
        <function-arg-description>
          Bind password
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          Name of output file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- Local variables -->
      <script>
        mylocation=location
        mypath=dsPath
        myhost=dsInstanceHost
        myport=dsInstancePort
        mydn=dsInstanceDn
        mypswd=dsInstancePswd
      </script>
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'isAlive',
        'fileFd'  : fileFd }
      </call>
      <call function="'writeMessage'">
      { 'fileFd'  : fileFd,
        'content' : 'Check if server %s:%s is alive' % (myhost,myport)
      }
      </call>
      <script>ldapRC=9999</script>
      <loop from="1" to="noOfLoops" while="ldapRC != 0">
        <sequence>
          <call function="'ldapSearch'">
            { 'location'       : mylocation,
              'dsPath'         : mypath,
              'dsInstanceHost' : myhost,
              'dsInstancePort' : myport,
              'dsInstanceDn'   : mydn,
              'dsInstancePswd' : mypswd,
              'dsScope'        : 'base',
              'dsBaseDN'       : 'cn=config',
              'dsFilter'       : 'objectclass=*',
              'dsAttributes'   : 'dn',
              'expectedRC'     : 'noCheck',
              'fileFd'         : fileFd
            }
          </call>
          <script>
            ldapRC=RC
            ldapReason=STAXResult
          </script>
          <call function="'sleep'">
            {
              'sleepForMilliSeconds'  : noOfMilliSeconds,
              'silentMode' : 'TRUE',
              'fileFd' : fileFd
            }
          </call>
        </sequence>
      </loop>
      <if expr="ldapRC == 0">
        <sequence>
          <call function="'writeMessage'">
          { 'fileFd'  : fileFd,
            'content' : 'Server is alive'
          }
          </call>
          <script>returnValue = TRUE</script>
        </sequence>
      <else>
        <sequence>
          <call function="'writeMessage'">
          { 'fileFd'  : fileFd,
            'content' : 'server is not alive'
          }
          </call>
          <script>returnValue = FALSE</script>
        </sequence>
      </else>
      </if>
      <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
      <return>returnValue</return>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="verifyTrees">
    <function-prolog>
      This function verifies that the tree of an instance belonging to an instances list
      (ie instance[n]) is synchronized with instance[n+1]
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="STAF_REMOTE_HOSTNAME">
        <function-arg-description>
          Location of target host
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="instance" type="required">
        <function-arg-description>
          Server that should be taken as reference.
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="instances" type="required">
        <function-arg-description>
          List of the instances objectclass to verify against the instance
          instance must belong to this list
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="suffixDn" type="required">
        <function-arg-description>
          Suffix of the tree to verify.
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="filePrefix" type="optional" default="verdict">
        <function-arg-description>
          Prefix for tmp files
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          Name of output file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- == Get instance2 (which is instance index + 1) == -->
      <script>
        instance2 = NOT_DEFINED
        i = 0
        found = FALSE
        # get the real instance reference from instances list
        for cInstance in instances:
          if cInstance.getName() == instance.getName():
            instance = cInstance
            found = TRUE
            break
          i += 1
        if found == TRUE:
          instanceIndex = instances.index(instance)
          # if len =1, only one instance, no need to verify tree
          if len(instances) > 1:
            lastIndex = len(instances) - 1
            # if instanceIndex == lastIndex, all previous instances
            # have been checked, no need to test this instance tree
            if instanceIndex != lastIndex:
              instance2 = instances[instanceIndex + 1]
      </script>
      <if expr="instance2 != NOT_DEFINED">
        <sequence>
          <call function="'writeStartTagStep'">
          { 'tagName' : 'verifyTrees',
            'fileFd'  : fileFd }
          </call>
          <script>
            myRC = 0
            dsPath = instance.getInstallDir()
            failedServers = []
            failingServerList = ''
            referenceServerPath = instance.getInstallDir()
            referenceTree = '%s/%s_%s_referenceTree.ldif' % (LOG_TMP_DIR,filePrefix,instance.getName()),
            sampleTree = '%s/%s_%s_sampleTree.ldif' % (LOG_TMP_DIR,filePrefix,instance.getName()),
            treeDiffs = '%s/%s_%s_treeDiffs.ldif' % (LOG_TMP_DIR,filePrefix,instance.getName())
            dsAttributes = 'dn postalAddress postalCode description \
    uid employeeNumber initials givenName pager mobile \
    cn sn telephoneNumber street homePhone l mail st'
          </script>
          <call function="'writeMessage'">
          { 'fileFd'  : fileFd,
            'content' : 'Verify tree %s taking %s as reference.' % (suffixDn, referenceServerPath)
          }
          </call>
          <!-- == Retrieve the tree from the reference server == -->
          <call function="'ldapSearch'">
            { 'location'       : location,
              'dsPath'         : dsPath,
              'dsInstanceHost' : instance.getHost(),
              'dsInstancePort' : instance.getLDAPPort(),
              'dsInstanceDn'   : DIRECTORY_INSTANCE_DN,
              'dsInstancePswd' : DIRECTORY_INSTANCE_PSWD,
              'dsBaseDN'       : suffixDn,
              'dsFilter'       : 'objectclass=*',
              'dsAttributes'   : dsAttributes,
              'outputFile'     : referenceTree,
              'fileFd'         : fileFd
            }
          </call>
          <if expr="RC != 0">
            <!-- == If the reference tree could not be retrieved, return an error == -->
            <sequence>
              <call function="'writeEndTagStep'">{ 'fileFd' : fileFd}</call>
              <return> [1, None] </return>
            </sequence>
          </if>
          <!-- Retrieve the same tree for instance2 -->
          <call function="'ldapSearch'">
            { 'location'       : location,
              'dsPath'         : dsPath,
              'dsInstanceHost' : instance2.getHost(),
              'dsInstancePort' : instance2.getLDAPPort(),
              'dsInstanceDn'   : DIRECTORY_INSTANCE_DN,
              'dsInstancePswd' : DIRECTORY_INSTANCE_PSWD,
              'dsBaseDN'       : suffixDn,
              'dsFilter'       : 'objectclass=*',
              'dsAttributes'   : dsAttributes,
              'outputFile'     : sampleTree,
              'fileFd'         : fileFd
            }
          </call>
          <script>
            ldapSearchRC = STAXResult[0]
          </script>
          <if expr="ldapSearchRC == 0">
            <sequence>
              <!-- == Check if file is empty == -->
              <call function="'isEmptyFile'">
                { 'location'   : location,
                  'fileName'   : sampleTree }
              </call>
              <script>
                myRC = STAXResult
              </script>
              <if expr="myRC == TRUE">
                <message>'WARNING!! : file emtpy %s' % sampleTree </message>
              </if>
              <!-- == Compare this tree to the reference one == -->
              <call function="'ldifDiff'">
                { 'location'   : location,
                  'dsPath'     : dsPath,
                  'sourceLdif' : sampleTree,
                  'targetLdif' : referenceTree,
                  'outputLdif' : treeDiffs,
                  'fileFd'     : fileFd
                }
              </call>
              <script>
                if STAXResult != 0 :
                  failedServers.append('%s:%s' % (instance2.getHost(), instance2.getLDAPPort()))
              </script>
            </sequence>
            <else>
              <script>
                failedServers.append('%s:%s' % (instance2.getHost(), instance2.getLDAPPort()))
              </script>
            </else>
          </if>
          <!-- == Compare both ldapsearch results and set the verdict == -->
          <if expr="len(failedServers) > 0">
            <!-- If at least one server failed to successfully compare to the reference tree, -->
            <!-- return an error, along with the list of the servers that failed to do so     -->
            <script>
              myRC = FALSE
              comma = ','
              messageInfo = 'List of non-synchronized servers (tree verify FAILED): %s' % comma.join(failedServers)
            </script>
          <else>
            <script>
              myRC = TRUE
              messageInfo = 'SUCCESS : All servers synchronized'
            </script>
          </else>
          </if>
          <call function="'checkRC'">
            { 'returncode' : myRC,
              'result'     : messageInfo,
              'fileFd'     : fileFd
            }
          </call>
          <call function="'writeEndTagStep'">{ 'fileFd' : fileFd}</call>
          <return>[myRC, failedServers]</return>
        </sequence>
      </if>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="ldapSearch">
    <function-prolog>
      This function performs an ldapsearch
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="STAF_REMOTE_HOSTNAME">
        <function-arg-description>
          Location of target host
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
      <function-arg-def name="dsPath" type="required">
        <function-arg-description>
          Pathname to installation root
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
      <function-arg-def name="dsDereferencePolicy" type="optional">
        <function-arg-description>
          Specifies dereference alias policy
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsTypesOnly" type="optional">
        <function-arg-description>
          Specifies to only include attribute type names
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsAssertionFilter" type="optional">
        <function-arg-description>
          Use the LDAP assertion control with the provided filter
        </function-arg-description>
        <function-arg-property name="type" value="filter"/>
      </function-arg-def>
      <function-arg-def name="dsContinueOnError" type="optional">
        <function-arg-description>
          Continue processing even if there are errors
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsPersistentSearch" type="optional">
        <function-arg-description>
          Use the persistent search control
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsCountEntries" type="optional">
        <function-arg-description>
          Count the number of entries returned by the server
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsReportAuthzID" type="optional">
        <function-arg-description>
          Use the authorization identity control
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsFilename" type="optional">
        <function-arg-description>
          File containing a list of search filter strings
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="dsHelp" type="optional">
        <function-arg-description>
          Display this usage information
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsEncoding" type="optional">
        <function-arg-description>
          Use the specified character set for command-line input
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsBindPasswordFile" type="optional">
        <function-arg-description>
          Bind password file
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="dsControl" type="optional">
        <function-arg-description>
          Use a request control with the provided information
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsKeyStorePath" type="optional">
        <function-arg-description>
          Certificate keystore path
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="dsKeyStorePasswordFile" type="optional">
        <function-arg-description>
          Certificate keystore PIN file
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="dsKeyStorePassword" type="optional">
        <function-arg-description>
          Certificate keystore PIN
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsTimeLimit" type="optional">
        <function-arg-description>
          Maximum length of time in seconds to allow for the search
        </function-arg-description>
        <function-arg-property name="type" value="integer"/>
      </function-arg-def>
      <function-arg-def name="dsMatchedValuesFilter" type="optional">
        <function-arg-description>
          Use the LDAP matched values control with the provided filter
        </function-arg-description>
        <function-arg-property name="type" value="filter"/>
      </function-arg-def>
      <function-arg-def name="dsDryRun" type="optional">
        <function-arg-description>
          Show what would be done but do not perform any operation
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsSaslOption" type="optional">
        <function-arg-description>
          SASL bind options
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsTrustStorePath" type="optional">
        <function-arg-description>
          Certificate trust store path
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="dsTrustStorePassword" type="optional">
        <function-arg-description>
          Certificate trust store PIN
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsTrustStorePasswordFile" type="optional">
        <function-arg-description>
          Certificate trust store PIN file
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="dsUseStartTLS" type="optional">
        <function-arg-description>
          Use StartTLS to secure communication with the server
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsUseSASLExternal" type="optional">
        <function-arg-description>
          Use the SASL EXTERNAL authentication mechanism
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsUseSSL" type="optional">
        <function-arg-description>
          Use SSL for secure communication with the server
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsTrustAll" type="optional">
        <function-arg-description>
          Trust all server SSL certificates
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsCertNickname" type="optional">
        <function-arg-description>
          Nickname of certificate for SSL client authentication
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsProxyAs" type="optional">
        <function-arg-description>
          Use the proxied authorization control with the given authorization ID
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsUsePasswordPolicyControl" type="optional">
        <function-arg-description>
          Use the password policy request control
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsSimplePageSize" type="optional">
        <function-arg-description>
          Use the simple paged results control with the given page size
        </function-arg-description>
        <function-arg-property name="type" value="integer"/>
      </function-arg-def>
      <function-arg-def name="dsSortOrder" type="optional">
        <function-arg-description>
          Sort the results using the provided sort order
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsVirtualListView" type="optional">
        <function-arg-description>
          Use the virtual list view control to retrieve the specified results page
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsGetEffectiveRightsAuthzid" type="optional">
        <function-arg-description>
          Use geteffectiverights control with the provided authzid
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsGetEffectiveRightsAttribute" type="optional">
        <function-arg-description>
          Specifies geteffectiverights control specific attribute list
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsVersion" type="optional">
        <function-arg-description>
          LDAP protocol version number
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsSizeLimit" type="optional">
        <function-arg-description>
          Maximum number of entries to return from the search
        </function-arg-description>
        <function-arg-property name="type" value="integer"/>
      </function-arg-def>
      <function-arg-def name="dsDontWrap" type="optional">
        <function-arg-description>
          Do not wrap long lines
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsVerbose" type="optional">
        <function-arg-description>
          Use verbose mode
        </function-arg-description>
        <function-arg-property name="type" value="option"/>
      </function-arg-def>
      <function-arg-def name="dsInstanceHost" type="optional">
        <function-arg-description>
          Directory Server Host Name
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
      <function-arg-def name="dsInstancePort" type="optional">
        <function-arg-description>
          Directory Server Port Number
        </function-arg-description>
        <function-arg-property name="type" value="integer"/>
      </function-arg-def>
      <function-arg-def name="dsInstanceDn" type="optional">
        <function-arg-description>
          Directory Server Manager DN
        </function-arg-description>
        <function-arg-property name="type" value="dn"/>
      </function-arg-def>
      <function-arg-def name="dsInstancePswd" type="optional">
        <function-arg-description>
          Directory Server Manager Password
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsScope" type="optional">
        <function-arg-description>
          The scope of the search operation
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="dsBaseDN" type="optional">
        <function-arg-description>
          The baseDN for the search operation
        </function-arg-description>
        <function-arg-property name="type" value="dn"/>
      </function-arg-def>
      <function-arg-def name="dsFilter" type="optional">
        <function-arg-description>
          The filter for the search operation
        </function-arg-description>
        <function-arg-property name="type" value="filter"/>
      </function-arg-def>
      <function-arg-def name="dsAttributes" type="optional">
        <function-arg-description>
          Only return these attributes
        </function-arg-description>
        <function-arg-property name="type" value="string"/>
      </function-arg-def>
      <function-arg-def name="outputFile" type="optional">
        <function-arg-description>
          Output file containing the search result in ldif format.
        </function-arg-description>
        <function-arg-property name="type" value="filepath"/>
      </function-arg-def>
      <function-arg-def name="expectedRC" type="optional" default="0">
        <function-arg-description>
          Expected return code value. Default value is 0. Wildcard 'noCheck' to not check the RC
        </function-arg-description>
        <function-arg-property name="type" value="integer"/>
        </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          Name of output file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- Build the Command -->
      <script>
        STAFCmdParamsList=[]
        STAFCmdParams=''
        if dsPath:
          dsBinPath='%s/bin' % (dsPath)
          STAFCmd='%s/ldapsearch' % (dsBinPath)
        if dsInstanceHost:
          STAFCmdParamsList.append('-h %s' % dsInstanceHost)
        if dsInstanceDn:
          STAFCmdParamsList.append('-D "%s"' % dsInstanceDn)
        if dsInstancePswd:
          STAFCmdParamsList.append('-w %s' % dsInstancePswd)
        if dsScope:
          STAFCmdParamsList.append('-s %s' % dsScope)
        if dsDereferencePolicy:
          STAFCmdParamsList.append('-a %s' % dsDereferencePolicy)
        if dsTypesOnly:
          STAFCmdParamsList.append('-A')
        if dsAssertionFilter:
          STAFCmdParamsList.append('--assertionFilter "%s"' % dsAssertionFilter)
        if dsBaseDN:
          STAFCmdParamsList.append('-b "%s"' % dsBaseDN)
        if dsContinueOnError:
          STAFCmdParamsList.append('-c')
        if dsPersistentSearch:
          STAFCmdParamsList.append('-C %s' % dsPersistentSearch)
        if dsCountEntries:
          STAFCmdParamsList.append('--countEntries')
        if dsGetEffectiveRightsAttribute:
          for attribute in dsGetEffectiveRightsAttribute:
            STAFCmdParamsList.append('-e %s' % attribute)
        if dsReportAuthzID:
          STAFCmdParamsList.append('-E')
        if dsFilename:
          STAFCmdParamsList.append('-f %s' % dsFilename)
        if dsGetEffectiveRightsAuthzid:
          STAFCmdParamsList.append('-g %s' % dsGetEffectiveRightsAuthzid)
        if dsVirtualListView:
          STAFCmdParamsList.append('-G %s' % dsVirtualListView)
        if dsHelp:
          STAFCmdParamsList.append('-H')
        if dsEncoding:
          STAFCmdParamsList.append('-i %s' % dsEncoding)
        if dsBindPasswordFile:
          STAFCmdParamsList.append('-j %s' % dsBindPasswordFile)
        if dsControl:
          STAFCmdParamsList.append('-J %s' % dsControl)
        if dsKeyStorePath:
          STAFCmdParamsList.append('-K %s' % dsKeyStorePath)
        if dsTimeLimit:
          STAFCmdParamsList.append('-l %s' % dsTimeLimit)
        if dsMatchedValuesFilter:
          STAFCmdParamsList.append('--matchedValuesFilter "%s"' % dsMatchedValuesFilter)
        if dsDryRun:
          STAFCmdParamsList.append('-n')
        if dsCertNickname:
          STAFCmdParamsList.append('-N %s' % dsCertNickname)
        if dsSaslOption:
          STAFCmdParamsList.append('-o %s' % dsSaslOption)
        if dsInstancePort:
          STAFCmdParamsList.append('-p %s' % dsInstancePort)
        if dsTrustStorePath:
          STAFCmdParamsList.append('-P %s' % dsTrustStorePath)
        if dsUseStartTLS:
          STAFCmdParamsList.append('-q')
        if dsUseSASLExternal:
          STAFCmdParamsList.append('-r')
        if dsSimplePageSize:
          STAFCmdParamsList.append('--simplePageSize %s' % dsSimplePageSize)
        if dsSortOrder:
          STAFCmdParamsList.append('-S %s' % dsSortOrder)
        if dsDontWrap:
          STAFCmdParamsList.append('-T')
        if dsTrustStorePassword:
          STAFCmdParamsList.append('--trustStorePassword %s' % dsTrustStorePassword)
        if dsTrustStorePasswordFile:
          STAFCmdParamsList.append('-U %s' % dsTrustStorePasswordFile)
        if dsKeyStorePasswordFile:
          STAFCmdParamsList.append('-u %s' % dsKeyStorePasswordFile)
        if dsUsePasswordPolicyControl:
          STAFCmdParamsList.append('--usePasswordPolicyControl')
        if dsVersion:
          STAFCmdParamsList.append('-V %s' % dsVersion)
        if dsVerbose:
          STAFCmdParamsList.append('-v')
        if dsKeyStorePassword:
          STAFCmdParamsList.append('-W %s' % dsKeyStorePassword)
        if dsTrustAll:
          STAFCmdParamsList.append('-X')
        if dsProxyAs:
          STAFCmdParamsList.append('-Y "%s"' % dsProxyAs)
        if dsUseSSL:
          STAFCmdParamsList.append('-Z')
        if dsSizeLimit:
          STAFCmdParamsList.append('-z %s' % dsSizeLimit)
        if dsFilter:
          STAFCmdParamsList.append('"%s"' % dsFilter)
        if dsAttributes:
          STAFCmdParamsList.append('%s' % dsAttributes)
        STAFCmdParams=' '.join(STAFCmdParamsList)
      </script>
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'ldapSearch',
        'fileFd'  : fileFd }
      </call>
      <call function="'writeMessage'">
      { 'fileFd'  : fileFd,
        'content' : '%s %s' % (STAFCmd, STAFCmdParams)
      }
      </call>
      <process name="'LDAP Search'">
        <location>'%s' % location</location>
        <command>'%s' % STAFCmd</command>
        <parms>'%s' % STAFCmdParams</parms>
        <workdir>'%s' % dsBinPath</workdir>
        <envs>
          ['PATH=/bin:/usr/bin:%s' % dsBinPath]
        </envs>
        <stdout if="outputFile != None" mode="'replace'">'%s' % outputFile</stdout>
        <stderr mode="'stdout'"/>
        <returnstdout/>
      </process>
      <script>
        STAXCode=RC
        STAXReason=STAXResult
      </script>
      <if expr="expectedRC != 'noCheck'">
        <call function="'checkRC'">
          { 'returncode' : STAXCode,
            'result'     : STAXReason,
            'fileFd'     : fileFd }
        </call>
      </if>
      <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
      <return>
        [STAXCode,STAXReason]
      </return>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/phases/shared/signals.xml
New file
@@ -0,0 +1,76 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <defaultcall function="signals" />
  <function name="signals">
    <function-prolog>
      This function contains all signal related functions
    </function-prolog>
    <function-no-args/>
    <sequence>
      <!-- Signal variables  -->
      <script>
        SignalRaised=''
      </script>
      <!-- Redefine the default signal handlers-->
      <call function="'OverideDefaultSignals'"/>
    </sequence>
  </function>
  <function name="OverideDefaultSignals">
    <function-prolog>
      This function overides the default STAX signal handlers
    </function-prolog>
    <function-no-args/>
    <!-- STAXPythonEvaluationError signal -->
    <signalhandler signal="'STAXPythonEvaluationError'">
      <sequence>
        <log level="'error'"  message="1">
          ('STAXPythonEvaluationError signal raised. ' + 'Continuing job. %s' % (STAXPythonEvalMsg))
        </log>
        <script>
          SignalRaised='STAXPythonEvaluationError'
        </script>
        <message>'SignalRaised = %s' % SignalRaised</message>
      </sequence>
    </signalhandler>
  </function>
</stax>
opends/tests/system-tests/phases/shared/stafcmd.xml
New file
@@ -0,0 +1,514 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <function name="copyFile">
    <function-prolog>
      This function copies a source file to destination file to host
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="'%s' % STAXServiceMachine">
        <function-arg-description>
          Location of target host
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
      <function-arg-def name="remoteHost" type="optional" default="'%s' % STAXServiceMachine">
        <function-arg-description>
          The name of remote host (default localhost)
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
      <function-arg-def name="srcFile" type="required">
        <function-arg-description>
          The name of the source fule
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="destFile" type="optional" default="NOT_DEFINED">
        <function-arg-description>
          The name of the destination fule
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="destDir" type="optional" default="NOT_DEFINED">
        <function-arg-description>
          The name of the destination fule
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor to write message in
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'copyFile',
        'fileFd'  : fileFd }
      </call>
      <call function="'writeMessage'">
       { 'content'  : 'Copy file(s) %s to %s from machine %s to %s' % (srcFile,destFile,location,remoteHost),
         'fileFd'   : fileFd }
      </call>
      <if expr="destFile != NOT_DEFINED">
        <stafcmd name="'STAF Command: Copy File'">
          <location>'%s' % location</location>
          <service>'fs'</service>
          <request>'COPY FILE %s TOFILE %s TOMACHINE %s' % (srcFile,destFile,remoteHost) </request>
        </stafcmd>
      <elseif expr="destDir != NOT_DEFINED">
        <stafcmd name="'STAF Command: Copy File'">
          <location>'%s' % location</location>
          <service>'fs'</service>
          <request>'COPY FILE %s TODIRECTORY %s TOMACHINE %s' % (srcFile,destDir,remoteHost) </request>
        </stafcmd>
      </elseif>
      <else>
        <sequence>
          <message>'ERROR copyFile() destFile or destDir must be specified'</message>
          <call function="'writeMessage'">
           { 'content'  : 'ERROR copyFile() destFile or destDir must be specified',
             'fileFd'   : fileFd }
          </call>
          <script>ERR_NUM[0] += 1</script>
        </sequence>
      </else>
      </if>
      <script>
        cmdRC=RC
        cmdResult=STAFResult
      </script>
      <call function="'checkRC'">
        { 'returncode' : cmdRC ,
          'result'     : cmdResult,
          'fileFd'     : fileFd }
      </call>
      <call function="'writeEndTagOperation'">{'fileFd' : fileFd}</call>
      <return>[cmdRC,cmdResult]</return>
    </sequence>
  </function>
  <function name="copyFolder">
    <function-prolog>
      This function copy directory through the network
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="'%s' % STAXServiceMachine">
        <function-arg-description>
          Location of target host
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
      <function-arg-def name="fromDirectory" type="required">
        <function-arg-description>
          directory to copy
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="remoteHost" type="required">
        <function-arg-description>
          host target where directory will be copied
        </function-arg-description>
        <function-arg-property name="type" value="filepath"/>
      </function-arg-def>
      <function-arg-def name="toDirectory" type="required">
        <function-arg-description>
          Directory target
        </function-arg-description>
        <function-arg-property name="type" value="filepath"/>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor to write message in
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'copyFolder',
        'fileFd'  : fileFd }
      </call>
      <call function="'writeMessage'">
        { 'content'  : 'Copy directory %s FROM machine %s TO machine %s into %s' % (fromDirectory,location,remoteHost,toDirectory),
          'fileFd'   : fileFd }
      </call>
      <if expr="remoteHost == STAXServiceMachine and fromDirectory == toDirectory">
        <sequence>
          <call function="'writeMessage'">
          {
            'content' : 'SKIP : same directory %s, same host %s' % \
                        (remoteHost,fromDirectory),
            'fileFd'  : fileFd
          }
          </call>
        </sequence>
      <else>
        <sequence>
          <stafcmd name="'STAF Command: copy directory'">
            <location>'%s' % location</location>
            <service>'fs'</service>
            <request>
                'COPY DIRECTORY %s TODIRECTORY %s TOMACHINE %s RECURSE CASEINSENSITIVE' % (fromDirectory,toDirectory,remoteHost)
            </request>
          </stafcmd>
          <script>
            cmdRC=RC
            cmdResult=STAFResult
          </script>
          <call function="'checkRC'">
            { 'returncode' : cmdRC ,
              'result'     : cmdResult,
              'fileFd'     : fileFd }
          </call>
        </sequence>
      </else>
      </if>
      <call function="'writeEndTagOperation'">{'fileFd' : fileFd}</call>
      <return>cmdRC</return>
    </sequence>
  </function>
  <function name="unZipFile">
    <function-prolog>
      This function unzips a compressed zip archive
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="'%s' % STAXServiceMachine">
        <function-arg-description>
          Location of target host
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
      <function-arg-def name="zipfile" type="required">
        <function-arg-description>
          Name of the file to place zip file contents
        </function-arg-description>
        <function-arg-property name="type" value="filename"/>
      </function-arg-def>
      <function-arg-def name="unzipdir" type="required">
        <function-arg-description>
          Name of destination folder to place zip file contents
        </function-arg-description>
        <function-arg-property name="type" value="filepath"/>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor to write message in
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'Unzip',
        'fileFd'  : fileFd }
      </call>
        <call function="'writeMessage'">
          { 'content'  : 'Unzip %s under %s' % (zipfile,unzipdir),
            'fileFd'   : fileFd }
        </call>
        <stafcmd name="'STAF Command: Unzip File'">
          <location>'%s' % location</location>
          <service>'zip'</service>
          <request>
              'UNZIP ZIPFILE %s TODIRECTORY %s RESTOREPERMISSION REPLACE' % (zipfile,unzipdir)
          </request>
        </stafcmd>
        <script>
          cmdRC=RC
          cmdResult=STAFResult
        </script>
        <call function="'checkRC'">
          { 'returncode' : cmdRC ,
            'result'     : cmdResult,
            'fileFd'     : fileFd }
        </call>
      <call function="'writeEndTagOperation'">{'fileFd' : fileFd}</call>
      <return>cmdRC</return>
    </sequence>
  </function>
  <function name="isFile">
    <function-prolog>
        This function returns TRUE if file exist, else FALSE
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="'%s' % STAXServiceMachine">
        <function-arg-description>
          Location of target host
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileName" type="required">
        <function-arg-description>
          Name of file
        </function-arg-description>
        </function-arg-def>
    </function-map-args>
    <sequence>
      <process name="'do ls'">
        <location>'%s' % location</location>
        <command>'ls'</command>
        <parms>'%s' % fileName</parms>
        <workdir>'/'</workdir>
        <envs>['PATH=/bin:/usr/bin']</envs>
        <stderr mode="'stdout'"/>
        <returnstdout/>
      </process>
      <script>
        lsResult = STAXResult[0][1]
        lsResult = lsResult.lower()
        indexResult = lsResult.find('no such file')
        if indexResult == -1:
          bExist = TRUE
        else:
          bExist = FALSE
      </script>
      <return>
        bExist
      </return>
    </sequence>
  </function>
  <function name="isEmptyFile">
    <function-prolog>
        This function returns TRUE if file is empty, else FALSE
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="'%s' % STAXServiceMachine">
        <function-arg-description>
          Location of target host
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileName" type="required">
        <function-arg-description>
          Name of the file
        </function-arg-description>
        </function-arg-def>
    </function-map-args>
    <sequence>
      <script>
        cmdResult=''
      </script>
      <stafcmd name="'STAF Command: Get File'">
        <location>'%s' % location</location>
        <service>'fs'</service>
        <request>'GET FILE %s TEXT' % fileName</request>
      </stafcmd>
      <script>
        cmdRC=RC
        cmdResult=STAFResult
      </script>
      <if expr="cmdRC != 0">
        <return>TRUE</return>
      <else>
        <if expr="cmdResult == ''">
          <return>TRUE</return>
        <else>
          <return>FALSE</return>
        </else>
        </if>
      </else>
      </if>
    </sequence>
  </function>
  <function name="deleteFolder">
    <function-prolog>
        This function recursively deletes a folder
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="'%s' % STAXServiceMachine">
        <function-arg-description>
          Location of target host
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
      <function-arg-def name="foldername" type="required">
        <function-arg-description>
          Name of folder to be deleted
        </function-arg-description>
        <function-arg-property name="type" value="filepath"/>
      </function-arg-def>
      <function-arg-def name="expectedRC" type="optional" default="[0]">
        <function-arg-description>
          expected return code
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <if expr="fileFd != NO_FILE">
        <call function="'writeStartTagOperation'">
        { 'tagName' : 'deleteFolder',
          'fileFd'  : fileFd }
        </call>
      <else>
        <message>'Delete folder on %s : %s' % (location,foldername)</message>
      </else>
      </if>
      <stafcmd name="'STAF Command: Get Folder Attributes'">
        <location>'%s' % location</location>
        <service>'fs'</service>
        <request>'GET ENTRY %s TYPE' % foldername</request>
      </stafcmd>
      <if expr="RC == 48">
        <sequence>
          <if expr="fileFd != NO_FILE">
            <call function="'writeMessage'">
            { 'content' : 'Folder does not exist, do not delete it.',
              'fileFd'  : fileFd }
            </call>
          </if>
          <return>0</return>
        </sequence>
        <else>
          <if expr="fileFd != NO_FILE">
            <call function="'writeMessage'">
            { 'content' : 'Folder exists, will delete it : %s' % foldername,
              'fileFd'  : fileFd }
            </call>
          </if>
        </else>
      </if>
      <stafcmd name="'STAF Command: Recursively Delete Folder'">
        <location>'%s' % location</location>
        <service>'fs'</service>
        <request>
          'DELETE ENTRY %s RECURSE IGNOREERRORS CONFIRM' % (foldername)
        </request>
      </stafcmd>
      <script>
        cmdRC=RC
        cmdResult=STAFResult
      </script>
      <call function="'checkRC'">
          { 'returncode' : cmdRC ,
            'result'     : cmdResult,
            'expected'   : expectedRC,
            'fileFd'     : fileFd }
      </call>
      <call function="'writeEndTagOperation'">{'fileFd' : fileFd}</call>
      <return>cmdRC</return>
      </sequence>
    </function>
    <function name="createFolder">
    <function-prolog>
        This function creates a folder
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="STAXServiceMachine">
        <function-arg-description>
          Location of target host
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="foldername" type="required">
        <function-arg-description>
          Name of file to be created
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor, wildcard : NO_FILE to not write information in a file
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'createFolder',
        'fileFd'  : fileFd }
      </call>
      <call function="'writeMessage'">
        {
          'content'  : 'Create directory %s on %s' % (foldername,location) ,
          'fileFd'   : fileFd
        }
      </call>
      <stafcmd name="'STAF Command: Create Folder'">
        <location>'%s' % location</location>
        <service>'fs'</service>
        <request>
          'CREATE DIRECTORY %s FULLPATH' % foldername
        </request>
      </stafcmd>
      <script>
        cmdRC=RC
        cmdResult=STAFResult
      </script>
       <call function="'checkRC'">
          { 'returncode' : cmdRC ,
            'result'     : cmdResult ,
            'fileFd'     : fileFd
          }
      </call>
      <call function="'writeEndTagOperation'">{'fileFd' : fileFd}</call>
      <return>cmdRC</return>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/phases/shared/staxcmd.xml
New file
@@ -0,0 +1,61 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <function name="queryTestcase">
    <function-prolog>Queries the current testcase</function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="'%s' % STAXServiceMachine">
        <function-arg-description>
          Location of target host
        </function-arg-description>
        <function-arg-property name="type" value="hostname" />
      </function-arg-def>
    </function-map-args>
    <sequence>
      <script>
        STAXRequest='QUERY JOB %s TESTCASE "%s"' % (STAXJobID,STAXCurrentTestcase)
      </script>
      <stafcmd name="'STAX Command: Test Case Query for %s' % STAXCurrentTestcase">
        <location>'%s' % location</location>
        <service>'stax'</service>
        <request>'%s' % STAXRequest</request>
      </stafcmd>
      <return>RC</return>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/phases/shared/utils.xml
New file
@@ -0,0 +1,658 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <!-- ************************************************************ -->
  <function name="checkRC">
    <function-prolog>
      This function checks a return code against an expected return code
    </function-prolog>
    <function-map-args>
      <function-arg-def name="returncode" type="required">
        <function-arg-description>
          return code received from command
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="result" type="required">
        <function-arg-description>
          the output of the result
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="expected" type="optional" default="[0]">
        <function-arg-description>
          the expected return code (list of value : [0] or [0,5])
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="optional" default="LOG_MAIN_FD">
        <function-arg-description>
          file descriptor, keywords : NO_FILE
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
<!-- TBD
      <script>
        result = result.replace('"','&quot;')
#        result = result.replace('<','&lt;')
#        result = result.replace('>','&gt;')
      </script>
      see the call in scheduler.xml
      clientSearchLoad() checkRC after process "running java program : searchLoad"
-->
      <script>
        _errNum = 0
        verdict = 'FAIL'
        for expRC in expected:
          if ( expRC == returncode ):
            verdict = 'PASS'
      </script>
      <if expr="verdict == 'PASS'">
        <sequence>
          <call function="'writeOperationResult'">
          {
            'returncode' : returncode,
            'expected'   : expected,
            'result'     : '',
            'status'     : 'SUCCESS',
            'fileFd'     : fileFd
          }
          </call>
        </sequence>
      <else>
        <sequence>
          <call function="'writeOperationResult'">
          {
            'returncode' : returncode,
            'expected'   : expected,
            'result'     : result,
            'status'     : 'ERROR',
            'fileFd'     : fileFd
          }
          </call>
          <script>
            _errNum = 1
          </script>
        </sequence>
      </else>
      </if>
      <script>
        ERR_NUM[0] += _errNum
      </script>
      <return>
        _errNum
      </return>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="phasePreamble">
    <function-prolog>
      Performs all the preoperations for a phase
    </function-prolog>
    <function-map-args>
      <function-arg-def name="phaseName" type="required">
      </function-arg-def>
      <function-arg-def name="tagAttr" type="optional" default='[]'>
        <function-arg-description>
          attribute/value of the tag [[attr1,val1],[attr2,val2],...]
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- Start time of test suite -->
      <script>
        phaseStartTime=strftime("%Y%m%d@%H:%M:%S",localtime())
        ERR_NUM[0] = 0
        if tagAttr == []:
          tagAttr = [['date',phaseStartTime]]
        else:
          tagAttr.append(['date',phaseStartTime])
      </script>
      <message log="1">''</message>
      <message log="1">
        '=================== START PHASE %s @ %s  ========================='\
        % (phaseName,phaseStartTime)
      </message>
      <call function="'writeStartTagPhase'">
      {
        'tagName' : phaseName ,
        'tagAttr' : tagAttr,
        'fileFd'  : fileFd
      }
      </call>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="phasePostamble">
    <function-prolog>
      Performs all the post operations for a phase
    </function-prolog>
    <function-map-args>
      <function-arg-def name="phaseName" type="required">
        <function-arg-description>
          Name of the phase
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          Name of output file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <if expr="phaseName == 'verdict'">
        <message log="1">
          '== Found a TOTAL of %s Error(s)' % (ERR_NUM[0])
        </message>
      <else>
        <message log="1">
          '== Found %s Error(s) during this phase' % (ERR_NUM[0])
        </message>
      </else>
      </if>
      <message log="1">
        '===================  STOP PHASE %s  ============================' \
        % (phaseName)
      </message>
      <call function="'writeTag'">
      {
        'tagName' : 'phaseResult',
        'tagAttr' : [['errNum',ERR_NUM[0]]] ,
        'fileFd'  : LOG_MAIN_FD
      }
      </call>
      <call function="'writeEndTagPhase'">
      {
        'fileFd'  : LOG_MAIN_FD
      }
      </call>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="sleep">
    <function-prolog>
      Sleep for number of milliseconds
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="'%s' % STAXServiceMachine">
        <function-arg-description>
          Location of target host
      </function-arg-description>
      <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
      <function-arg-def name="sleepForMilliSeconds" type="required">
        <function-arg-description>
          Number of milliseconds to sleep
        </function-arg-description>
        <function-arg-property name="type" value="seconds"/>
      </function-arg-def>
      <function-arg-def name="silentMode" type="optional" default="FALSE">
        <function-arg-description>
          do not write message in log file if set to TRUE
        </function-arg-description>
        <function-arg-property name="type" value="seconds"/>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          Name of output file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <if expr="silentMode == 'FALSE'">
        <sequence>
          <call function="'writeStartTagOperation'">
          { 'tagName' : 'sleep',
            'fileFd'  : fileFd }
          </call>
          <call function="'writeMessage'">
          { 'fileFd'  : fileFd,
            'content' : 'sleep for %s milliseconds on %s' % (sleepForMilliSeconds,location)
          }
          </call>
        </sequence>
      </if>
      <stafcmd name="'STAF Command: Delay'">
        <location>'%s' % location</location>
        <service>'delay'</service>
        <request>
          'delay %i' % sleepForMilliSeconds
        </request>
      </stafcmd>
      <if expr="silentMode == 'FALSE'">
        <sequence>
          <call function="'checkRC'">
            { 'returncode' : RC ,
              'result'     : STAFResult,
              'fileFd'     : fileFd }
          </call>
          <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
        </sequence>
      </if>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="ldifDiff">
    <function-prolog>
      This function  compares two LDIF files and reports the differences in LDIF format
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="STAF_REMOTE_HOSTNAME">
        <function-arg-description>
          Location of target host
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="dsPath" type="required">
        <function-arg-description>
          Pathname to installation root
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="version" type="optional">
        <function-arg-description>
          Display Directory Server version information
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="sourceLdif" type="required">
        <function-arg-description>
          LDIF file to use as the source data
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="targetLdif" type="required">
        <function-arg-description>
          LDIF file to use as the target data
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="outputLdif" type="required">
        <function-arg-description>
          File to which the diffs should be written
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="overwriteExisting" type="optional" default="TRUE">
        <function-arg-description>
          Overwrite existing output file rather than append to it
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="singleValueChanges" type="optional">
        <function-arg-description>
          Write each attribute-level change as a separate modification
          per attribute value rather than one modification per entry
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="Help" type="optional">
        <function-arg-description>
          Help option
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          Name of output file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'ldifDiff',
        'fileFd'  : fileFd }
      </call>
      <call function="'writeMessage'">
      { 'fileFd'  : fileFd,
        'content' : 'Compares two LDIF files and reports the differences in LDIF format'
      }
      </call>
      <!-- Build the Command -->
      <script>
        STAFCmdParamsList=[]
        STAFCmdParams=''
        if dsPath:
          dsBinPath='%s/bin' % (dsPath)
          STAFCmd='%s/ldif-diff' % (dsBinPath)
        if version:
          STAFCmdParamsList.append('-V')
        if sourceLdif:
          STAFCmdParamsList.append('-s %s' % sourceLdif)
        if targetLdif:
          STAFCmdParamsList.append('-t %s' % targetLdif)
        if outputLdif:
          STAFCmdParamsList.append('-o %s' % outputLdif)
        if overwriteExisting:
          STAFCmdParamsList.append('-O')
        if singleValueChanges:
          STAFCmdParamsList.append('-S')
        if Help:
          STAFCmdParamsList.append('-H')
        STAFCmdParams=' '.join(STAFCmdParamsList)
      </script>
      <call function="'writeMessage'">
      { 'fileFd'  : fileFd,
        'content' : '%s %s' % (STAFCmd,STAFCmdParams)
      }
      </call>
      <process name="'LDIF Diff Script'">
        <location>location</location>
        <command>STAFCmd</command>
        <parms>STAFCmdParams</parms>
        <workdir>dsBinPath</workdir>
        <envs>
          ['PATH=/bin:/usr/bin:%s' % dsBinPath]
        </envs>
        <console use="'same'"/>
        <stderr mode="'stdout'"/>
        <returnstdout/>
        <returnfile>outputLdif</returnfile>
      </process>
      <script>
        STAXCode=RC
        STAXReason=STAXResult
      </script>
      <script>
        diffsInfo = STAXReason[1]
        diffs = diffsInfo[1]
        if (diffsInfo[0] == 0) and (diffs.startswith("# No differences were detected between the source and target LDIF files")) :
          diffRC = 0
        else:
          diffRC = 1
      </script>
      <call function="'checkRC'">
        { 'returncode' : diffRC,
          'result'     : 'diff file : %s' % outputLdif,
          'fileFd'     : fileFd }
      </call>
      <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
      <return> diffRC </return>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="grep">
    <function-prolog>
      This function compares grep a string in a file
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional" default="STAF_REMOTE_HOSTNAME">
        <function-arg-description>
          Location of target host
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="string2grep" type="required">
        <function-arg-description>
          string to grep
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="file" type="required">
        <function-arg-description>
          File where grep will be done
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="expect2Find" type="optional" default="TRUE">
        <function-arg-description>
          if true, return SUCCESS if string2find is in the file
          if false, return SUCCESS if string2find is NOT in the file
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="caseSensitive" type="optional" default="TRUE">
        <function-arg-description>
          if true, grep with case sensitive mode
          if false, grep with case insensitive mode
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          Name of output file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!-- ========== -->
      <call function="'writeStartTagOperation'">
      { 'tagName' : 'grep',
        'fileFd'  : fileFd }
      </call>
      <if expr="expect2Find == TRUE">
        <call function="'writeMessage'">
        { 'fileFd'  : fileFd,
          'content' : "Check '%s' is in %s" % (string2grep,file)
        }
        </call>
      <else>
        <call function="'writeMessage'">
        { 'fileFd'  : fileFd,
          'content' : "Check '%s' is NOT in %s" % (string2grep,file)
        }
        </call>
      </else>
      </if>
      <!-- ========== -->
      <script>
        result = 'NOTHING'
        if (caseSensitive == TRUE):
          options = ''
        else:
          options = '-i'
      </script>
      <process name="'Grep'">
        <location>location</location>
        <command mode="'shell'">
          "grep %s '%s' %s" % (options,string2grep,file)
        </command>
        <envs>['PATH=/bin:/usr/bin']</envs>
        <stderr mode="'stdout'"/>
        <stdout/>
        <returnstdout/>
      </process>
      <script>
        grepRC=RC
        grepRC2=STAXResult[0][0]
        result=STAXResult[0][1]
      </script>
      <if expr="expect2Find == TRUE">
        <if expr="(result != 'NOTHING') and (grepRC == 0)">
          <call function="'checkRC'">
            { 'returncode' : 0,
              'result'     : '',
              'fileFd'     : fileFd }
          </call>
        <else>
          <call function="'checkRC'">
            { 'returncode' : grepRC,
              'result'     : result,
              'fileFd'     : fileFd }
          </call>
        </else>
        </if>
      <!-- == expect2Find == FALSE == -->
      <else>
        <if expr="(result == '') and (grepRC != 0)">
          <call function="'checkRC'">
            { 'returncode' : 0,
              'result'     : '',
              'fileFd'     : fileFd }
          </call>
        <else>
          <call function="'checkRC'">
            { 'returncode' : grepRC,
              'expected'   : [1],
              'result'     : result,
              'fileFd'     : fileFd }
          </call>
        </else>
        </if>
      </else>
      </if>
      <!-- ========== -->
      <call function="'writeEndTagOperation'">{'fileFd'  : fileFd}</call>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="getOSvariables">
    <function-prolog>
      Get OS related variables
    </function-prolog>
    <function-map-args>
      <function-arg-def name="hostname" type="required">
        <function-arg-description>
          Name of host on which to retrieve variables
        </function-arg-description>
        <function-arg-property name="type" value="hostname"/>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <stafcmd name="'STAF Command: Get OS Name'">
        <location>'%s' % hostname</location>
        <service>'var'</service>
        <request>
          'get system var STAF/Config/OS/Name'
        </request>
      </stafcmd>
      <return>STAFResult</return>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="getOSDate">
    <function-prolog>
        This function returns the date (MONTH/DAY/YEARS-HOURS/MIN) of the OS
    </function-prolog>
    <function-map-args>
      <function-arg-def name="location" type="optional"
                        default="'%s' % STAXServiceMachine">
        <function-arg-description>
          Location of target host
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <call function="'getOSvariables'">
        { 'hostname' : location }
      </call>
      <script>
        import re
        winPattern=re.compile('win', re.IGNORECASE)
        isWindows=winPattern.search(STAXResult)
      </script>
      <!-- OS is windows -->
      <if expr="isWindows">
        <sequence>
          <process name="'get date on %s' % location">
            <location>location</location>
            <command mode="'shell'">'date /T'</command>
            <workdir>'/'</workdir>
            <stderr mode="'stdout'"/>
            <returnstdout/>
          </process>
          <script>
            date = STAFResult
            date = date[date.find(' ')+1:len(date)].strip()
          </script>
          <process name="'get time on %s' % location">
            <location>location</location>
            <command mode="'shell'">'time /T'</command>
            <workdir>'/'</workdir>
            <stderr mode="'stdout'"/>
            <returnstdout/>
          </process>
          <script>
            time = STAFResult
            #time = time[0:time.find(' ')].strip()
            date = '%s-%s' % (date,time)
          </script>
        </sequence>
      <!-- OS is UNIX based -->
      <else>
        <sequence>
          <process name="'get date on %s' % location">
            <location>location</location>
            <command mode="'shell'">'date'</command>
            <parms>"'+%m/%d/%Y-%H:%M:%S'"</parms>
            <workdir>'/'</workdir>
            <envs>['PATH=/bin:/usr/bin']</envs>
            <stderr mode="'stdout'"/>
            <returnstdout/>
          </process>
          <script>
            date = STAXResult[0][1].split('\n')
          </script>
        </sequence>
      </else>
      </if>
      <return>date</return>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/phases/verdict/verdict.xml
New file
@@ -0,0 +1,169 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <defaultcall function="verdict"/>
  <!-- ************************************************************ -->
  <function name="verdict">
    <function-map-args>
      <function-arg-def name="instances" type="required">
        <function-arg-description>
          list of instance objects
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="suffix" type="required">
        <function-arg-description>
          suffix object
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="runConfiguration" type="required">
        <function-arg-description>
          boolean : configuration phase has been run or not
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="runScheduler" type="required">
        <function-arg-description>
          boolean : scheduler phase has been run or not
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!--==========  Call preambule  =========-->
      <call function="'phasePreamble'">
      { 'phaseName' : 'verdict',
        'fileFd'    : LOG_MAIN_FD }
      </call>
      <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
      file="'%s/phases/verdict/verdict_opends.xml' % (TESTS_DIR)"/>
      <!--== Check if previous phases raised some errors ==-->
      <if expr="ERR_NUM_INSTALL != 0 and ERR_NUM_INSTALL != ''">
        <script> ERR_NUM[0] += 1 </script>
      </if>
      <if expr="ERR_NUM_GEN_LDIF != 0 and ERR_NUM_GEN_LDIF != ''">
        <script> ERR_NUM[0] += 1 </script>
      </if>
      <if expr="ERR_NUM_CONFIGURATION != 0 and ERR_NUM_CONFIGURATION != ''">
        <script> ERR_NUM[0] += 1 </script>
      </if>
      <if expr="ERR_NUM_SCHEDULER != 0 and ERR_NUM_SCHEDULER != ''">
        <script> ERR_NUM[0] += 1 </script>
      </if>
      <!--== If configuration/schedulers phases have been run ==-->
      <!--== then do some basic checks : isalive ==-->
      <if expr="runConfiguration == 'true' or runScheduler == 'true'">
        <sequence>
          <script>
            fileList = STAXGlobal([])
          </script>
          <script>
            topoInstances = suffix.getTopology()
          </script>
          <paralleliterate in="topoInstances" var="topoInstance">
            <sequence>
              <!-- parallel process, all variables defined        -->
              <!-- and values set below are local to the sequence -->
              <script>
                instance = topoInstance.getInstanceRef()
                logName = '%s_%s' % (instance.getHost(),instance.getName())
                logFile = '%s/verdict_%s.xml' % (LOG_XML_TMP_DIR,logName)
                fileList.append(logFile)
                cFileFd = open(logFile,'w')
                # Write start tag
                str = '&lt;instance name=\"%s\"' % instance.getName()
                str = '%s host=\"%s\"' % (str, instance.getHost())
                str = '%s port=\"%s\"' % (str, instance.getLDAPPort())
                str = '%s product=\"opends\"&gt;\n' % str
                cFileFd.write(str)
              </script>
              <if expr="instance.getProduct() == 'opends'">
                <call function="'verdictOpends'">
                {
                  'instance'  : instance,
                  'instances' : topoInstances,
                  'suffix'    : suffix,
                  'fileFd'    : cFileFd
                }
                </call>
              </if>
              <!--== Post operations ======-->
              <message>
                '%s : %s : verdict complete' % \
                (instance.getHost(),instance.getName())
              </message>
              <script>
                cFileFd.write('&lt;/instance&gt;\n')
                cFileFd.close()
                cFileFd = ''
              </script>
            </sequence>
          </paralleliterate>
        </sequence>
      </if>
      <!--==========  Merge files    ==========-->
      <call function="'mergeFiles'">
        {
          'fileList' : fileList,
          'fileFd'   : LOG_MAIN_FD
        }
      </call>
      <!--==========  Call postphase =========-->
      <call function="'phasePostamble'">
      {
        'phaseName' : 'verdict',
        'fileFd'    : LOG_MAIN_FD
      }
      </call>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/phases/verdict/verdict_opends.xml
New file
@@ -0,0 +1,209 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <defaultcall function="verdictOpends"/>
  <!-- ************************************************************ -->
  <function name="verdictOpends">
    <function-map-args>
      <function-arg-def name="instance" type="required">
        <function-arg-description>
          opends instance object
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="instances" type="required">
        <function-arg-description>
          list of instance objects
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="suffix" type="required">
        <function-arg-description>
          suffix object
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          file descriptor, wildcard : NO_FILE to not write into a file
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <!--== Get the list of opends instances in the topology == -->
      <script>
        opendsInstances = []
        topoInstances   = suffix.getTopology()
        for topoInstance in topoInstances:
          cInstance = topoInstance.getInstanceRef()
          if cInstance.getProduct() == 'opends':
            opendsInstances.append(cInstance)
      </script>
      <!--==== Check server is alive =========-->
      <call function="'isAlive'">
        { 'location'         : instance.getHost(),
          'noOfLoops'        : 1,
          'noOfMilliSeconds' : 2000,
          'dsPath'           : instance.getInstallDir(),
          'dsInstanceHost'   : instance.getHost(),
          'dsInstancePort'   : instance.getLDAPPort(),
          'fileFd'           : fileFd
        }
      </call>
      <script>isAliveResult = STAXResult</script>
      <if expr="isAliveResult == FALSE">
        <call function="'checkRC'">
          {
            'returncode' : isAliveResult,
            'result'     : 'Server does not responding',
            'fileFd'     : fileFd
          }
        </call>
      </if>
      <!--==== Check replication synchronization =========-->
      <!--
      <call function="'checkReplicationSynchro'">
          { 'instance' : instance,
            'fileFd'   : fileFd
          }
      </call>
      -->
      <!--==== Compare entries =========-->
      <call function="'verifyTrees'">
        {
          'location'   : instance.getHost(),
          'instance'   : instance,
          'instances'  : opendsInstances,
          'suffixDn'   : suffix.getSuffixDn(),
          'filePrefix' : 'verdict',
          'fileFd'     : fileFd
        }
      </call>
      <!--== Check error/access logs =========-->
      <call function="'checkLogs'">
        {
          'location'   : instance.getHost(),
          'installDir' : instance.getInstallDir(),
          'fileFd'     : fileFd
        }
      </call>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="checkReplicationSynchro">
    <function-map-args>
      <function-arg-def name="instance" type="required">
        <function-arg-description>
          instance object
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          Name of output file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <call function="'writeStartTagStep'">
      { 'tagName' : 'checkReplicationSynchro',
        'fileFd'  : fileFd }
      </call>
      <message>'TBD'</message>
      <call function="'writeEndTagStep'">{ 'fileFd' : fileFd}</call>
    </sequence>
  </function>
  <!-- ************************************************************ -->
  <function name="checkLogs">
    <function-map-args>
      <function-arg-def name="location" type="optional"
                        default="STAF_REMOTE_HOSTNAME">
        <function-arg-description>
          Location of target host
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="installDir" type="required">
        <function-arg-description>
          instance installation path
        </function-arg-description>
      </function-arg-def>
      <function-arg-def name="fileFd" type="required">
        <function-arg-description>
          Name of output file descriptor
        </function-arg-description>
      </function-arg-def>
    </function-map-args>
    <sequence>
      <call function="'writeStartTagStep'">
      { 'tagName' : 'checkLogs',
        'fileFd'  : fileFd }
      </call>
      <call function="'grep'">
      {
        'location'      : location,
        'string2grep'   : 'ERROR',
        'expect2Find'   : FALSE,
        'caseSensitive' : FALSE,
        'file'          : '%s/logs/errors' % installDir,
        'fileFd'        : fileFd
      }
      </call>
      <call function="'grep'">
      {
        'location'      : location,
        'string2grep'   : 'exception',
        'expect2Find'   : FALSE,
        'caseSensitive' : FALSE,
        'file'          : '%s/logs/errors' % installDir,
        'fileFd'        : fileFd
      }
      </call>
      <call function="'writeEndTagStep'">{ 'fileFd' : fileFd}</call>
    </sequence>
  </function>
</stax>
opends/tests/system-tests/report/opends_logo_sm.png
opends/tests/system-tests/report/result.css
New file
@@ -0,0 +1,142 @@
/****
 * 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 2008 Sun Microsystems, Inc.
 ****/
html,body {
  background-color : black;
}
p {
  font-size : 100%;
  font-family :  Verdana, Arial, Helvetica, Geneva, sans-serif;
  color : black;
  background-color : white;
  margin-left:20px;
}
h1 {
  font-size : 200%;
  font-family :  Verdana, Arial, Helvetica, Geneva, sans-serif;
  border-top: 3px double;
  border-bottom: 3px double;
  color : white;
  text-align: center;
}
h2 {
  font-size : 150%;
  font-family :  Verdana, Arial, Helvetica, Geneva, sans-serif;
  color : black;
  padding-left:15px;
  text-align: center;
}
a:link {color: black; text-decoration:underline;}
a:visited {color: black; text-decoration:underline;}
a:hover {color:red; text-decoration:none;}
/*******************/
/* summary phase  */
summary {
  font-size : 120%;
  font-family :  Verdana, Arial, Helvetica, Geneva, sans-serif;
  padding-left:25px;
  text-align: left;
}
table#summaryTable {
  border-style:none;
  text-align:left;
}
table#summaryTable td{
  border-style:none;
  border-width:none;
}
/*******************/
/* table */
table {
  margin-left:35px;
  padding-left:50px;
  border-style:solid;
  border-width:1px;
  border-color:#CCCCFF;
  border-collapse:collapse;
  text-align:center;
}
td {
  border-style:solid;
  border-width:1px;
  border-color:#CCCCFF;
  /*font-size: 10px;*/
  /*height: 30px;*/
}
th {
  background-color:#CCCCFF;
  border-style:solid;
  border-width:1px;
  text-align: center;
  /*height: 40px;*/
}
.bgcol1 {
  font-style: italic;
  text-align: center;
  background-color: #FFFFCC;
}
.bgcolth {
  border-width:1px;
  border-style:solid;
  border-color:#CCCCFF;
  font-style: bold;
  height: 40px;
  text-align: center;
  background-color: #CCCCFF;
}
/*******************/
/* pass fail color */
.pass {
  font-style: bold;
  color: rgb(51, 204, 0);
}
.fail {
  font-style: bold;
  color: rgb(255, 0, 0);
}
.phaseResult {
  font-style: bold;
  font-size : 120%;
}
.showLink {
  cursor: pointer;
  text-decoration:underline;
}
opends/tests/system-tests/report/result.xsl
New file
@@ -0,0 +1,680 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
 ! 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 2008 Sun Microsystems, Inc.
 ! -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output
  method="html"
  encoding="ISO-8859-1"
  doctype-public="-//W3C//DTD HTML 4.01//EN"
  doctype-system="http://www.w3.org/TR/html4/strict.dtd"
  indent="yes" />
<!-- ================= MAIN ================ -->
<xsl:template match="systemTestRoot">
  <html>
    <head>
      <link href="result.css" rel="stylesheet" type="text/css"></link>
    </head>
    <body>
    <script type="text/javascript" language="javascript">
      function ShowHideListElement(eSrc)
      {
      eSrc = document.getElementById(eSrc);
      eSrc.style.display = ("block" == eSrc.style.display ? "none" : "block");
      }
    </script>
    <h1>System Test Report</h1>
    <xsl:apply-templates select="summary" />
    <xsl:apply-templates select="topology"/>
    <xsl:apply-templates select="phase" />
  </body></html>
</xsl:template>
<!-- ================= Manage phase node ================ -->
<xsl:template match="phase">
    <p>
    <xsl:variable name="phaseName" select="normalize-space(@name)"/>
    <!-- Display title -->
    <h2>
      Phase
      <font color="blue">
        <xsl:value-of select="$phaseName" />
      </font>
    <i>
      <xsl:text> started at </xsl:text>
      <xsl:value-of select="@date" />
      <xsl:choose>
        <xsl:when test="$phaseName = 'scheduler'">
          / duration <xsl:value-of select="@duration" />
        </xsl:when>
      </xsl:choose>
    </i>
    <br/>
    </h2>
    <!-- Call specific display depending on the phase -->
    <xsl:choose>
      <xsl:when test="$phaseName = 'installation'">
        <a name="installation"/>
        <xsl:call-template name="parsePhase">
          <xsl:with-param name="phaseName" select="'Installation'" />
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="$phaseName = 'generateLdif'">
        <a name="generateLdif"/>
        <xsl:call-template name="parsePhase">
          <xsl:with-param name="phaseName" select="'GenerateLdif'" />
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="$phaseName = 'configuration'">
        <a name="configuration"/>
        <xsl:call-template name="parsePhase">
          <xsl:with-param name="phaseName" select="'Configuration'" />
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="$phaseName = 'scheduler'">
        <a name="scheduler"/>
        <xsl:call-template name="parsePhase">
          <xsl:with-param name="phaseName" select="'Scheduler'" />
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="$phaseName = 'verdict'">
        <a name="verdict"/>
        <xsl:call-template name="parsePhase">
          <xsl:with-param name="phaseName" select="'Verdict'" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <span style="color: rgb(255, 0, 0); font-weight: bold;">
          ERROR :Unknown phase name <xsl:value-of select="$phaseName"/>
        </span>
      </xsl:otherwise>
    </xsl:choose>
    <br/>
     <xsl:apply-templates select="phaseResult" />
    </p>
</xsl:template>
<!-- ********************************************************************* -->
<!-- ***********************  SUMMARY PHASE   **************************** -->
<!-- ********************************************************************* -->
<xsl:template match="summary">
  <p>
    <a name="summary"/>
    <h2>Summary</h2>
    <xsl:apply-templates select="scenario" />
    <table id="summaryTable">
      <xsl:apply-templates select="phaseSummmary" />
    </table>
  </p>
 </xsl:template>
<!-- ================= Display scenario informations ============ -->
<xsl:template match="scenario">
  <b>Scenario name</b> : <xsl:value-of select="normalize-space(@name)"/> <br/>
  <b>Description</b> : <xsl:value-of
                            select="normalize-space(local-name(.))"/> <br/>
  <b>Duration</b> : <xsl:value-of
                            select="normalize-space(@duration)"/> <br/>
  <br/>
 </xsl:template>
<!-- ================= Display each phase status ================ -->
<xsl:template match="phaseSummmary">
  <tr><td>
    <xsl:variable name="name" select="normalize-space(@name)"/>
    <a href="#{$name}"><xsl:value-of select="$name" /> </a>
  </td>
  <td>
    <xsl:variable name="result" select="normalize-space(@result)"/>
    <b>
    <xsl:choose>
      <xsl:when test="$result='0'">
       <span class="pass">PASS</span>
      </xsl:when>
      <xsl:otherwise>
       <span class="fail">FAIL</span>
      </xsl:otherwise>
     </xsl:choose>
     </b>
  </td></tr>
</xsl:template>
<!-- ********************************************************************* -->
<!-- ***********************  TOPOLOGY PHASE     ************************* -->
<!-- ********************************************************************* -->
<!-- =================  ================ -->
<xsl:template match="topology">
  <p>
    <a name="topology"/>
    <h2>Topology</h2>
    <xsl:apply-templates select="instances" />
    <xsl:apply-templates select="suffixes" />
    <xsl:apply-templates select="schedulerParser" />
    <xsl:call-template name="parseChildPhase" />
  </p>
</xsl:template>
<!-- =================  ================ -->
<xsl:template match="instances">
  <table>
  <th> </th>
  <xsl:for-each select="child::*">
    <xsl:variable name="nodeName" select="normalize-space(local-name(.))"/>
    <xsl:choose>
      <xsl:when test="$nodeName = 'instance'">
        <th><xsl:value-of select="normalize-space(@name)"/></th>
      </xsl:when>
    </xsl:choose>
  </xsl:for-each>
  <!-- PRODUCT -->
  <tr>
    <td class="bgcolth"> Product </td>
    <xsl:for-each select="child::*">
    <xsl:variable name="nodeName" select="normalize-space(local-name(.))"/>
    <xsl:choose>
      <xsl:when test="$nodeName = 'instance'">
          <td><xsl:value-of select="normalize-space(@product)"/></td>
      </xsl:when>
    </xsl:choose>
    </xsl:for-each>
  </tr>
  <!-- BUILD -->
  <tr>
    <td class="bgcolth"> Build </td>
    <xsl:for-each select="child::*">
    <xsl:variable name="nodeName" select="normalize-space(local-name(.))"/>
    <xsl:choose>
      <xsl:when test="$nodeName = 'instance'">
          <td><xsl:value-of select="normalize-space(buildId)"/></td>
      </xsl:when>
    </xsl:choose>
    </xsl:for-each>
  </tr>
  <!-- HOST -->
  <tr>
    <td class="bgcolth"> Host </td>
    <xsl:for-each select="child::*">
    <xsl:variable name="nodeName" select="normalize-space(local-name(.))"/>
    <xsl:choose>
      <xsl:when test="$nodeName = 'instance'">
          <td><xsl:value-of select="normalize-space(host)"/></td>
      </xsl:when>
    </xsl:choose>
    </xsl:for-each>
  </tr>
  <!-- OS -->
  <tr>
    <td class="bgcolth"> OS </td>
    <xsl:for-each select="child::*">
    <xsl:variable name="nodeName" select="normalize-space(local-name(.))"/>
    <xsl:choose>
      <xsl:when test="$nodeName = 'instance'">
          <td><xsl:value-of select="normalize-space(os)"/></td>
      </xsl:when>
    </xsl:choose>
    </xsl:for-each>
  </tr>
  <!-- JAVA -->
  <tr>
    <td class="bgcolth"> Build </td>
    <xsl:for-each select="child::*">
    <xsl:variable name="nodeName" select="normalize-space(local-name(.))"/>
    <xsl:choose>
      <xsl:when test="$nodeName = 'instance'">
          <td><xsl:value-of select="normalize-space(jvm)"/></td>
      </xsl:when>
    </xsl:choose>
    </xsl:for-each>
  </tr>
  <!-- LDAP PORT -->
  <tr>
    <td class="bgcolth"> Ldap Port </td>
    <xsl:for-each select="child::*">
    <xsl:variable name="nodeName" select="normalize-space(local-name(.))"/>
    <xsl:choose>
      <xsl:when test="$nodeName = 'instance'">
          <td><xsl:value-of select="normalize-space(port/ldap)"/></td>
      </xsl:when>
    </xsl:choose>
    </xsl:for-each>
  </tr>
  <!-- SYNCHRO DATE -->
  <tr>
    <td class="bgcolth"> Date 4 synchronization </td>
    <xsl:for-each select="child::*">
    <xsl:variable name="nodeName" select="normalize-space(local-name(.))"/>
    <xsl:choose>
      <xsl:when test="$nodeName = 'instance'">
          <td><xsl:value-of select="normalize-space(synchroDate)"/></td>
      </xsl:when>
    </xsl:choose>
    </xsl:for-each>
  </tr>
  </table><br/><br/>
<!--
  <table>
      <th> Instance </th>
      <th> Product </th>
      <th> Build </th>
      <th> Host </th>
      <th> OS </th>
      <th> Jvm </th>
      <th> LDAP port </th>
      <th> InstallDir </th>
-->
  <!-- child is instance node only -->
<!--
  <xsl:for-each select="child::*">
    <xsl:variable name="nodeName" select="normalize-space(local-name(.))"/>
    <xsl:choose>
      <xsl:when test="$nodeName = 'instance'">
        <tr class="bgcol1">
          <td><xsl:value-of select="normalize-space(@name)"/> </td>
          <td><xsl:value-of select="normalize-space(@product)"/></td>
          <td><xsl:value-of select="normalize-space(buildId/.)"/></td>
          <td><xsl:value-of select="normalize-space(host/.)"/> </td>
          <td><xsl:value-of select="normalize-space(os/.)"/> </td>
          <td><xsl:value-of select="normalize-space(javaVersion/.)"/> </td>
          <td><xsl:value-of select="normalize-space(port/ldap/.)"/></td>
          <td><xsl:value-of select="normalize-space(installDir/.)"/></td>
        </tr>
      </xsl:when>
      <xsl:otherwise>
        <tr>
          <td>
            <span style="color: rgb(255, 0, 0); font-weight: bold;">
                  ERROR :Unknown phase name <xsl:value-of select="$nodeName"/>
                  using product
            </span>
          </td>
        </tr>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:for-each>
  </table> <br/><br/>
-->
</xsl:template>
<!-- ================= Manage suffixes node ================ -->
<xsl:template match="suffixes">
  <table>
    <tr>
      <th>Suffix name</th>
      <th>Nb of Entries</th>
      <th>Instances / init rule</th>
    </tr>
    <!-- child is instance node only -->
    <xsl:for-each select="child::*">
      <xsl:variable name="nodeName" select="normalize-space(local-name(.))"/>
      <xsl:choose>
        <xsl:when test="$nodeName = 'suffix'">
          <tr class="bgcol1">
            <td><xsl:value-of select="normalize-space(@name)"/> </td>
            <td>
              <xsl:value-of select="normalize-space(numberOfEntries/.)"/>
            </td>
            <td>
            <xsl:for-each select="child::topology/instance">
              <xsl:variable name="iName" select="normalize-space(@name)"/>
              <xsl:variable name="iInitRule"
                            select="normalize-space(@initRule)"/>
              <xsl:value-of select="$iName"/>
              /
              <xsl:value-of select="$iInitRule"/>
              <br/>
            </xsl:for-each>
            </td>
          </tr>
        </xsl:when>
        <xsl:otherwise>
          <span style="color: rgb(255, 0, 0); font-weight: bold;">
            ERROR :Unknown phase name <xsl:value-of select="$nodeName"/>
          </span>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </table><br/><br/>
</xsl:template>
<!-- ====== Manage scheduler child for topology phase ====== -->
<xsl:template match="schedulerParser">
  <table>
    <tr>
      <th>Modules</th>
      <th>Clients</th>
    </tr>
  <!-- child is instance node only -->
  <xsl:for-each select="child::*">
    <xsl:variable name="nodeName" select="normalize-space(local-name(.))"/>
    <xsl:variable name="moduleEnabled" select="normalize-space(@enabled)"/>
    <xsl:choose>
      <xsl:when test="$nodeName = 'module'">
        <tr class="bgcol1">
          <td>
            <xsl:choose>
              <xsl:when test="$moduleEnabled = 'true'">
                <xsl:value-of select="normalize-space(@name)"/> (enabled)
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="normalize-space(@name)"/> (disabled)
              </xsl:otherwise>
            </xsl:choose>
          </td>
          <td>
            <xsl:apply-templates select="client" />
          </td>
        </tr>
      </xsl:when>
      <xsl:otherwise>
        <span style="color: rgb(255, 0, 0); font-weight: bold;">
          ERROR :Unknown phase name <xsl:value-of select="$nodeName"/>
        </span>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:for-each>
  </table><br/><br/>
</xsl:template>
<!-- ============ Manage client node for topology phase ============= -->
<xsl:template match="client">
  <xsl:value-of select="normalize-space(@name)"/>
  <xsl:variable name="stop" select="normalize-space(@stop)"/>
  <xsl:choose>
    <xsl:when test="$stop = 'ERROR_not_defined'">
      (<xsl:value-of select="normalize-space(@start)"/> -
        dependency <xsl:value-of select="normalize-space(@dependency)"/>)
    </xsl:when>
    <xsl:otherwise>
      (<xsl:value-of select="normalize-space(@start)"/> -
        <xsl:value-of select="normalize-space(@stop)"/>)
    </xsl:otherwise>
  </xsl:choose>
  <br/>
</xsl:template>
<!-- ********************************************************************* -->
<!-- ***********************  GENERIC         **************************** -->
<!-- ********************************************************************* -->
<!-- =================  ================ -->
<xsl:template name="parsePhase">
  <xsl:param name="phaseName"/>
  * <a href="#summary"> Move up to Summary</a>
  <br/>
  * <a onclick="ShowHideListElement('{$phaseName}')">
    <span class="showLink"> Clic me to show/hide details</span>
  </a>
  <p id="{$phaseName}" style="display: none">
    <ul>
    <!--== Child of phase can be a module, operation, instance node ==-->
    <xsl:for-each select="child::*">
      <xsl:variable name="nodeName" select="normalize-space(local-name(.))"/>
      <xsl:choose>
        <!--== module node ==-->
        <xsl:when test="$nodeName = 'module'">
          <xsl:call-template name="displayModule" />
        </xsl:when>
        <!--== step node ==-->
        <xsl:when test="$nodeName = 'step'">
          <xsl:call-template name="displayStep" />
          <br/>
        </xsl:when>
        <!--== operation node ==-->
        <xsl:when test="$nodeName = 'operation'">
          <xsl:call-template name="displayOperation" />
          <br/>
        </xsl:when>
        <!--== instance node ==-->
        <xsl:when test="$nodeName = 'instance'">
          <xsl:variable name="instanceName" select="normalize-space(@name)"/>
          <xsl:variable name="instanceHost" select="normalize-space(@host)"/>
          <xsl:variable name="instancePort" select="normalize-space(@port)"/>
          <xsl:variable name="instanceProduct"
                        select="normalize-space(@product)"/>
          <li>
            <b>
              <xsl:value-of select="$phaseName"/> for instance
              <font color="blue"><xsl:value-of select="$instanceName"/></font>
              on <xsl:value-of select="$instanceHost"/> :
              <xsl:value-of select="$instancePort"/>
              (<xsl:value-of select="$instanceProduct" />)
            </b><br/>
            <xsl:call-template name="parseChildPhase" />
          </li><br/><br/>
        </xsl:when>
        <!--== phaseResult node ==-->
        <xsl:when test="$nodeName = 'phaseResult'">
        </xsl:when>
        <!--== else... ==-->
        <xsl:otherwise>
          <span style="color: rgb(255, 0, 0); font-weight: bold;">
            ERROR : Unknown node name <xsl:value-of select="$nodeName"/>
          </span><br/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
    </ul>
  * <a onclick="ShowHideListElement('{$phaseName}')">
    <span class="showLink">Clic me to show/hide details</span>
  </a><br/>
  * <a href="#summary">Move up to Summary</a>
  </p>
</xsl:template>
<!-- ================= Manage phase node childs ================ -->
<xsl:template name="parseChildPhase">
  <!--== Generic sub childs can be a operation/operationResult/... nodes ==-->
  <ul>
    <xsl:for-each select="child::*">
      <xsl:variable name="nodeName" select="normalize-space(local-name(.))"/>
      <xsl:choose>
        <xsl:when test="$nodeName = 'step'">
          <xsl:call-template name="displayStep" />
        </xsl:when>
        <xsl:when test="$nodeName = 'operation'">
          <xsl:call-template name="displayOperation" />
        </xsl:when>
        <xsl:when test="$nodeName = 'operationResult'">
          <xsl:call-template name="displayOperationResult" />
        </xsl:when>
        <xsl:when test="$nodeName = 'message'">
          <xsl:call-template name="displayMessage" />
        </xsl:when>
        <xsl:when test="$nodeName = 'client'">
          <xsl:call-template name="displayClient" />
        </xsl:when>
        <!--== Nothing to do, just for node recognition ==-->
        <xsl:when test="$nodeName = 'instances'">
        </xsl:when>
        <xsl:when test="$nodeName = 'suffixes'">
        </xsl:when>
        <xsl:when test="$nodeName = 'phaseResult'">
        </xsl:when>
        <xsl:when test="$nodeName = 'schedulerParser'">
        </xsl:when>
        <xsl:when test="$nodeName = 'copyClient'">
        </xsl:when>
        <xsl:when test="$nodeName = 'clientResult'">
        </xsl:when>
        <xsl:otherwise>
          <span style="color: rgb(255, 0, 0); font-weight: bold;">
            ERROR : unknown node name <xsl:value-of select="$nodeName"/>
          </span><br/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </ul>
</xsl:template>
<!-- ================= Manage module node ================ -->
<xsl:template name="displayModule">
  <li> <b>Module</b> : <xsl:value-of select="normalize-space(@name)"/> <br/>
      <xsl:call-template name="parseChildPhase" />
  </li><br/>
</xsl:template>
<!-- ================= Manage client node ================ -->
<xsl:template name="displayClient">
  <xsl:variable name="clientName" select="normalize-space(@name)"/>
  <xsl:variable name="clientHost" select="normalize-space(@host)"/>
  <li>
    <xsl:variable name="i" select="count(preceding::client)"/>
    <a onclick="ShowHideListElement('{$i}')">
      <span class="showLink">
        <xsl:value-of select="$clientName"/> on
        <xsl:value-of select="$clientHost"/>
      </span>
    </a>
    <p id="{$i}" style="display: none">
      <xsl:call-template name="parseChildPhase" />
    </p>
    client ends with status :
      <xsl:variable name="clientStatus"
                    select="normalize-space(clientResult/@status)"/>
      <xsl:choose>
        <xsl:when test="$clientStatus='SUCCESS'">
          <b><span class="pass">SUCCESS</span></b>
        </xsl:when>
        <xsl:otherwise>
          <b><span class="fail">FAIL</span></b>
        </xsl:otherwise>
      </xsl:choose>
  </li><br/>
</xsl:template>
<!-- ================= Manage step node ================ -->
<xsl:template name="displayStep">
  <xsl:variable name="stepName" select="normalize-space(@name)"/>
  <li>
    <b>Step : <xsl:value-of select="$stepName" /> </b><br/>
    <xsl:call-template name="parseChildPhase" />
  </li>
</xsl:template>
<!-- ================= Manage operation node ================ -->
<xsl:template name="displayOperation">
  <xsl:variable name="opName" select="normalize-space(@name)"/>
  <li>
    <b><xsl:value-of select="$opName" /> </b><br/>
    <xsl:call-template name="parseChildPhase" />
  </li>
</xsl:template>
<!-- ================= Manage operationResult node ================ -->
<xsl:template name="displayOperationResult">
  <xsl:variable name="rc" select="normalize-space(@returncode)"/>
  <xsl:variable name="exprc" select="normalize-space(@expected)"/>
  <xsl:variable name="result" select="normalize-space(.)"/>
  <xsl:variable name="status" select="normalize-space(@status)"/>
  <b>
    <xsl:choose>
      <xsl:when test="$status='SUCCESS'">
        <span class="pass"><xsl:value-of select="$status"/></span>
        [
         return code <xsl:value-of select="$rc" />,
         expected <xsl:value-of select="$exprc" />
        ] <br/>
      </xsl:when>
      <xsl:when test="$status='ERROR'">
        <span class="fail"><xsl:value-of select="$status"/></span>
        [
         return code <xsl:value-of select="$rc" />,
         expected <xsl:value-of select="$exprc" />,
         <xsl:value-of select="$result" />
        ] <br/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$status"/>
      </xsl:otherwise>
    </xsl:choose>
  </b>
  <xsl:call-template name="parseChildPhase" />
</xsl:template>
<!-- ================= Manage message node     ================ -->
<xsl:template name="displayMessage">
  <xsl:value-of select="." /> <br/>
  <xsl:call-template name="parseChildPhase" />
</xsl:template>
<!-- ================= Manage phaseResult node ================ -->
<xsl:template match="phaseResult">
  <span class="phaseResult">
    Phase ends with status :
    <xsl:variable name="result" select="normalize-space(@errNum)"/>
    <xsl:choose>
      <xsl:when test="$result='0'">
       <span class="pass">PASS</span>
      </xsl:when>
      <xsl:otherwise>
       <span class="fail">FAIL</span>
      </xsl:otherwise>
     </xsl:choose>
  </span>
</xsl:template>
</xsl:stylesheet>
opends/tests/system-tests/scenario/conf.dtd
New file
@@ -0,0 +1,111 @@
<!--
 ! 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 2008 Sun Microsystems, Inc.
 ! -->
<!ELEMENT systemTestConfiguration (globalParameters, instance+,
                                   suffix?, scheduler?)>
<!-- ========== GLOBAL PARAMETERS NODE ========================= -->
<!ELEMENT globalParameters (scenario,opendsName,opendsZip,directoryManagerDn?,
                            directoryManagerPswd?,domain?)>
  <!ELEMENT scenario (name,description)>
    <!ELEMENT name (#PCDATA)>
    <!ELEMENT description (#PCDATA)>
  <!ELEMENT opendsName (#PCDATA)>
  <!ELEMENT opendsZip (#PCDATA)>
  <!ELEMENT directoryManagerDn (#PCDATA)>
  <!ELEMENT directoryManagerPswd (#PCDATA)>
  <!ELEMENT domain (#PCDATA)>
<!-- ========== INSTANCE NODE ========================= -->
<!ELEMENT instance (host,installDir,ports?)>
<!ATTLIST instance
    name NMTOKEN #REQUIRED
    product NMTOKEN #REQUIRED>
  <!ELEMENT host (#PCDATA)>
  <!ELEMENT installDir (#PCDATA)>
  <!ELEMENT ports (ldap?,ldaps?,jmx?,replicationServer?)>
    <!ELEMENT ldap (#PCDATA)>
    <!ELEMENT ldaps (#PCDATA)>
    <!ELEMENT jmx (#PCDATA)>
    <!ELEMENT replicationServer (#PCDATA)>
<!-- ========== SUFFIX NODE ========================= -->
<!ELEMENT suffix (topology,tree)>
<!ATTLIST suffix
    dn CDATA #REQUIRED>
  <!ELEMENT topology (element+)>
    <!ELEMENT element EMPTY>
    <!ATTLIST element
          instanceName NMTOKEN #REQUIRED
          initRule ( importLdif | totalUpdate ) "importLdif"
          instanceSourceName NMTOKEN #IMPLIED>
  <!ELEMENT tree (branch+,subordinateTemplate*)>
    <!ATTLIST tree nbOfEntries CDATA #REQUIRED>
    <!ELEMENT branch (branch*,subordinateTemplate*)>
    <!ATTLIST branch name CDATA #REQUIRED>
    <!ELEMENT subordinateTemplate EMPTY>
    <!ATTLIST subordinateTemplate
          type ( person | inetOrgPerson | organizationalPerson
                 | inetOrgPerson_Jpeg_1MB ) #REQUIRED
          percentage NMTOKEN #IMPLIED
          nb NMTOKEN #IMPLIED>
<!-- ========== CLIENT PHASES NODE ========================= -->
<!ELEMENT scheduler (duration,module+)>
  <!ELEMENT duration (#PCDATA)>
  <!ATTLIST duration
    unit ( s | m | h | d ) "m">
  <!ELEMENT module (client+)>
  <!ATTLIST module
    name NMTOKEN #REQUIRED
    enabled ( true | false ) "true">
    <!ELEMENT client ANY>
    <!ATTLIST client
      id NMTOKEN #IMPLIED
      name ( searchLoad | modifyLoad | restartDs) "searchLoad"
      host NMTOKEN #IMPLIED
      start NMTOKEN #IMPLIED
      stop NMTOKEN #IMPLIED
      dependencyId CDATA #IMPLIED>
  <!ELEMENT serverInstance (#PCDATA)>
  <!ELEMENT baseDn (#PCDATA)>
  <!ELEMENT nbCnx (#PCDATA)>
  <!ELEMENT nbMaxSearch (#PCDATA)>
  <!ELEMENT attribute (#PCDATA)>
opends/tests/system-tests/scenario/sample/conf.xml
New file
@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE systemTestConfiguration SYSTEM "../conf.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 2008 Sun Microsystems, Inc.
 ! -->
<!-- This conf.xml file is an example, to run it, -->
<!-- replace variable NEED_VALUE                  -->
<systemTestConfiguration>
  <!-- ================= Global Parameters ===================== -->
  <!-- =============  Should be the first node   =============== -->
  <globalParameters>
    <scenario>
      <name>Sample</name>
      <description>This is an example</description>
    </scenario>
    <opendsName>OpenDS-1.0.0</opendsName>
    <opendsZip>NEED_VALUE</opendsZip>
    <domain>NEED_VALUE</domain>
  </globalParameters>
  <!-- ================= Instance ============================== -->
  <instance name="I1" product="opends">
    <host>NEED_VALUE</host>
    <installDir>NEED_VALUE</installDir>
  </instance>
  <!-- ================= Instance ============================== -->
  <instance name="I2" product="opends">
    <host>NEED_VALUE</host>
    <installDir>NEED_VALUE</installDir>
  </instance>
  <!-- ================= Suffix  ============================== -->
  <suffix dn="dc=com">
    <topology>
        <element instanceName="I1" initRule="importLdif"/>
      <element instanceName="I2" initRule="totalUpdate"
               instanceSourceName="I1"/>
    </topology>
    <tree nbOfEntries="50">
      <branch name="ou=france,dc=com">
        <branch name="ou=QA Engineers,ou=france,dc=com">
          <subordinateTemplate type="inetOrgPerson" percentage="30"/>
        </branch>
        <branch name="ou=Accounting,ou=france,dc=com">
          <subordinateTemplate type="organizationalPerson" percentage="30"/>
        </branch>
        <branch name="ou=Managers,ou=france,dc=com">
          <subordinateTemplate type="person" nb="1"/>
        </branch>
        <branch name="ou=Engineers,ou=france,dc=com">
          <subordinateTemplate type="person" percentage="40"/>
        </branch>
      </branch>
    </tree>
  </suffix>
  <!-- ================= Scheduler  =========================== -->
  <!-- [1] duration must be more than 1 minute                  -->
  <!-- [2] dependencyId is a list of client id ie : 1,2         -->
  <!--     if using it, specify id attribute for each clients   -->
  <scheduler>
    <duration unit="m">4</duration>
    <!--== Module 1 ==-->
    <module name="search" enabled="true">
      <client id="1" name="searchLoad" host="NEED_VALUE" start="t30"
                                                         stop="t60">
        <serverInstance>I1</serverInstance>
        <baseDn>dc=com</baseDn>
        <nbCnx>5</nbCnx>
        <nbMaxSearch>5</nbMaxSearch>
        <attribute>sn</attribute>
      </client>
      <client id="2" name="searchLoad" host="NEED_VALUE" start="t0"
                                                         stop="t50">
        <serverInstance>I2</serverInstance>
        <baseDn>dc=com</baseDn>
        <nbCnx>5</nbCnx>
        <nbMaxSearch>5</nbMaxSearch>
        <attribute>sn</attribute>
      </client>
    </module>
    <!--== Module 2 ==-->
    <module name="restart_and_modify" enabled="true">
      <client id="3" name="restartDs" host="NEED_VALUE" start="t50"
                                                        dependencyId="1">
        <serverInstance>I2</serverInstance>
        <baseDn>dc=com</baseDn>
        <nbCnx>5</nbCnx>
        <nbMaxSearch>5</nbMaxSearch>
        <attribute>sn</attribute>
      </client>
      <client id="4" name="modifyLoad" host="NEED_VALUE" start="t60"
                                                         stop="t100">
        <serverInstance>I1</serverInstance>
        <baseDn>dc=com</baseDn>
        <nbCnx>5</nbCnx>
        <nbMaxSearch>5</nbMaxSearch>
        <attribute>sn</attribute>
      </client>
    </module>
  </scheduler>
</systemTestConfiguration>
opends/tests/system-tests/scenario/sample/sample.xml
New file
@@ -0,0 +1,54 @@
<?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 2008 Sun Microsystems, Inc.
 ! -->
<stax>
  <defaultcall function="mainSample"/>
  <function name="mainSample">
      <sequence>
        <import machine="'%s' % (STAF_LOCAL_HOSTNAME)"
          file="'%s/phases/main_run.xml' % (TESTS_DIR)"/>
        <!-- directoryName must have the name of the current directory -->
        <script>
          dirName  = 'sample'
          confFile = '%s/scenario/%s/conf.xml' % (TESTS_DIR,dirName)
        </script>
        <call function="'main_run'">
        {
         'configurationFile': confFile,
         'runInstallation'  : 'true',
         'runGenerateLdif'  : 'true',
         'runConfiguration' : 'true',
         'runScheduler'     : 'true'
        }
        </call>
    </sequence>
  </function>
</stax>