-- MicheleDibenedetto - 18-Feb-2010

Introduction

The ETICS SA2 team has designed and developed a Java-based architecture that enables to the ETICS Configuration Web Service
to interact with job submission in easily, providing a well-defined interface to each of
the principal submission operations (like submit a job, query a job status, cancel a job submission) available via
the Web Service implementation.
The provided ETICS Submission Web Service (ESWS) architecture allows the service consumer to interact with
different job submission environments transparently, hiding the complexity of each environment
(Glite, Nmi, ecc) behind the simple WSDL exposed. The ESWS architecture has been designed in order to be
extensible to other submission environments that can be easily plugged in implementing few self describing
Java Interfaces intended to provide the execution of typical job operations and alimenting the self-configuring
engine with a factory getter class.

Implementation

In order to plug a new submitter in the ESWS you must follow the following steps.
Your implementation must use Java JDK 1.5.0-12.

Those guidelines are referred to plugin interface version 0.9.5-1.
The interface jar can be downloaded from ETICS. It is the component org.etics.submission.common

(Note: if you would like to use a command line client to implement the job operations go to the appendix of this document)

Step 1

Extend the Abstract Class eu.eticsproject.submission.resources.GeneralJobStatus to a Class
<YourSubmitterName>JobStatus in the package eu.eticsproject.submission.resources.<yourSubmitterName>
This Class is intended to enable ESWS to know which name is assigned to job life-cycle statuses in your submitter.
Extending the Abstract Class you have to provide a non-arguments empty constructor.
Then for each inherited method you must return an array of strings representing the names
of the job statuses that represent a completed status, a running status and so on as shown from method's signature
(e.g. for the method getSuccessStatus() you have to return the array [“MySuccessStatus” , “MyOtherSuccessStatus”]
if in your submission environment each of these two strings represent a Success job status).
If in your submission environment there is not anything like one or more of the requested statuses
you symply have to return null.
ESWS requires that you returns a non null statuses string array for the getSuccessStatus(), getFailedStatus() and getRunningStatus() methods.
All your status strings have to be returned in one of the implemented methods.
You cannot return the same status string in more than one inherited method implementation.
Let's inspect the required statuses and their meaning:

  • The "Pending" status is the status of a job that has been submitted but is not running on a worker node yet
  • The "Running" status is the status of a job that is runnig on a worker node
  • The "Success" status is the status of a job that has completed its execution with a zero return code. It has produced the output of a build or test that has "Success" as result
  • The "Failed" status is the status of a job that has completed its execution with a not zero return code. It has produced the output of a build or test that has "Failed" as result
  • The "Removed" status is the status of a job that has been canceled
  • The "Aborted" status is the status of a job that has not completed its execution and cannot provide the build or test results
  • The "Unknown" status is the status that has to be used when the actual status of the job is not known

After having implmented this Class you have to provide a Factory Class to it by implementing the Interface eu.eticsproject.submission.resources.JobStatusFactory.
It will be a simple Factory Class, let’s see a sample.

The JobStatusFactory Interface looks like this:

public interface JobStatusFactory {

     public GeneralJobStatus createStatus();

}

Your implementation will be something like

public class YourSubmitterNameJobStatusFactory implements JobStatusFactory {

     public GeneralJobStatus createStatus() {

        return new YourSubmitterNameJobStatus();

    }

}

Step 2

Implement the Interfaces:

  • JobSubmit
  • JobGetStatus
  • JobCancel
  • JobGetOutput

from the package eu.eticsproject.submission.operation in a package
eu.eticsproject.submission.operation.<yourSubmitterName>

The Job<Something> Interfaces, hereafter called job operation Interfaces,
are intended to be the bridge between the ESWS architecture and your submitter.
Each job operation Interface has a method to be implemented that
will execute one of the four basic submitter operation in your implementation: submit a job,
query the status of a job, cancel a job submission, retrieve the output of a completed job.
The JobSubmit interface has a further method to be implemented, which requests
the submitter plugin to check if it is able to satisfy the provided submission requirements.
Doing so a job that cannot be executed is not submitted at all.
The logic of your submitter is confined here.

