1 Using Autorun to Execute Startup Tasks

This chapter provides an introduction to the EDQ autorun functionality, which allows EDQ to load projects and run jobs when the application server starts up. It explains how the autorun functionality is configured, introduces the chore types that can be performed by using the autorun facility and provides examples of autorun scripts.

This chapter includes the following sections:

Understanding Autorun

EDQ can be configured to do the following automatically at startup:

  • Perform a range of tasks when the application server starts up. Each task, which is composed of chores, can be configured to be performed every time the application server is started, or just once the next time the application server is started.

  • Load and apply purge rules that override the purge settings that are stored in the EDQ server.

To use autorun processing, you place autorun scripts, written in XML, that specify tasks in one of two specific directories in the EDQ installation:

  • startup directory: Scripts in the startup directory are processed every time the EDQ application server starts up.

  • onceonly directory: Scripts in the onceonly directory are processed when the EDQ application server next starts up, and are then moved to the complete subdirectory within onceonly. Scripts in the complete directory are not processed on subsequent start ups.

When the application server starts up, EDQ checks the onceonly and startup directories for autorun scripts and processes any that are present.

The startup and onceonly directories are located in the EDQ autorun directory in the local configuration directory of the application server, oedq.local.home.

Using the Autorun Chores

Various kinds of autorun chores are available in EDQ, each with a set of XML attributes specific to its function. The chore types and their available attributes are defined by the autorun file XML schema, see Understanding the Chore and Rules Schemas. The chores available are listed in the following table:

Chore Type What the Chore Does

httpget

Downloads files from a web server.

package

Loads a project from a .dxi file into the server, or saves a project on the server into a .dxi file. If no nodes are specified then the contents of the whole file, including system level components, are loaded into the server.

load

Loads a file, for example a purge rules configuration file. This chore is valid only in the startup directory. See using_autorun.html#GUID-E65CEC27-3777-4BCE-8546-A9ABF4266854__BABCGHFA for how to use the load chore with the Rules schema to load purge rules.

runjob

Runs an existing job from Director. Any run labels in a run profile specified in this chore are ignored. (Use runopsjob to run a job based on a run label.)

runopsjob

Runs an existing job from the EDQ Server Console and requires a run label to be set, either in the run profile or with the runlabel attribute.

dbscript

Runs a database script against the Director database. This kind of chore must only be used with extreme care, as inappropriately applied scripts may corrupt the underlying database.

sleep

Waits for a specified interval before proceeding.

Using the Autorun Scripts

Autorun scripts are files that contain XML code. The main part of an autorun script consists of a list of chores, each bounded by <chores> tags. Each chore is of one of the autorun chore types listed in Using the Autorun Chores and includes a set of attributes that specify the chore to be performed. The attributes available depend on the chore type selected.

The XML schema that is used to structure autorun scripts is shown in full in Understanding the Chore and Rules Schemas.

Examples

This section shows some examples of autorun scripts.

Example 1   

The following XML code shows a sample autorun script that instructs EDQ to:

  • Download the 23People.dxi file, overwriting any existing file with the same name.

  • Import the 23People project from the 23People.dxi file, overwriting any existing project with the same name.

  • Run the 23People Excel.23People job with the rp1 run profile. Any run label specified in the profile will be ignored, because this is not a runopsjob chore.

<?xml version="1.0" encoding="UTF-8"?>
 <chores version="1">
  <!-- Get the dxi file -->
    <httpget overwrite="true" todir="dxiland" tofile="23People.dxi">
      <url>http://svn/repos/dev/trunk/benchmark/ benchmark/dxis/23People.dxi</url>
  </httpget>
  <!-- Import the project from the dxi -->
    <package direction="in" dir="dxiland" file="23People.dxi" overwrite="true">
      <node type="project" name="23People"/>
    </package>
    <!-- Run the jobs -->
    <runjob project="23People" job="23People Excel.23People" runprofile="rp1"
      waitforcompletion="true"/>
 </chores>
Example 2   

The following XML code shows a sample autorun script that shows four different ways to use a runjob or runopsjob chore to run a job.

