org.kalypso.simulation.grid.SimpleGridProcess.java Source code

Java tutorial

Introduction

Here is the source code for org.kalypso.simulation.grid.SimpleGridProcess.java

Source

/*----------------    FILE HEADER KALYPSO ------------------------------------------
 *
 *  This file is part of kalypso.
 *  Copyright (C) 2004 by:
 * 
 *  Technical University Hamburg-Harburg (TUHH)
 *  Institute of River and coastal engineering
 *  Denickestrae 22
 *  21073 Hamburg, Germany
 *  http://www.tuhh.de/wb
 * 
 *  and
 * 
 *  Bjoernsen Consulting Engineers (BCE)
 *  Maria Trost 3
 *  56070 Koblenz, Germany
 *  http://www.bjoernsen.de
 * 
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 * 
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 * 
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 *  Contact:
 * 
 *  E-Mail:
 *  belger@bjoernsen.de
 *  schlienger@bjoernsen.de
 *  v.doemming@tuhh.de
 * 
 *  ---------------------------------------------------------------------------*/
package org.kalypso.simulation.grid;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.security.auth.Subject;

import org.apache.commons.io.IOUtils;
import org.apache.commons.vfs.FileName;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystem;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemManagerWrapper;
import org.apache.commons.vfs.provider.gsiftp.GsiFtpFileObject;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.gridforum.jgss.ExtendedGSSManager;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
import org.kalypso.commons.io.VFSUtilities;
import org.kalypso.commons.process.IProcess;
import org.kalypso.commons.process.ProcessTimeoutException;
import org.kalypso.contribs.java.lang.ICancelable;

import de.unihannover.rvs.gdi.jobsubmit.impl.GDIJobFactory;
import de.unihannover.rvs.gdi.jobsubmit.impl.GDIJobProperties;
import de.unihannover.rvs.gdi.jobsubmit.impl.GDIState;
import de.unihannover.rvs.gdi.jobsubmit.interfaces.GDIJob;
import de.unihannover.rvs.gdi.jobsubmit.interfaces.GDIObserver;
import de.unihannover.rvs.gdi.jobsubmit.interfaces.GDIObserverSubject;

/**
 * This implementation executes processes in a computing grid.
 * 
 * @author Stefan Kurzbach
 */
public class SimpleGridProcess implements IProcess, GDIObserver {
    private static final String GRID_SERVER_HANNOVER = "gramd1.gridlab.uni-hannover.de";

    @SuppressWarnings("unused")
    private static final String GRID_SERVER_KAISERSLAUTERN = "gt4-gdi.sugi.uni-kl.de";

    private final String m_targetHostName;

    private final FileObject m_workingDir;

    private final String m_executable;

    private long m_timeout;

    private final List<String> m_commandLine = new ArrayList<String>();

    private final Map<String, String> m_environment = new HashMap<String, String>();

    private GDIState m_status = GDIState.UNSUBMITTED;

    private final FileSystemManagerWrapper m_manager;

    // private IProgressMonitor m_monitor;

    /**
     * Creates a new grid process with given sandbox, executable and arguments.
     * 
     * @param tempDirName
     * @param exeUrl
     * @param commandlineArgs
     */
    public SimpleGridProcess(final String tempDirName, final String executable, final String... commandLineArgs)
            throws IOException {
        Assert.isNotNull(tempDirName);
        Assert.isNotNull(executable);

        m_executable = executable;
        m_targetHostName = GRID_SERVER_HANNOVER;
        // m_targetHostName = GRID_SERVER_KAISERSLAUTERN;

        if (commandLineArgs != null) {
            for (final String arg : commandLineArgs) {
                m_commandLine.add(arg);
            }
        }

        m_manager = VFSUtilities.getNewManager();
        m_workingDir = createSandbox(tempDirName);
    }

    /**
     * @see org.kalypso.commons.process.IProcess#getSandboxDirectory()
     */
    @Override
    public String getSandboxDirectory() {
        final FileName name = m_workingDir.getName();
        return name.getURI();
    }

    // /**
    // * Sets a progress monitor.
    // *
    // * @see org.kalypso.commons.process.IProcess#setProgressMonitor(org.eclipse.core .runtime.IProgressMonitor)
    // */
    // @Override
    // public void setProgressMonitor( final IProgressMonitor monitor )
    // {
    // m_monitor = monitor;
    // }

    /**
     * Gets the grid job's environment
     * 
     * @see org.kalypso.commons.process.IProcess#environment()
     */
    @Override
    public Map<String, String> environment() {
        return m_environment;
    }

    /**
     * @see org.kalypso.commons.process.IProcess#setTimeout(long)
     */
    @Override
    public void setTimeout(final long timeout) {
        m_timeout = timeout;
    }