Let’s inspect the Interfaces to understand how they have to be implemented.
Here is the JobSubmit Interface:

public interface JobSubmit {

     /**
      * @param platform the ETICS platform on which to submit the job
      * @param configuration the component configuration to be builded or tested
      * @param build if true a build has to be submitted, if false a test
      * @param checkoutOptions the options to be appended to the checkout command
      * @param buildTestOptions the options to be appended to the build or test command
      * @param environmentVariables the variables to be added to execution environment
      * @param runAsRoot if true the job has to be executed as root
      * @param enableIPv6 if true the job has to be executed with IPv6 support
      * @param privateResource if true the job has to be run on private resources
      * @param freezeTime if greater than 0 job results has to be maintained for the specified amount of minutes
      * @param privateResult if true the job results on the repository has to be private
      * @param virtual if true the ETICS vmloader has to be used
      * @param clientUrl the URL from which the ETICS client setup has to be downloaded
      * @param user the user requesting the build or test
      * @param serverHost the ETICS server host to be used to checkout the component configuration
      * @param workDirectory a temporary folder that can be used to store temporary files
      * @return an ID identifying the job uniquely
      * @throws IllegalArgumentFault if arguments are not correct
      * @throws SubmissionErrorFault if an error occurs during job submission
      */
     public String submit(String platform, Configuration configuration, boolean build, String checkoutOptions,
        String buildTestOptions, Map<String, String> environmentVariables, boolean runAsRoot,
        boolean enableIPv6, boolean privateResource, long freezeTime, boolean privateResult,
        boolean virtual, String clientUrl, User user, String serverHost, String workDirectory)
        throws IllegalArgumentFault, SubmissionErrorFault;

     /**
      * @param platform the ETICS platform for which to check the requirements
      * @param runAsRoot if true runAsRoot requirement has to be supported on the provided platform
      * @param enableIPv6 if true enableIPv6 requirement has to be supported on the provided platform
      * @param privateResource if true privateResource requirement has to be supported on the provided platform
      * @param freeze if true freeze requirement has to be supported on the provided platform
      * @param privateResult if true privateResult requirement has to be supported on the provided platform
      * @param virtual if true virtual requirement has to be supported on the provided platform
      * @throws IllegalArgumentFault if arguments are not correct
      * @throws SubmissionErrorFault if an error occurs during requirements checking
      * @throws SubmissionNotSupportedFault if one or more requirements are not satisfied
      */
     public void checkRequirements(String platform, boolean runAsRoot, boolean enableIPv6,
        boolean privateResource, boolean freeze, boolean privateResult, boolean virtual)
        throws IllegalArgumentFault, SubmissionErrorFault, SubmissionNotSupportedFault;

}

It has to be implemented as follows

public class SomeJobSubmit implements JobSubmit {

     public String submit(String platform, Configuration configuration, boolean build, String checkoutOptions,
        String buildTestOptions, Map<String, String> environmentVariables, boolean runAsRoot,
        boolean enableIPv6, boolean privateResource, long freezeTime, boolean privateResult,
        boolean virtual, String clientUrl, User user, String serverHost, String workDirectory)
        throws IllegalArgumentFault, SubmissionErrorFault{

       logger.debug( "Submitting on platform " + platform);
       /* Do what you need to do to submit a job to your submitter given
        * the info in the parameters*/

       /* Return the unique id generated by your submitter for this job
        * submission to be used in next interactions with it */

       logger.debug( "Submitted the job for platform " + platform + " as " + someID);
       return someID;

   }

