/** * Copyright 2007-2008 University Of Southern California * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package edu.isi.pegasus.planner.code.generator.condor; import edu.isi.pegasus.planner.classes.ADag; import edu.isi.pegasus.planner.classes.AggregatedJob; import edu.isi.pegasus.planner.classes.DagInfo; import edu.isi.pegasus.planner.classes.Job; import edu.isi.pegasus.planner.namespace.Pegasus; import java.io.PrintWriter; /** * A helper class, that generates Pegasus specific classads for the jobs. * * @author Karan Vahi * @version $Revision$ */ public class ClassADSGenerator { /** * The name of the generator. */ public static final String GENERATOR = "Pegasus"; /** * The complete classad designating Pegasus as the generator. */ public static final String GENERATOR_AD_KEY = "pegasus_generator"; /** * The class ad key for the version id. * * @see org.griphyn.cPlanner.classes.DagInfo#releaseVersion */ public static final String VERSION_AD_KEY = "pegasus_version"; /** * The classad key for the pegasus build. */ public static final String BUILD_AD_KEY = "pegasus_build"; /** * The classad for the root workflow uuid */ public static final String ROOT_WF_UUID_KEY = "pegasus_root_wf_uuid"; /** * The classad for the workflow uuid */ public static final String WF_UUID_KEY = "pegasus_wf_uuid"; /** * The classad for the flow id. * * @see org.griphyn.cPlanner.classes.DagInfo#flowIDName */ public static final String WF_NAME_AD_KEY = "pegasus_wf_name"; /** * The classad for the timestamp. * * @see org.griphyn.cPlanner.classes.DagInfo#mFlowTimestamp */ public static final String WF_TIME_AD_KEY = "pegasus_wf_time"; /** * The classad for the complete transformation name. */ public static final String XFORMATION_AD_KEY = "pegasus_wf_xformation"; /** * The classad for generating the DAX ID */ public static final String DAX_JOB_ID_KEY = "pegasus_wf_dax_job_id"; /** * The class ad for job Class. * * @see org.griphyn.cPlanner.classes.Job#jobClass */ public static final String JOB_CLASS_AD_KEY = "pegasus_job_class"; /** * The class ad for the jobId. * * @see org.griphyn.cPlanner.classes.Job#jobID */ public static final String DAG_JOB_ID_KEY = "pegasus_wf_dag_job_id"; /** * The class ad for the expected job value */ public static final String JOB_RUNTIME_AD_KEY = "pegasus_job_runtime"; /** * The key for the number of cores for the multiplier factor in stampede. */ public static final String CORES_KEY = "pegasus_cores"; /** * The class ad to store the execution pool at which the job is run. The * globusscheduler specified in the submit file refers to the jobmanager on * this execution pool. */ public static final String RESOURCE_AD_KEY = "pegasus_site"; public static final String PLUS_RESOURCE_AD_KEY = "+" + RESOURCE_AD_KEY; /** * The class ad to designate the size of the clustered jobs. */ public static final String JOB_CLUSTER_SIZE_AD_KEY = "pegasus_cluster_size"; /** * Writes out the classads for a workflow to corresponding writer stream. * * @param writer is an open stream for the Condor submit file. * @param dag the workflow object containing metadata about the workflow * like the workflow id and the release version. */ public static void generate( PrintWriter writer, ADag dag ) { //get hold of the object holding the metadata //information about the workflow //pegasus is the generator writer.println( generateClassAdAttribute( GENERATOR_AD_KEY, GENERATOR) ); //the root workflow and workflow uuid writer.println( generateClassAdAttribute( ROOT_WF_UUID_KEY, dag.getRootWorkflowUUID()) ); writer.println( generateClassAdAttribute( WF_UUID_KEY, dag.getWorkflowUUID()) ); //the vds version writer.println( generateClassAdAttribute(VERSION_AD_KEY, dag.getReleaseVersion() )); //the workflow name writer.println( generateClassAdAttribute(WF_NAME_AD_KEY, dag.getFlowName() )); //the workflow time if ( dag.getMTime() != null) { writer.println( generateClassAdAttribute(WF_TIME_AD_KEY, dag.getFlowTimestamp())); } } /** * Writes out the classads for a job to corresponding writer stream. * The writer stream points to a Condor Submit file for the job. * * @param writer is an open stream for the Condor submit file. * @param dag the workflow object containing metadata about the workflow * like the workflow id and the release version. * @param job the <code>Job</code> object for which the writer stream * is passed. **/ public static void generate( PrintWriter writer, ADag dag, Job job ) { //get all the workflow classads generate( writer, dag ); //get the job classads //the tranformation name writer.println( generateClassAdAttribute( ClassADSGenerator.XFORMATION_AD_KEY, job.getCompleteTCName() ) ); //put in the DAX writer.println( generateClassAdAttribute( DAX_JOB_ID_KEY, job.getDAXID() ) ); //the supernode id writer.println(generateClassAdAttribute( ClassADSGenerator.DAG_JOB_ID_KEY, job.getID() )); //the class of the job writer.println(generateClassAdAttribute( ClassADSGenerator.JOB_CLASS_AD_KEY, job.getJobType() ) ); //the resource on which the job is scheduled //PM-796 only generate the resource ad key //if job is not previously associated with it String plusResourceKey = ClassADSGenerator.PLUS_RESOURCE_AD_KEY; if( job.condorVariables.containsKey( plusResourceKey )){ //pick the one pre populated writer.println(generateClassAdAttribute( ClassADSGenerator.RESOURCE_AD_KEY, (String)job.condorVariables.removeKey( plusResourceKey ) ) ); } else{ //generate the default one writer.println(generateClassAdAttribute( ClassADSGenerator.RESOURCE_AD_KEY, job.getSiteHandle() ) ); } //add the pegasus value if defined. String value = (String)job.vdsNS.getStringValue( Pegasus.RUNTIME_KEY ); //else see if globus maxwalltime defined value = ( value == null )? (String)job.globusRSL.get( "maxwalltime" ) : value; int runtime = 0; try{ runtime = ( value == null )? 0: Integer.parseInt(value); } catch( Exception e ){ //ignore } writer.println(generateClassAdAttribute( ClassADSGenerator.JOB_RUNTIME_AD_KEY, runtime ) ); //write out the cores if specified for job String coresvalue = job.vdsNS.getStringValue( Pegasus.CORES_KEY ); int cores = 1; try{ cores = ( coresvalue == null ) ? 1 : Integer.parseInt( coresvalue ); } catch( Exception e ){ //ignore } writer.println(generateClassAdAttribute( ClassADSGenerator.CORES_KEY, cores ) ); //determine the cluster size int csize = ( job instanceof AggregatedJob ) ? ( (AggregatedJob)job ).numberOfConsitutentJobs() : 1; writer.println( generateClassAdAttribute( ClassADSGenerator.JOB_CLUSTER_SIZE_AD_KEY, csize ) ); } /** * Generates a classad attribute given the name and the value. * * @param name the attribute name. * @param value the value/expression making the classad attribute. * * @return the classad attriubute. */ private static String generateClassAdAttribute(String name, String value) { return generateClassAdAttribute( name, value, false); } /** * Generates a classad attribute given the name and the value. It by default * adds a new line character at start of each attribute. * * @param name the attribute name. * @param value the value/expression making the classad attribute. * * @return the classad attriubute. */ private static String generateClassAdAttribute(String name, int value) { StringBuffer sb = new StringBuffer(10); sb.append("+"); sb.append(name).append(" = "); sb.append(value); return sb.toString(); } /** * Generates a classad attribute given the name and the value. * * @param name the attribute name. * @param value the value/expression making the classad attribute. * @param newLine boolean denoting whether to add a new line character at * start or not. * * @return the classad attriubute. */ private static String generateClassAdAttribute( String name, String value, boolean newLine) { StringBuffer sb = new StringBuffer(10); if(newLine) sb.append("\n"); sb.append("+"); sb.append(name).append(" = "); sb.append("\""); sb.append(value); sb.append("\""); return sb.toString(); } }