<?xml version="1.0" encoding="UTF-8"?>
<chores version="1">
  <!-- runs a director job with no runlabel -->
  <runjob project="merge" job="tester" waitforlocks="false" 
    waitforcompletion="false" runprofile="x"/>
  <!-- runs an ops job with the runlabel from the runprofile -->
  <runopsjob project="merge" job="tester" waitforlocks="false"
    waitforcompletion="false" runprofile="x" />
  <!-- runs an ops job with the runlabel from the runlabel attribute-->
  <runopsjob project="merge" job="tester" waitforlocks="false"
     waitforcompletion="false" runprofile="x" runlabel="chooseme" />
  <!-- runs an ops job with the runlabel from the runlabel attribute-->
  <runopsjob project="merge" job="tester" waitforlocks="false"
     waitforcompletion="false" runlabel="onlychoice" />
</chores>
Example 3   

The following XML code shows how to use a load chore to load purge rules.

<?xml version="1.0" encoding="UTF-8" ?> 
<chores version="1">
  <load file="purgerules.xml" dir="autorun" type="purgeRules" /> 
</chores>

The following are the purge rules in the purgerules.xml file that is loaded in the chore specification:

<?xml version="1.0" encoding="UTF-8" ?>
- <rules>
  - <rule displayName="testa" enabled="true">
      <purgePeriod period="1" unit="HOURS" />
      <project>aa</project>
      <job>12345</job>
      <runlabelMatcher regex="false" runlabel="ABCD" />
  </rule>
  - <rule displayName="testb" enabled="true">
      <purgePeriod period="1" unit="HOURS" />
      <project>aa</project>
      <job>ABCD</job>
      <runlabelMatcher regex="true" runlabel="^\d{5}$" />
  </rule>
- <rule displayName="testc" enabled="true">
  <purgePeriod period="2" unit="HOURS" />
      <project />
      <job />
      <runlabelMatcher regex="true" runlabel="TEST" />
  </rule>
- <rule displayName="testd" enabled="true">
      <purgePeriod period="3" unit="WEEKS" />
      <project />
      <job />
      <runlabelMatcher regex="true" runlabel="TEST" />
  </rule>
  - <rule displayName="teste" enabled="false">
      <purgePeriod period="999" unit="MONTHS" />
      <project />
      <job />
      <runlabelMatcher regex="true" runlabel="^\d{5}$" />
  </rule>
  - <rule displayName="testf" enabled="true">
      <purgePeriod period="1" unit="HOURS" />
      <project />
      <job />
      <runlabelMatcher regex="true" runlabel="^\d{5}$" />
  </rule>
  - <rule displayName="testg" enabled="true">
      <purgePeriod period="1" unit="DAYS" />
      <project />
      <job />
      <runlabelMatcher regex="false" runlabel="ABCD" />
  </rule>
</rules>

Understanding the Chore and Rules Schemas

This section shows the Chores and Rules XML schemas.

Understanding the Chores Schema