     public void checkRequirements(String platform, boolean runAsRoot, boolean enableIPv6,
        boolean privateResource, boolean freeze, boolean privateResult, boolean virtual)
        throws IllegalArgumentFault, SubmissionErrorFault, SubmissionNotSupportedFault {

       logger.debug( "Checking provided submission requirements for platform " + platform);
       /* Check if your submitter satisfies the requirements provided
        * as parameters on the requeted platform */

       /* If one or more of the requirements is not provided on the platform or
        * the platform itself is not available at all throw a
        * SubmissionNotSupportedFault exception */

       if(runAsRoot)
       {
          logger.debug("Has been requested the possibility to sun a submission as root"
                     + " on platform " + platform);
          if(platform.equals("somePlatform")
          {
             /* As sample here runAsRoot is not supported */
             throw new SubmissionNotSupportedFault(""Error! Run as root is not supported"
                     + " on platform somePlatform!");
          }
       }
       logger.debug( "Requirements are satisfied on platform " + platform);

   }

}

This interface provides two methods: submit() and checkRequirements()

The implementation of the checkRequirements() method has to check if the requested requirements are satisfacted on the provided platform.
If any of them is not satisfied a SubmissionNotSupportedFault exception has to be thrown

The implementation of the submit() method has to submit a new job on your submission engine
that executes the following operations:

  • downloads the ETICS client from URL provided as clientUrl parameter
  • exports all the environment variables provided environmentVariables as parameter where this is a map variableName-variableValue
  • installs the ETICS client by executing the downloaded python setup script
  • sets the ETICS_HOME environment variable
  • sets the ETICS server to the value of serverHost the parameter
  • creates a workspace folder and executes the etics-workspace-setup command on it
  • executes the etics-get-project command on the project specified inside the configuration parameter
  • executes the etics-checkout command on the module and configuration specified inside the configuration parameter with options provided with parameter checkoutOptions
  • if the build parameter is true, executes the etics-build command on the module specified inside the configuration parameter provided options provided with parameter buildTestOptions
  • if the build parameter is false, executes the etics-test command on the module specified inside the configuration parameter provided options provided with parameter buildTestOptions
  • finally creates a tar.gz of the workspace dist and report folders and of the etics.log file, called workspace.tar.gz

Depending on the received requirements the job have to:

  • be executed as root user if the runAsRoot requirement is true
  • use IPv6 adressing if the enableIPv6 requirement is true
  • do not delete job results according to minutes as specified in freezeTime requirement if this is greater than 0

The following requirements are not yet completely supported. So you have to throw a SubmissionErrorFault execption if requested.

  • use the ETICS vmloader to load a proper virtual machine to execute job if the requirement virtual is true
  • use private resources if the privateResource requirement is true
  • reduce visibility of result on the repository if the privateResult requirement is true

The string that is returned by the submit() method (hereafter called submitterId) will be used in the subsequent
interaction with the submitter to refers to the submitted job.

Here is the JobGetStatus Interface:

public interface JobGetStatus {

     /**
      * Retrieves the status of the job identified by submitterId
      *
      * @param submitterId the Submitter Id of a submitted job
      * @return a String representing the status of the job
      * @throws GetStatusErrorFault if an error occurs during status retrieving
      */
     public String getStatus(String submitterId) throws GetStatusErrorFault;

}

It has to be implemented as follows

public class SomeJobGetStatus implements JobGetStatus {

     public String getStatus(String submitterId) throws GetStatusErrorFault {
       logger.debug("Requested retrieving the status for job " + submitterId);

       /* Do what u need to retrieve the status of the
        * job identified by the unique ID submitterId */

       String status = ...
       return status;

   }
}

In the implementation of the getStatus() method the string that is returned MUST match with one of the status name that you have specified in the methods of your Class extending eu.eticsproject.submission.resources.GeneralJobStatus.

The JobCancel Interface is similar to the previous:

public interface JobCancel {

     /**
      * Cancel a previously submitted job
      *
      * @param submitterId the Submitter Id of a submitted job
      * @throws CancelErrorFault if an error occurs during job cancelation
      */
     public void cancel(String submitterId) throws CancelErrorFault;

}

It has to be implemented as follows

public class SomeJobCancel implements JobCancel {

     public void cancel(String submitterId) throws CancelErrorFault {
       logger.debug("Requested cancelling the job " + submitterId);

       /* Do what u need to cancel the job identified
        * by the unique ID submitterId */

   }
}

ESWS will never ask for the cancel of a job that has not been previously submitted neither ask for the cancel of a single job no more than one time

instead the JobGetOutput Interface
is quite different because as parameter to the method invocation it specifies the directory path
where you have to put the retrieved output:

public interface JobGetOutput {

