/**
* 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.style;
import edu.isi.pegasus.common.credential.CredentialHandler;
import edu.isi.pegasus.common.credential.CredentialHandlerFactory;
import edu.isi.pegasus.common.logging.LogManager;
import edu.isi.pegasus.planner.catalog.site.classes.SiteCatalogEntry;
import edu.isi.pegasus.planner.catalog.site.classes.SiteStore;
import edu.isi.pegasus.planner.classes.AggregatedJob;
import edu.isi.pegasus.planner.classes.Job;
import edu.isi.pegasus.planner.classes.PegasusBag;
import edu.isi.pegasus.planner.code.generator.condor.CondorStyle;
import edu.isi.pegasus.planner.code.generator.condor.CondorStyleException;
import edu.isi.pegasus.planner.code.generator.condor.CondorStyleFactoryException;
import edu.isi.pegasus.planner.common.PegasusProperties;
import java.util.Iterator;
import java.util.Set;
import java.util.Map;
/**
* An abstract implementation of the CondorStyle interface.
* Implements the initialization method.
*
* @author Karan Vahi
* @version $Revision$
*/
public abstract class Abstract implements CondorStyle {
/**
* The object holding all the properties pertaining to Pegasus.
*/
protected PegasusProperties mProps;
/**
* The handle to the Site Catalog Store.
*/
protected SiteStore mSiteStore;
/**
* A handle to the logging object.
*/
protected LogManager mLogger;
/**
* Handle to the Credential Handler Factory
*/
protected CredentialHandlerFactory mCredentialFactory ;
/**
* The default constructor.
*/
public Abstract() {
//mLogger = LogManager.getInstance();
}
/**
* Initializes the Code Style implementation.
*
* @param bag the bag of initialization objects
* @param credentialFactory the credential handler factory
*
*
* @throws CondorStyleFactoryException that nests any error that
* might occur during the instantiation of the implementation.
*/
public void initialize( PegasusBag bag , CredentialHandlerFactory credentialFactory )throws CondorStyleException{
mProps = bag.getPegasusProperties();
mSiteStore = bag.getHandleToSiteStore();
mLogger = bag.getLogger();
mCredentialFactory = credentialFactory;
}
/**
* Apply a style to an AggregatedJob
*
* @param job the <code>AggregatedJob</code> object containing the job.
*
* @throws CondorStyleException in case of any error occuring code generation.
*/
public void apply( AggregatedJob job ) throws CondorStyleException{
//apply style to all constituent jobs
for( Iterator it = job.constituentJobsIterator(); it.hasNext(); ){
Job j = (Job) it.next();
this.apply( j );
}
//also apply style to the aggregated job itself
this.apply( (Job)job );
}
/**
* Empty implementation.
*
* @param site the site catalog entry object
*
* @throws CondorStyleException in case of any error occuring code generation.
*/
public void apply( SiteCatalogEntry site ) throws CondorStyleException{
//do nothing
}
/**
* Examines the credential requirements for a job and adds appropiate
* transfer and environment directives for the credentials to be staged
* and picked up by the job.
* @param job
*/
protected void applyCredentialsForRemoteExec(Job job) throws CondorStyleException {
//sanity check
if ( !job.requiresCredentials() ) {
return;
}
applyCredentialsForJobSubmission( job );
// jobs can have multiple credential requirements
//and may need credentials associated with different sites PM-731
for( Map.Entry<String,Set<CredentialHandler.TYPE>> entry : job.getCredentialTypes().entrySet() ){
String siteHandle = entry.getKey();
for( CredentialHandler.TYPE credType: entry.getValue()){
CredentialHandler handler = mCredentialFactory.loadInstance( credType );
// if the credential is listed in the remote sites environment, don't do anything
SiteCatalogEntry site = mSiteStore.lookup(job.getSiteHandle());
if (site.getEnvironmentVariable(handler.getProfileKey()) != null &&
siteHandle.equals( job.getSiteHandle() )) {
//the user has the enviornment variable specified in the site
//catalog pointing to an existing credential on the remote
//site and the job is going to run on the site for which we
//need the credential
continue;
}
//make sure we can have a path to credential
String credentialPath = handler.getPath( siteHandle );
if ( credentialPath == null ){
this.complainForCredential( job, handler.getProfileKey(), siteHandle );
}
switch(credType) {
case x509:
//check if x509userproxy not already set. can be set
//as part of credentials for job submission
if ( job.condorVariables.containsKey( Condor.X509USERPROXY_KEY) ){
//we can transfer the credential only via condor file io
//sanity check to to make sure not same as already set
String existing = (String)job.condorVariables.get( Condor.X509USERPROXY_KEY);
if( !existing.equals( credentialPath)){
job.condorVariables.addIPFileForTransfer( credentialPath );
job.envVariables.construct(handler.getEnvironmentVariable( siteHandle ), handler.getBaseName( siteHandle ) );
}
}
else{
//PM-1099 set the x509userproxy key directly
//we don's set the environment variable based on site name
//as for GRAM submissions, the proxy is renmaed by GRAM on the
//remote end tp the x509_user_proxy when placed in ~/.globus/job
//directory. GRAM then sets X509_USER_PROXY env variable to reflect
//the path to the proxy.
job.condorVariables.construct( Condor.X509USERPROXY_KEY, credentialPath );
}
break;
case irods:
case s3:
case boto:
case googlep12:
case ssh:
// transfer using condor file transfer, and advertise in env
// but first make sure it is specified in our environment
/*String path = handler.getPath( siteHandle );
if ( path == null ){
this.complainForCredential( job, handler.getProfileKey(), siteHandle );
}*/
job.condorVariables.addIPFileForTransfer( credentialPath );
job.envVariables.construct(handler.getEnvironmentVariable( siteHandle ), handler.getBaseName( siteHandle ) );
break;
default:
throw new CondorStyleException("Job has been tagged with unknown credential type");
}
}//for each credential for each site
}
}
/**
* Examines the credential requirements for a job and adds appropiate
* transfer and environment directives for the credentials to be picked
* up for the local job
* @param job
*/
protected void applyCredentialsForLocalExec(Job job) throws CondorStyleException {
//sanity check
if ( !job.requiresCredentials() ) {
return;
}
//associate any credentials if reqd for job submission.
this.applyCredentialsForJobSubmission(job);
// jobs can have multiple credential requirements
//and may need credentials associated with different sites PM-731
for( Map.Entry<String,Set<CredentialHandler.TYPE>> entry : job.getCredentialTypes().entrySet() ){
// jobs can have multiple credential requirements
String siteHandle = entry.getKey();
for( CredentialHandler.TYPE credType: entry.getValue()){
CredentialHandler handler = mCredentialFactory.loadInstance( credType );
switch(credType) {
case x509:
case irods:
case s3:
case boto:
case googlep12:
case ssh:
// for local exec, just set envionment variables to full path
String path = handler.getPath( siteHandle );
if ( path == null) {
this.complainForCredential( job, handler.getProfileKey(), siteHandle );
}
job.envVariables.construct(handler.getEnvironmentVariable( siteHandle ), path );
break;
default:
throw new CondorStyleException("Job has been tagged with unknown credential type");
}
}
}
}
/**
* Associates credentials required for job submission.
*
* @param job
* @throws CondorStyleException
*/
protected void applyCredentialsForJobSubmission(Job job) throws CondorStyleException {
//handle credential for job submission if set
if( job.getSubmissionCredential() == null ){
return;
}
//set the proxy for job submission
CredentialHandler.TYPE cred = job.getSubmissionCredential();
CredentialHandler handler = mCredentialFactory.loadInstance( cred );
String path = handler.getPath( job.getSiteHandle());
if ( path == null) {
this.complainForCredential( job, handler.getProfileKey(), job.getSiteHandle() );
}
switch( cred ) {
case x509:
job.condorVariables.construct( Condor.X509USERPROXY_KEY, path );
break;
default:
//only job submission via x509 is explicitly supported
throw new CondorStyleException( "Invalid credential type for job submission " + cred + " for job " + job.getName() );
}
return;
}
/**
* Complain if a particular credential key is not found for a site
*
* @param job
* @param key
* @param site
* @throws CondorStyleException
*/
protected void complainForCredential( Job job, String key , String site ) throws CondorStyleException{
StringBuilder error = new StringBuilder();
error.append( "Unable to find required credential for file transfers for job ").
append( job.getName() ).append( " . Please make sure that the key " ).append( key ).
append( " is set as a Pegasus profile in the site catalog for site ").append( site ).
append( " or in your environment.");
throw new CondorStyleException( error.toString() );
}
/**
* Constructs an error message in case of style mismatch.
*
* @param job the job object.
* @param style the name of the style.
* @param universe the universe associated with the job.
*/
protected String errorMessage( Job job, String style, String universe){
StringBuilder sb = new StringBuilder();
sb.append( "( " ).
append( style ).append( "," ).
append( universe ).append( "," ).
append( job.getSiteHandle() ).
append( ")" ).
append( " mismatch for job " ).append( job.getName() );
return sb.toString();
}
}