    /**
     * @see org.kalypso.commons.process.IProcess#startProcess(java.io.OutputStream, java.io.OutputStream,
     *      java.io.InputStream, org.kalypso.contribs.java.lang.ICancelable)
     */
    @Override
    public int startProcess(final OutputStream stdOut, final OutputStream stdErr, final InputStream stdIn,
            final ICancelable cancelable) throws ProcessTimeoutException, IOException {
        // initialize simulation monitor if not set
        // final String friendlyURI = m_workingDir.getName().getFriendlyURI();
        // m_monitor = SubMonitor.convert( m_monitor, String.format(
        // "Running grid process for executable %s in directoy %s.", m_executable, friendlyURI ), 10 );

        /* configure and submit grid job */

        // logging output
        final String stdOutFileName = m_executable + ".out";
        final String stdErrFileName = m_executable + ".err";

        // for hannover
        final String queue = "dgitest";
        final String factory = "PBS";

        // for kaiserslautern
        // final String queue = "dgitest";
        // final String factory = "SGE"

        final FileObject executableFile = m_workingDir.resolveFile(m_executable);
        if (!executableFile.exists())
            throw new IOException("Executable does not exist!");

        // make file executable
        ((GsiFtpFileObject) executableFile).makeExecutable();

        final GSSCredential credential = getCredential();

        final GDIJobProperties props = new GDIJobProperties();

        props.addPreference("gdi.targethostname", m_targetHostName);
        props.addPreference("gdi.executable", "./" + m_executable);
        props.addPreference("gdi.arguments", m_commandLine);
        props.addPreference("gdi.environment", m_environment);

        final String sandboxName = m_workingDir.getName().getBaseName();
        props.addPreference("gdi.sandboxdir", sandboxName);

        props.addPreference("gdi.stdout", stdOutFileName);
        props.addPreference("gdi.stderr", stdErrFileName);
        props.addPreference("gdi.factory", factory);
        props.addPreference("gdi.queue", queue);
        props.addPreference("gdi.credential", credential);

        final GDIJob job = GDIJobFactory.createGDIJob(GDIJobFactory.defaultGDIJob);
        job.setProps(props);

        // m_monitor.subTask( String.format( "Submitting grid job to server %s.", m_targetHostName ) );

        final PrintWriter stdPrinter = new PrintWriter(stdOut);
        final PrintWriter errPrinter = new PrintWriter(stdErr);

        // on error iRetVal will be IStatus.ERROR (4)
        // if finished successfully, iRetVal will be IStatus.OK (0)
        int iRetVal = IStatus.ERROR;
        try {
            // register observer
            ((GDIObserverSubject) job).registerObserver(this);

            // submit job
            job.submit();

            final long startTime = System.currentTimeMillis();
            finished: while (!isCanceled(cancelable)) {
                if (m_timeout > 0) {
                    final long currentTime = System.currentTimeMillis();
                    final long processDuration = currentTime - startTime;
                    if (processDuration > m_timeout) {
                        // job will be canceled in finish statement of try/catch block
                        throw new ProcessTimeoutException();
                    }
                }
                switch (m_status) {
                case UNSUBMITTED:
                case STAGEIN:
                case STAGEOUT:
                case RUNNING:
                    Thread.sleep(1000);
                    break;
                case FINISHED:
                    iRetVal = IStatus.OK;
                case FAILED:
                    break finished;
                }
            }
        } catch (final InterruptedException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(stdPrinter);
            IOUtils.closeQuietly(errPrinter);

            // clean up job in case of an error
            // this will have no effect if job has finished successfully
            if (job != null && job.getStatus() == GDIState.RUNNING) {
                job.cancelJob();
            }

            if (m_manager != null)
                m_manager.close();

            if (isCanceled(cancelable)) {
                errPrinter.println("Job has been canceled.");
                throw new OperationCanceledException();
            }
        }

        return iRetVal;
    }

    private FileObject createSandbox(final String tempDirName) throws FileSystemException {
        final String gridFtpRoot = "gridftp://" + m_targetHostName;
        final FileObject remoteRoot = m_manager.resolveFile(gridFtpRoot);
        final FileSystem fileSystem = remoteRoot.getFileSystem();

        // get home directory of user who created this job
        final String homeDirString = (String) fileSystem.getAttribute("HOME_DIRECTORY");
        final FileObject homeDir = remoteRoot.resolveFile(homeDirString);
        final FileObject workingDir = homeDir.resolveFile(tempDirName);
        workingDir.createFolder();
        return workingDir;
    }

    private GSSCredential getCredential() throws IOException {
        // 1.
        // search for credential in current security context
        final Subject currentSubject = org.globus.gsi.jaas.JaasSubject.getCurrentSubject();
        if (currentSubject != null) {
            final Set<Object> creds = currentSubject.getPrivateCredentials();
            if (creds.size() >= 1) {
                return (GSSCredential) creds.iterator().next();
            } else {
                // if we are on server side, we cannot just create a credential, so throw an exception
                throw new IOException("Current subject does not have private credentials.");
            }
        }

        // 2.
        // Authenticate with user credential defined in <USER_HOME>/.globus/cog.properties
        // or (if undefined) use default proxy certificate <TEMP>/X509...
        final ExtendedGSSManager manager = (ExtendedGSSManager) ExtendedGSSManager.getInstance();
        try {
            return manager.createCredential(GSSCredential.INITIATE_AND_ACCEPT);
        } catch (final GSSException e) {
            // wrap as IOException because we cannot do I/O without security
            throw new IOException(e);
        }
    }

    private boolean isCanceled(final ICancelable cancelable) {
        return cancelable != null && cancelable.isCanceled();
        // return m_monitor.isCanceled() || (cancelable != null && cancelable.isCanceled());
    }

    /*
     * (non-Javadoc)
     * @see de.unihannover.rvs.gdi.jobsubmit.interfaces.GDIObserver#update(org.gridlab .gat.resources.Job.JobState)
     */
    public void update(final GDIState newStatus) {
        m_status = newStatus;
        // m_monitor.subTask( m_status.toString() );
    }
}