     /**
      * Retrieves the output generated by the job identified by the provided
      * Submitter Id and stores it in the provided directory outputDirectory
      *
      * @param submitterId the id of a completed job
      * @param outputDirectory an existent directory
      * @throws SubmissionOutputException if an error occurs during job output retrieving
      */
     public void getOutput(String submitterId, String outputDirectory) throws SubmissionOutputException ;

}

It has to be implemented as follows

public class SomeJobGetOutput implements JobGetOutput {

     public void getOutput(String submitterId, String outputDirectory) throws SubmissionOutputException {
       logger.debug("Requested retrieving the output of job " + submitterId " in folder " + outputDirectory);

       /* Do what u need to retieve the generated workspace.tar.gz
        * archive produced by the job identified by the unique ID submitterId
        * and put it in the provided folder */

   }
}

The implementation of the getOutput() method has to put the workspace.tar.gz file probuced by the build in the folder specified as paramether.
This method will be invoked by ESWS only when invoking the get status method it obtains a Success status or a Failed status.

Step 3

Implement the Interfaces:

  • JobSubmitFactory
  • JobGetStatusFactory
  • JobCancelFactory
  • JobGetOutputFactory

The Java Interfaces named Job<Something>Factory have only the create<Something>() method in which <Something> is one of the four job operations.
They have to be implemented as simple Factory Classes for the respective operation interface implementation.
They provide a new instance of the job operation object on demand.

Let’s see as sample the JobSubmitFactory Interface:

public interface JobSubmitFactory {

     public JobSubmit createJobSubmit();

}

It has to be implemented as follows

public class SomeJobSubmitFactory implements JobSubmitFactory {

     public JobSubmit createJobSubmit() {
       return new SomeJobSubmit();
   }

}

where SomeJobSubmit is your implementation of the JobSubmit Interface

Step 4

Finally you have to extend the Abstract Class eu.eticsproject.submission.implementation.AbstractImplementation
to a Class named <YourSubmitterName>Implementation in the package
eu.eticsproject.submission.implementation.<yourSubmitterName> providing a non-arguments empty constructor.
This Class is needed by ESWS to be able to get all your Factory Class implementations.

The Abstract Class eu.eticsproject.submission.implementation.AbstractImplementation looks as follows

public abstract class AbstractImplementation implements Implementation {

     [...]

     public abstract Integer getSubmitterCode() ;

     protected abstract JobGetStatusFactory getJobGetStatusFactory();

     protected abstract JobSubmitFactory getJobSubmitFactory();

     protected abstract JobGetOutputFactory getJobGetOutputFactory();

     protected abstract JobCancelFactory getJobCancelFactory();

     protected abstract JobStatusFactory getJobStatusFactory() ;

}

For each of the get<Something>Factory() methods you have to return a new instance of the proper
Factory Class created in the previous steps. For the method getSubmitterCode() you have to return
the integer value that will be assigned to your submitter implementation.

Your implementation <YourSubmitterName>Implementation will look like this:

public class YourSubmitterNameImplementation extends AbstractImplementation {

     /**
     * The submitter code associated to your submitter submitter
     */

     public static final Integer CODE = new Integer(2);

     @Override
     protected JobCancelFactory getJobCancelFactory() {
       return new YourSubmitterNameJobCancelFactory();
   }

     @Override
     protected JobGetOutputFactory getJobGetOutputFactory() {
       return new YourSubmitterNameJobGetOutputFactory();
   }

     @Override
     protected JobGetStatusFactory getJobGetStatusFactory() {
       return new YourSubmitterNameJobGetStatusFactory();
    }

     @Override
     protected JobSubmitFactory getJobSubmitFactory() {
       return new YourSubmitterNameJobSubmitFactory();
    }

     @Override
     protected JobStatusFactory getJobStatusFactory() {
       return new YourSubmitterNameStatusFactory();
    }