This schema explains the chores listed in Using the Autorun Chores.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
 
  <!-- Chores -->
  <xs:element name="chores">
    <xs:complexType>
    
      <!-- 
      List of chores that need to be performed.  The chores will be performed 
      in the order
      specified in the xml file
      -->
      <xs:choice minOccurs="0" maxOccurs="unbounded">
 
        <xs:element name="httpget"     type="httpgetType"/>
        <xs:element name="package"     type="packageType"/>
        <xs:element name="runjob"      type="runjobType"/>
        <xs:element name="runopsjob"   type="runopsjobType"/>
        <xs:element name="dumpdb"      type="dumpdbType"/>
        <xs:element name="dbscript"    type="dbScriptType"/>
        <xs:element name="sleep"       type="sleepType"/>
        <xs:element name="load"        type="loadType"/>
      </xs:choice>
      
      <!-- Schema version number -->
      <xs:attribute name="version" type="xs:positiveInteger" use="required"/>
      
    </xs:complexType>
  </xs:element>
 
  <!-- Base type for chores -->
  <xs:complexType name="choreType">
  
    <!-- Flag indicating whether we should wait for completion before moving 
    on to the next chore. -->
    <xs:attribute name="waitforcompletion" type="xs:boolean" 
    use="optional" default="true"/>
  </xs:complexType>
  
  <!-- HTTP Get chore.  Download the specified urls. -->
  <xs:complexType name="httpgetType">
    
    <xs:complexContent>
      <xs:extension base="choreType">
      
        <xs:sequence minOccurs="1" maxOccurs="1">
          <!-- URL to download. -->
          <xs:element name="url" type="xs:string"/>
        </xs:sequence>
        
        <!-- Filename to download to. -->
        <xs:attribute name="tofile" type="xs:string" use="required"/>
        
        <!-- 
        Directory to download the files to.
          - relative path is relative to the config dir
          - absolute path is used as is
          - no path indicates the config dir   
        -->
        <xs:attribute name="todir" type="xs:string" use="optional"/>
        
        <!-- If true existing files are overwritten, otherwise download is 
        not performed. -->
        <xs:attribute name="overwrite" type="xs:boolean" use="optional"
        default="true"/>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  
  <!-- dxi file control chore.  Import or export to/from a dxi file. -->
  <xs:complexType name="packageType">
    
    <xs:complexContent>
      <xs:extension base="choreType">
 
        <!-- List of root level nodes to import/export.  
        An empty list indicates 'all'. -->      
        <xs:sequence minOccurs="0" maxOccurs="unbounded">
          <xs:element name="node" type="packageNodeType"/>
        </xs:sequence>
        
        <!-- dxi filename. -->
        <xs:attribute name="file" type="xs:string" use="required"/>
        
        <!--  
        Directory that the dxi is in.
          - relative path is relative to the config dir
          - absolute path is used as is
          - no path indicates the config dir   
        -->
        <xs:attribute name="dir" type="xs:string" use="optional"/>
        
        <!-- If true existing files/nodes are overwritten,
        otherwise no operation. -->
        <xs:attribute name="overwrite" type="xs:boolean" 
        use="optional" default="true"/>
        
        <!-- Direction: in=import out=export -->
        <xs:attribute name="direction" type="packageDirectionEnum"
        use="required"/>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  
  <!-- Package node for import or export from/to a dxi. -->
  <xs:complexType name="packageNodeType">
    
    <!-- the type of the node to process -->
    <xs:attribute name="type" type="nodeTypeEnum" use="required"/>
    
    <!-- the name of the node to process -->
    <xs:attribute name="name" type="xs:string" use="required"/>
  </xs:complexType>
 
  <!-- db script control chore.  Runs db script against the configuration database. -->
  <xs:complexType name="dbScriptType">
    
    <xs:complexContent>
      <xs:extension base="choreType">
        
        <!-- db script filename. -->
        <xs:attribute name="file" type="xs:string" use="required"/>
        
        <!--  
        Directory that the db script is in.
          - relative path is relative to the config dir
          - absolute path is used as is
          - no path indicates the config dir   
        -->
        <xs:attribute name="dir" type="xs:string" use="optional"/>
        
        <!-- The database to run the script against -->
        <xs:attribute name="database" type="databaseEnum" use="required"/>
                
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
    
  <!-- Invoke named job chore.  Run a named job -->
  <xs:complexType name="runjobType">
    <xs:complexContent>
      <xs:extension base="choreType">
        
        <!-- Project name -->
        <xs:attribute name="project" type="xs:string" use="required"/>
        
        <!-- Job name -->
        <xs:attribute name="job" type="xs:string" use="required"/>
        
        <!-- Wait for locks flag - default to true -->
        <xs:attribute name="waitforlocks" type="xs:boolean" 
        use="optional" default="true"/>
        
        <!-- Optional run profile -->
        <xs:attribute name="runprofile" type="xs:string" use="optional"/>
        
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  
  <xs:complexType name="runopsjobType">
    <xs:complexContent>
      <xs:extension base="runjobType">
      
        <!-- Optional run label (will override run profile run label if set) -->
        <xs:attribute name="runlabel" type="xs:string" use="optional"/>
        
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  
  <!--
    Dump the database.
  -->
  <xs:complexType name="dumpdbType">
    <xs:complexContent>
      <xs:extension base="choreType">
        
        <!-- Output JMP file for config database -->
        <xs:attribute name="configout" type="xs:string" use="required"/>
        
        <!-- Output JMP file for results database -->
        <xs:attribute name="resultsout" type="xs:string" use="required"/>
        
        <!--  
        Directory that the JMP files are written to
          - relative path is relative to the config dir
          - absolute path is used as is
          - no path indicates the config dir   
        -->
        <xs:attribute name="dir" type="xs:string" use="optional"/>
        
        <!--
        TODO: Add some filtering to allow dumping of categories of data
        e.g. staged data, results data, case management data, etc.
        -->
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  
  <!-- Load a certain file to do a certain thing. Eg change purge rules. -->
  <xs:complexType name="loadType">
    <xs:complexContent>
      <xs:extension base="choreType">        
        <!-- type of action to run with file -->
        <xs:attribute name="type" type="loadTypeEnum" use="required"/>
        
        <!-- filename -->
        <xs:attribute name="file" type="xs:string" use="required"/>
        
        <!--  
        Directory that the file is in.
          - relative path is relative to the config dir
          - absolute path is used as is
          - no path indicates the config dir   
        -->
        <xs:attribute name="dir" type="xs:string" use="optional"/>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  
  <!--  Enumeration of databases  -->
  <xs:simpleType name="databaseEnum">
    <xs:restriction base="xs:string">
        <xs:enumeration value="director"/>
        <xs:enumeration value="results"/>
    </xs:restriction>
  </xs:simpleType>
  
  <!-- Enumeration of valid node types -->
  <xs:simpleType name="nodeTypeEnum">
    <xs:restriction base="xs:string">
      <xs:enumeration value="project"/>
      <!-- Probably need to do these sometime
      <xs:enumeration value="resource"/>
      <xs:enumeration value="datastore"/>
      -->
    </xs:restriction>
  </xs:simpleType>
  
  <!-- Enumeration of packaging direction. -->
  <xs:simpleType name="packageDirectionEnum">
    <xs:restriction base="xs:string">
      <xs:enumeration value="in"/>
      <xs:enumeration value="out"/>
    </xs:restriction>
  </xs:simpleType>
  
  <!-- Enumeration of types of things that can be loaded. -->
  <xs:simpleType name="loadTypeEnum">
    <xs:restriction base="xs:string">
      <xs:enumeration value="purgeRules"/>
      <!-- <xs:enumeration value="schedule"/> -->
    </xs:restriction>
  </xs:simpleType>
  
    <!-- Sleep chore.  Wait for a while before doing other autorun stuff -->
  <xs:complexType name="sleepType">
    
    <xs:complexContent>
      <xs:extension base="choreType">
        
        <!-- seconds to wait. -->
        <xs:attribute name="time" type="xs:integer" use="required"/>
 
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  
</xs:schema>

Understanding the Rules Schema

This section describes the Rules schema, which provides the basis for structuring an XML script that specifies EDQ server purge rules. Use the load chore to load the script at EDQ startup.

<?xml version="1.0" encoding="UTF-8"?>
 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
 
  <!-- Common types -->
  <!-- ============ -->
  <xs:include schemaLocation="urn:commontypes.xsd"/>
 
  <xs:element name="rules" type="rulesType">
    <!-- Rule name must be unique -->
    <xs:key name="rule.name">
      <xs:selector xpath="rules/rule"/>
      <xs:field    xpath="@name"/>
    </xs:key>
  </xs:element>
 
  <!--  Rules  -->
 
  <xs:complexType name="rulesType">
    <xs:sequence>
      <xs:element name="rule" type="ruleType" minOccurs="0"
        maxOccurs="unbounded"/>
    </xs:sequence>
    
    <xs:attribute name="schemaversion" type="xs:positiveInteger" 
       use="optional" default="1"/>
  </xs:complexType>
 
  <xs:complexType name="ruleType">
    <xs:sequence>
      <xs:element name="purgePeriod"     type="periodType"   minOccurs="1"
         maxOccurs="1"/>
      <xs:element name="project"         type="xs:string"    minOccurs="0"
         maxOccurs="1"/>
      <xs:element name="job"             type="xs:string"    minOccurs="0"
         maxOccurs="1"/>
      <xs:element name="runlabelMatcher" type="runlabelType" minOccurs="0"
         maxOccurs="1"/>
    </xs:sequence>
    
    <!-- name -->
    <xs:attribute name="displayName"    type="xs:string"  use="required"/>
    <!-- whether this rule should be applied -->
    <xs:attribute name="enabled" type="xs:boolean" use="required"/>
  </xs:complexType>
  
  <!-- Runlabel -->
  
  <xs:complexType name="runlabelType">
    <xs:attribute name="regex"    type="xs:boolean" use="required"/>
    <xs:attribute name="runlabel" type="xs:string"  use="required"/>
  </xs:complexType>
 
  <!-- Purge Period -->
  
  <xs:complexType name="periodType">
    <xs:attribute name="period" type="xs:int" use="optional"/>
    <xs:attribute name="unit" type="periodUnitType" use="required"/>
  </xs:complexType>
 
  <!-- Purge Unit types -->
 
  <xs:simpleType name="periodUnitType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="IMMEDIATE"/>
      <xs:enumeration value="HOURS"/>
      <xs:enumeration value="DAYS"/>
      <xs:enumeration value="WEEKS"/>
      <xs:enumeration value="MONTHS"/>
      <xs:enumeration value="NEVER"/>
    </xs:restriction>
  </xs:simpleType>
 
</xs:schema>