     @Override
     public Integer getSubmitterCode() {
       return CODE;
    }

The name of the created Implementation Class with its full package name
is used to configure ESWS to use your newly created submitter plugin.

That’s enough, if everything is correct it will works!

Appendix

If you like to use a command line client to implement the job operations
the ESWS architecture provides some commodity Classes that helps your development
in the package eu.eticsproject.submission.operation.cli.commandline. After step 1 you have to
substitute step 2 with the following step 2.1.

Step 2.1

For each job operation we have an Abstract Class:

  • CommandLineJobSubmit
  • CommandLineJobGetStatus
  • CommandLineJobCancel
  • CommandLineJobGetOutput

located in package eu.eticsproject.submission.operation.cli.commandline You have to extend those Abstract Classes.
All those Abstract Classes inherits from the Interface
eu.eticsproject.submission.operation.cli.Operation the method getCommand(). This method has to be implemented by your implementation Classes and has to return a string representing the command line command that have to be executed. It looks as follows:

public interface Operation {

     ...

     public abstract String getCommand();

}

NOTE: you ONLY have to return the command to execute, and not its parameters. It has to be a string with no white spaces

The CommandLineJob<Something> Abstract Classes will look like this

public abstract class CommandLineJobSomething extends CommandLine implements JobSomething {

     ...

     public abstract ... parseOutput(Integer exitValue, String output) throws ...;

     public abstract Map<String, String> init(...) throws ...;

     public abstract void close() throws OperationException, ...;

}

The parseOutput() method looks and behaves slightly different inside each
Interface, the init() and close() methods instead will have always
the same meaning. In init() you can do everything you need before the command line
command execution. You have to set all the command line parameters and options
that you need by invoking addParameter(<SomeString>) and addOption(<SomeStringWithSpaces>).
The return value of this method is a map of strings that contains a list of variables with their value that you
want to be available as environment variables during the command execution.

As a sample if you want to execute the "etics-get-project -c config1 org.etics" command with the ETICS_HOME variable setted to "/home/MyEticsHome" you have to:

  • Provide the string "etics-get-project" as return value of you implementation of the getCommand()
  • Invoke the addOption() method in your implementation of the init() method passing the "-c config1" string as parameter.
  • Invoke the addParameter() method in your implementation of the init() method passing the "org.etics" string as parameter.
  • Return a new map object containing the key-value coupple "ETICS_HOME"-"/home/MyEticsHome" in your implementation of the init().

The parameters of the init() method are different for different job operations.
In close() you can do what you need to finalize the command execution.
NOTE: the order by which you add the parameters to the command line in the init()method
is important! Parameters will be appended to the command string in the given order.
The parseOutput() method is expected to inspect the output and the exit value of the command execution
provided as parameters and to throw a proper Exception in case they are reporting an error.

Let’s look inside each Abstract Class for better comprehension.

The CommandLineJobSubmit Abstract Class looks like this:

public abstract class CommandLineJobSubmit extends CommandLine implements JobSubmit{

     ...

     /**
      * @param platform the ETICS platform on which to submit the job
      * @param configuration the component configuration to be builded or tested
      * @param build if true a build has to be submitted, if false a test
      * @param checkoutOptions the options to be appended to the checkout command
      * @param buildTestOptions the options to be appended to the build or test command
      * @param environmentVariables the variables to be added to execution environment
      * @param runAsRoot if true the job has to be executed as root
      * @param enableIPv6 if true the job has to be executed with IPv6 support
      * @param privateResource if true the job has to be run on private resources
      * @param freezeTime if greater than 0 job results has to be maintained for the specified amount of minutes
      * @param privateResult if true the job results on the repository has to be private
      * @param virtual if true the ETICS vmloader has to be used
      * @param clientUrl the URL from which the ETICS client setup has to be downloaded
      * @param user the user requesting the build or test
      * @param serverHost the ETICS server host to be used to checkout the component configuration
      * @param workDirectory a temporary folder that can be used to store temporary files
      * @return an ID identifying the job uniquely
      * @throws IllegalArgumentFault if arguments are not correct
      * @throws SubmissionErrorFault if an error occurs during job submission
      */
     public abstract Map<String, String> init(String platform, Configuration configuration,
        boolean build, String checkoutOptions, String buildTestOptions,
        Map<String, String> environmentVariables, boolean runAsRoot,boolean enableIPv6,
        boolean privateResource, long freezeTime, boolean privateResult,
        boolean virtual, String clientUrl, User user, String serverHost, String workDirectory)
        throws SubmissionErrorFault, IllegalArgumentFault;

     /**
      * @param exitValue the exit value of the command execution
      * @param output the command line output
      * @throws SubmissionErrorFault if an error has occurred during job submission
      */
     public abstract String parseOutput(Integer exitValue, String output) throws SubmissionErrorFault;

     /**
      * @throws OperationException if a non blocking error has occurred during the operaiton finalization
      * @throws SubmissionErrorFault if a blocking error has occurred during the operaiton finalization
      */
     public abstract void close() throws OperationException, SubmissionErrorFault;

     public abstract boolean providesVirtual(String platform)
        throws IllegalArgumentFault, SubmissionErrorFault;

     public abstract boolean providesPrivateResult(String platform)
        throws IllegalArgumentFault, SubmissionErrorFault;

     public abstract boolean providesFreeze(String platform)
        throws IllegalArgumentFault, SubmissionErrorFault;

     public abstract boolean providesPrivateResource(String platform)
        throws IllegalArgumentFault, SubmissionErrorFault;

     public abstract boolean providesEnableIPv6(String platform)
        throws IllegalArgumentFault, SubmissionErrorFault;

     public abstract boolean providesRunAsRoot(String platform)
        throws IllegalArgumentFault, SubmissionErrorFault;

     public abstract boolean supportsPlatform(String platform)
        throws IllegalArgumentFault, SubmissionErrorFault;

}

In your implementation of the init() method you prepare a command that do all what is needed to submit a job
to you submission engine that executes the following:

  • downloads the ETICS client from URL provided as clientUrl parameter
  • exports all the environment variables provided environmentVariables as parameter where this is a map variableName-variableValue
  • installs the ETICS client by executing the downloaded python setup script
  • sets the ETICS_HOME environment variable
  • sets the ETICS server to the value of serverHost the parameter
  • creates a workspace folder and executes the etics-workspace-setup command on it
  • executes the etics-get-project command on the project specified inside the configuration parameter
  • executes the etics-checkout command on the module and configuration specified inside the configuration parameter with options provided with parameter checkoutOptions
  • if the build parameter is true, executes the etics-build command on the module specified inside the configuration parameter provided options provided with parameter buildTestOptions
  • if the build parameter is false, executes the etics-test command on the module specified inside the configuration parameter provided options provided with parameter buildTestOptions
  • finally creates a tar.gz of the workspace dist and report folders and of the etics.log file, called workspace.tar.gz

Depending on the received requirements the job have to:

  • be executed as root user if the runAsRoot requirement is true
  • use IPv6 adressing if the enableIPv6 requirement is true
  • do not delete job results according to minutes as specified in freezeTime requirement if this is greater than 0

The following requirements are not yet completely supported. So you have to throw a SubmissionErrorFault execption if requested.

  • use the ETICS vmloader to load a proper virtual machine to execute job if the requirement virtual is true
  • use private resources if the privateResource requirement is true
  • reduce visibility of result on the repository if the privateResult requirement is true

In your implementation of the parseOutput method you have to return the string representing the unique identifier (hereafter called submitterId)
generated for the job or to throw a new SubmissionErrorFault if the operation fails.
The submitterId will be used in the subsequent interaction with the submitter to refers
to the submitted job.

This Abstract Class requests the implementation of 7 more methods. Those methods are related to the check of the
possibility to satisfy given requirements on a certain platform. From the name of the method you can understand
which requirement is related to. For the supportsPlatform() method you have to return true if you are able to submit
a job on the specified ETICS platform.
For the remaining methods you have to return true if, on the specified platform, your submitter plugin provides the capability
requested; otherwise, return false. For all this methods if an error occurs during the checking of the requirement you have to throw a SubmissionErrorFault exception.
Instead if the platform is null, you have to throw a IllegalArgumentFault exception.

For what concerns providesVirtual() providesPrivateResult() and providesPrivateResource() methods you have to
always return false because they are not yet completely supported.

The CommandLineJobGetStatus Abstract Class looks like this:

public abstract class CommandLineJobGetStatus extends CommandLine implements JobGetStatus{

     /**
      * @param submitterId the identifier of the job of which retrieve the status
      * @throws GetStatusErrorFault if an error has occurred during operation initialization
      */
     public abstract Map<String, String> init(String submitterId) throws GetStatusErrorFault;

     /**
      * @param exitValue the exit value of the command execution
      * @param output the command line output
      * @throws GetStatusErrorFault if an error has occurred during job status retrieving
      */
     public abstract String parseOutput(Integer exitValue, String output)
       throws GetStatusErrorFault;

     /**
      * @throws OperationException if a non blocking error has occurred during the operaiton finalization
      * @throws GetStatusErrorFault if a blocking error has occurred during the operaiton finalization
      */
     public abstract void close() throws OperationException, GetStatusErrorFault;

}

In your implementation of the init() method you have to prepare a command that retrieves the current status
of the job identified by the submitterId provided as parameter.
In your implementation of the parseOutput() method you have to return the string representing the current status of the job or to throw a new SubmissionErrorFault if the operation fails. The string that is returned MUST match with one of the status name that you have specified in the methods of your Class extending eu.eticsproject.submission.resources.GeneralJobStatus.

The CommandLineJobCancel Abstract Class looks like this:

public abstract class CancelOperation extends CommandLine implements JobCancel{

     /**
      * @param submitterId the identifier of the job to cancel
      * @throws CancelErrorFault if an error has occurred during operation initialization
      */
     public abstract Map<String, String> init(String submitterId) throws CancelErrorFault;

     /**
      * @param exitValue the exit value of the command execution
      * @param output the command line output
      * @throws CancelErrorFault if an error has occurred during job cancel
      */
     public abstract void parseOutput(Integer exitValue, String output)
       throws CancelErrorFault;

     /**
      * @throws OperationException if a non blocking error has occurred during the operaiton finalization
      * @throws CancelErrorFault if a blocking error has occurred during the operaiton finalization
      */
     public abstract void close() throws OperationException, CancelErrorFault;

}

In your implementation of the init() method you have to prepare a command that cancels the running job
identified by the submitterId provided as parameter.
In your implementation of the parseOutput() method you have to throw a new CancelErrorFault exception if the operation fails.

The CommandLineJobGetOutput Abstract Class looks like this:

public abstract class CommandLineJobGetOutput extends CommandLine implements JobGetOutput{

     /**
      * @param submitterId the identifier of the job of which retrieve the output
      * @param outputDirectory the directory where the workspace.tar.gz file has to be stored
      * @throws SubmissionOutputException if an error has occurred during operation initialization
      */
     public abstract Map<String, String> init(String submitterId, String outputDirectory) throws SubmissionOutputException;

     /**
      * @param exitValue the exit value of the command execution
      * @param output the command line output
      * @throws SubmissionOutputException if an error has occurred during job output retrieving
      */
     public abstract void parseOutput(Integer exitValue, String output)
       throws SubmissionOutputException;

     /**
      * @throws OperationException if a non blocking error has occurred during the operaiton finalization
      * @throws SubmissionOutputException if a blocking error has occurred during the operaiton finalization
      */
     public abstract void close() throws OperationException, SubmissionOutputException;

}

In your implementation of the init() method you have to prepare a command that retrieves the produced output of the completed job
identified by the submitterId provided as parameter and to store it in the form of a tar.gz archive named workspace.tar.gz in the provided outputDirectory directory.
In your implementation of the parseOutput() method you have to throw a new SubmissionOutputException if the operation fails.

Now you can proceed with step 3 and step 4 by using your new implemented Command Line Classes when the instrucions refers
to the implementations of the operations interfaces.

For any question mail to michele.dibenedetto@cnafNOSPAMPLEASE.infn.it

Edit | Attach | Watch | Print version | History: r10 < r9 < r8 < r7 < r6 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r10 - 2010-02-18 - unknown
 
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    ETICS All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright & 2008-2020 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback