Package org.globus.workspace.cloud.client.util

Source Code of org.globus.workspace.cloud.client.util.ExecuteUtil$IdIpPair

/*
* Copyright 1999-2008 University of Chicago
*
* 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 org.globus.workspace.cloud.client.util;

import edu.emory.mathcs.backport.java.util.concurrent.ExecutionException;
import edu.emory.mathcs.backport.java.util.concurrent.ExecutorService;
import edu.emory.mathcs.backport.java.util.concurrent.Executors;
import edu.emory.mathcs.backport.java.util.concurrent.FutureTask;
import org.apache.axis.message.addressing.EndpointReferenceType;
import org.apache.axis.types.URI;
import org.globus.workspace.client_common.BaseClient;
import org.globus.workspace.client_core.ExecutionProblem;
import org.globus.workspace.client_core.ExitNow;
import org.globus.workspace.client_core.ParameterProblem;
import org.globus.workspace.client_core.print.PrCodes;
import org.globus.workspace.client_core.utils.EPRUtils;
import org.globus.workspace.client_core.utils.FileUtils;
import org.globus.workspace.client_core.utils.StringUtils;
import org.globus.workspace.cloud.client.Opts;
import org.globus.workspace.cloud.client.cluster.ClusterMember;
import org.globus.workspace.cloud.client.cluster.KnownHostsTask;
import org.globus.workspace.cloud.client.tasks.ClusterDoneTask;
import org.globus.workspace.cloud.client.tasks.ClusterMonitorTask;
import org.globus.workspace.cloud.client.tasks.ContextMonitorTask;
import org.globus.workspace.cloud.client.tasks.CreateContextTask;
import org.globus.workspace.cloud.client.tasks.DestroyTask;
import org.globus.workspace.cloud.client.tasks.FactoryQueryTask;
import org.globus.workspace.cloud.client.tasks.PrintContextStatusTask;
import org.globus.workspace.cloud.client.tasks.QueryTask;
import org.globus.workspace.cloud.client.tasks.RunTask;
import org.globus.workspace.cloud.client.tasks.SaveTask;
import org.globus.workspace.cloud.meta.client.CloudDeployment;
import org.globus.workspace.common.client.CommonPrint;
import org.globus.workspace.common.print.Print;
import org.globus.workspace.common.print.PrintOpts;
import org.nimbustools.ctxbroker.generated.gt4_0.description.BrokerContactType;
import org.nimbustools.ctxbroker.generated.gt4_0.description.Cloudcluster_Type;
import org.nimbustools.ctxbroker.generated.gt4_0.description.Nimbusctx_Type;
import org.nimbustools.messaging.gt4_0.common.CommonUtil;
import org.nimbustools.messaging.gt4_0.generated.metadata.VirtualWorkspace_Type;
import org.nimbustools.messaging.gt4_0.generated.negotiable.WorkspaceDeployment_Type;

import javax.xml.namespace.QName;
import java.io.File;
import java.io.FilenameFilter;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class ExecuteUtil {

    // -------------------------------------------------------------------------
    // INSTANCE VARIABLES
    // -------------------------------------------------------------------------

    final ExecutorService executor;
    final boolean okToShutdownExecutorService;


    // -------------------------------------------------------------------------
    // CONSTRUCTORS
    // -------------------------------------------------------------------------

    public ExecuteUtil() {
        this.executor = Executors.newCachedThreadPool();
        this.okToShutdownExecutorService = true;
    }

    public ExecutorService getExecer() {
        return this.executor;
    }

    public ExecuteUtil(ExecutorService executorService, boolean okToShutdown) {
        if (executorService == null) {
            throw new IllegalArgumentException(
                                "executorService may not be null");
        }
        this.executor = executorService;
        this.okToShutdownExecutorService = okToShutdown;
    }

   
    // -------------------------------------------------------------------------
    // GENERAL
    // -------------------------------------------------------------------------

    public synchronized void stopExecutorService() {

        if (!this.okToShutdownExecutorService) {
            return;
        }

        if (!this.executor.isShutdown()) {
            this.executor.shutdownNow();
        }
    }

    // -------------------------------------------------------------------------
    // STATUS QUERY (query one)
    // -------------------------------------------------------------------------

    public void statusQuery(String eprPath,
                            String idAuthz,
                            Print print)

            throws ExecutionProblem, ExitNow {

        String shortName = null;
        final File epr = new File(eprPath);
        final String dirName = epr.getParentFile().getName();

        if (dirName.startsWith(HistoryUtil.historyClusterDirPrefix)) {
            throw new ExecutionProblem("Cluster handles are not supported, " +
                    "use the \"--" + Opts.STATUS_CHECK_OPT_STRING +
                    "\" option by itself instead.");
        }

        if (dirName.startsWith(HistoryUtil.historyDirPrefix)) {

            print.debugln("Surmising from EPR parent directory that " +
                          "short name is '" + dirName +
                          "' (used for printing only)");

            shortName = dirName;
        }

        print.infoln("Querying for '" + dirName + "' information:");
        print.infoln("  - Workspace handle (EPR): '" + eprPath + "'");

        final FutureTask task =
                new FutureTask(
                        new QueryTask(eprPath, idAuthz, shortName,
                                      print));
       
        this.executor.submit(task);

        try {
            final Integer retCode = (Integer) task.get();
            if (retCode.intValue() != BaseClient.SUCCESS_EXIT_CODE) {
                throw new ExitNow(retCode.intValue());
            }
        } catch (InterruptedException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        } catch (ExecutionException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        }
    }


    // -------------------------------------------------------------------------
    // PRINT CONTEXT STATUS QUERY
    // -------------------------------------------------------------------------

    public void printContextStatusQuery(String eprPath,
                                  String brokerIdAuthz,
                                  Print print)

            throws ExecutionProblem, ExitNow {

        String shortName = null;
        print.debugln("Received broker EPR path: " + eprPath);
        final File epr = new File(eprPath);
        final String dirName = epr.getParentFile().getName();

        if (dirName.startsWith(HistoryUtil.historyDirPrefix) ||
                dirName.startsWith(HistoryUtil.historyClusterDirPrefix)) {

            print.debugln("Surmising from context EPR parent directory that " +
                          "short name is '" + dirName +
                          "' (used for printing only)");

            shortName = dirName;
        }

        final File ipIdDir = new File(epr.getParentFile(), "id-ip-dir");
        final String ipIdDirPath = ipIdDir.getAbsolutePath();
        print.debugln("Surmising from context EPR parent directory that " +
                          "id-ip-dir is: " + ipIdDirPath);
        if (!ipIdDir.exists()) {
            throw new ExecutionProblem("Could not find the 'id-ip-dir' for this handle, " +
                    "was it a virtual cluster launched with the context broker?");
        }

        final FutureTask task =
                new FutureTask(
                        new PrintContextStatusTask(eprPath, brokerIdAuthz, shortName,
                                             ipIdDirPath, print));

        this.executor.submit(task);

        try {
            final Integer retCode = (Integer) task.get();
            if (retCode.intValue() != BaseClient.SUCCESS_EXIT_CODE) {
                throw new ExitNow(retCode.intValue());
            }
        } catch (InterruptedException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        } catch (ExecutionException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        }
    }

    // -------------------------------------------------------------------------
    // ASSOCIATION QUERY
    // -------------------------------------------------------------------------

    public void associationQuery(String workspaceFactoryURL,
                                 String factoryID,
                                 Print print)

            throws ExecutionProblem, ExitNow {

        print.infoln("Querying networks.");

        // don't mess with the main print system, make a new one
        final int[] printThese = {PrCodes.FACTORYRPQUERY__ASSOCS};
        final PrintOpts newOpts = new PrintOpts(printThese);
        final Print newprint = new Print(newOpts,
                                         print.getInfoProxy(),
                                         print.getErrProxy(),
                                         print.getDebugProxy());

        final FutureTask task =
                new FutureTask(
                        new FactoryQueryTask(workspaceFactoryURL,
                                             factoryID,
                                             newprint));

        this.executor.submit(task);

        try {
            final Integer retCode = (Integer) task.get();
            if (retCode.intValue() != BaseClient.SUCCESS_EXIT_CODE) {
                throw new ExitNow(retCode.intValue());
            }
        } catch (InterruptedException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        } catch (ExecutionException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        }
    }


    // -------------------------------------------------------------------------
    // SHUTDOWN-SAVE
    // -------------------------------------------------------------------------

    public void save(String newSaveTargetPrintName,
                     String newSaveTargetURL,
                     String eprPath,
                     long pollMs,
                     boolean useNotifications,
                     String identityAuthorization,
                     Print print)

            throws ExecutionProblem, ExitNow {

        print.infoln("\nSaving workspace.");
        print.infoln("  - Workspace handle (EPR): '" + eprPath + "'");
        if (newSaveTargetPrintName != null) {
            print.infoln("  - New name: '" + newSaveTargetPrintName + "'");
        }

        final File epr = new File(eprPath);

        String shortName = null;

        final String dirName = epr.getParentFile().getName();
        if (dirName.startsWith(HistoryUtil.historyClusterDirPrefix)
                || dirName.startsWith(HistoryUtil.historyDirPrefix)) {
           
            print.debugln("Surmising from EPR parent directory that " +
                          "short name is '" + dirName +
                          "' (used for printing only)");

            shortName = dirName;
        }

        boolean disableAllStateChecks = false;
        if (pollMs < 1 && !useNotifications) {
            disableAllStateChecks = true;
        }

        final SaveTask sTask = new SaveTask(eprPath,
                                            newSaveTargetURL,
                                            identityAuthorization,
                                            pollMs,
                                            disableAllStateChecks,
                                            shortName,
                                            print);

        final FutureTask task = new FutureTask(sTask);
        this.executor.submit(task);

        try {
            final Integer retCode = (Integer) task.get();
            if (retCode.intValue() != BaseClient.SUCCESS_EXIT_CODE) {
                throw new ExitNow(retCode.intValue());
            }
        } catch (InterruptedException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        } catch (ExecutionException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        }
    }


    // -------------------------------------------------------------------------
    // DESTROY
    // -------------------------------------------------------------------------

    public void destroy(String eprPath,
                        String identityAuthorization,
                        boolean isClusterHandle,
                        Print print)

            throws ExecutionProblem, ExitNow {

        if (isClusterHandle) {
            print.infoln("\nTerminating cluster.");
            print.infoln("  - Cluster handle (EPR): '" + eprPath + "'");
        } else {
            print.infoln("\nTerminating workspace.");
            print.infoln("  - Workspace handle (EPR): '" + eprPath + "'");
        }

        final File epr = new File(eprPath);

        String dirName = epr.getParentFile().getName();
        if (dirName.startsWith(HistoryUtil.historyClusterDirPrefix)
                || dirName.startsWith(HistoryUtil.historyDirPrefix)) {
            print.debugln("Surmising from EPR parent directory that " +
                   "short name is '" + dirName + "' (used for printing only)");
        } else {
            dirName = null;
        }

        final DestroyTask dTask = new DestroyTask(eprPath,
                                                  identityAuthorization,
                                                  dirName,
                                                  print);

        final FutureTask task = new FutureTask(dTask);
        this.executor.submit(task);

        try {
            final Integer retCode = (Integer) task.get();
            if (retCode.intValue() != BaseClient.SUCCESS_EXIT_CODE) {
                throw new ExitNow(retCode.intValue());
            }
        } catch (InterruptedException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        } catch (ExecutionException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        }
    }

    public void startMultiCloudCluster(Collection<CloudDeployment> deploys,
                                      String historyDir,
                                      long pollMs,
                                      Print print,
                                      String brokerURL,
                                      String brokerIdentityAuthorization,
                                       String sshKeyPath, int durationMinutes
    )
        throws ExecutionProblem, ExitNow {

        CloudDeployment[] clouds = new CloudDeployment[deploys.size()];
        clouds = deploys.toArray(clouds);

        final File newdir = ExecuteUtil.createNewMultiClusterDir(
            historyDir, print);
        final String newdirPath = newdir.getAbsolutePath();
        final String multiclusterHandle = newdir.getName();

        final File runLog =
                HistoryUtil.newLogFile(newdir, RunTask.LOG_FILE_NAME, print);
        if (runLog != null) {
            try {
                print.getOpts().setInfoErrFile(runLog.getAbsolutePath());
            } catch (Exception e) {
                print.errln("Problem setting InfoErrFile: " + e.getMessage());
                // carry on
            }
        }

        final File debugLog =
               HistoryUtil.newLogFile(newdir, RunTask.DEBUG_LOG_FILE_NAME, print);
        if (debugLog != null) {
            try {
                print.getOpts().setAllOutFile(debugLog.getAbsolutePath());
            } catch (Exception e) {
                print.errln("Problem setting AllOutFile: " + e.getMessage());
                // carry on
            }
        }

        boolean usingContextBroker = false;
        for (CloudDeployment cloud : deploys) {
            if (cloud.hasContextualization()) {
                usingContextBroker = true;
                break;
            }
        }
        final String ctxEprPath;
        final String ctxReportsDirPath;
        final BrokerContactType brokerContact;

        if (!usingContextBroker) {
            ctxEprPath = null;
            ctxReportsDirPath = null;
            brokerContact = null;
        } else {

            final File ctxFile = new File(newdir,
                                          HistoryUtil.CONTEXT_EPR_FILE_NAME);
            ctxEprPath = ctxFile.getAbsolutePath();

            final File newdir3 = new File(newdirPath, "reports-ctx");
            ctxReportsDirPath = newdir3.getAbsolutePath();
            if (newdir3.mkdir()) {
                print.debugln("Created directory: " + ctxReportsDirPath);
            } else {
                throw new ExecutionProblem(
                        "Could not create directory '" + ctxReportsDirPath + "'");
            }

            final File newdir4 = new File(newdirPath, "ctx-tmp");
            final String ctxTempDirPath = newdir4.getAbsolutePath();
            if (newdir4.mkdir()) {
                print.debugln("Created directory: " + ctxTempDirPath);
            } else {
                throw new ExecutionProblem(
                        "Could not create directory '" + ctxTempDirPath + "'");
            }


            try {
                brokerContact = this.createCtx(brokerURL,
                                               brokerIdentityAuthorization,
                                               ctxEprPath,
                                               newdir4,
                                               false,
                                               print);
            } catch (Exception e) {
                throw new ExecutionProblem("Problem creating new context at " +
                        "the context broker: " + e.getMessage(), e);
            }
        }

        final String[] ensembleEprPaths =
            new String[deploys.size()];

        // Ensemble requests won't get time assignments, remove the
        // "will be set after lease is secured" messages when registering
        print.getOpts().codeRemove(
                PrCodes.CREATE__INSTANCE_CREATING_INIITIAL_START_TIME);
        print.getOpts().codeRemove(
                PrCodes.CREATE__INSTANCE_CREATING_INIITIAL_SHUTDOWN_TIME);
        print.getOpts().codeRemove(
                PrCodes.CREATE__INSTANCE_CREATING_INIITIAL_TERMINATION_TIME);
        print.getOpts().codeRemove(PrCodes.CREATE__GROUP_ID_PRINT);
        print.getOpts().codeRemove(PrCodes.ENSMONITOR__SINGLE_REPORT_NAMES);
        print.getOpts().codeRemove(PrCodes.CTXMONITOR__SINGLE_REPORT_NAMES);

        for (int i = 0; i < clouds.length; i++) {
            CloudDeployment cloud = clouds[i];
            final File cloudDir = new File(newdir,
                "cloud-" + cloud.getCloud().getName());
            final String cloudDirPath = cloudDir.getAbsolutePath();
            if (cloudDir.mkdir()) {
                print.debugln("Created directory: " + cloudDirPath);
            } else {
                throw new ExecutionProblem(
                    "Could not create directory '" + cloudDirPath + "'");
            }

            final RunTask[] runTasks = cloud.generateRunTasks(brokerContact,
                cloudDirPath, sshKeyPath, durationMinutes, print);
            final FutureTask[] futureTasks = new FutureTask[runTasks.length];
            for (int taskIndex = 0; taskIndex < futureTasks.length; taskIndex++) {
                futureTasks[taskIndex] = new FutureTask(runTasks[taskIndex]);
            }

            final String ensembleEprPath = runTasks[0].getEnsembleEprPath();

            final String identAuth = cloud.getCloud().getFactoryID();
            final String handle = cloud.getCloud().getName();

            print.infoln("\nLaunching "+handle+"...");

            try {
            startAllMembersWithBackout(futureTasks, ensembleEprPath,
                identAuth, handle, print);
            } catch (ExecutionProblem e) {
                destroyMultiCloudCluster(clouds, ensembleEprPaths, print);
                throw e;
            } catch (ExitNow e) {
                destroyMultiCloudCluster(clouds, ensembleEprPaths, print);
                throw e;
            }

            ensembleEprPaths[i] = ensembleEprPath;
        }

        print.infoln("\nWaiting for launch updates.");
         for (int i = 0; i < clouds.length; i++) {
            CloudDeployment cloud = clouds[i];
            final String ensembleEprPath = ensembleEprPaths[i];
            final String identAuth =  cloud.getCloud().getFactoryID();
            final String handle =  cloud.getCloud().getName();

            try {
            this.clusterMonitor(ensembleEprPath,
                identAuth,
                handle,
                null, //TODO set up reports dir
                pollMs,
                print);

            } catch (ExecutionProblem e) {
                destroyMultiCloudCluster(clouds, ensembleEprPaths, print);
                throw e;
            } catch (ExitNow e) {
                destroyMultiCloudCluster(clouds, ensembleEprPaths, print);
                throw e;
            }
        }

        if (!usingContextBroker) {
            return;
        }

        print.infoln("\nWaiting for context broker updates.");

        try {
        this.ctxMonitor(ctxEprPath, brokerIdentityAuthorization,
            multiclusterHandle, null, null, null, pollMs, print);
        } catch (ExecutionProblem e) {
            destroyMultiCloudCluster(clouds, ensembleEprPaths, print);
            throw e;
        } catch (ExitNow e) {
            destroyMultiCloudCluster(clouds, ensembleEprPaths, print);
            throw e;
        }
    }

    private void destroyMultiCloudCluster(CloudDeployment[] clouds,
                                          String[] ensembleEprPaths,
                                          Print print) {

        if (clouds == null) {
            throw new IllegalArgumentException("clouds may not be null");
        }
        if (ensembleEprPaths == null) {
            throw new IllegalArgumentException("ensembleEprPaths may not be null");
        }

        if (clouds.length != ensembleEprPaths.length) {
            throw new IllegalArgumentException("lengths of clouds and " +
                "ensembleEprPaths arrays must match");
        }
        print.errln("\nProblem, attempting to destroy cluster.");

        for (int i=0; i<clouds.length; i++) {
            final CloudDeployment cloud = clouds[i];
            final String ensembleEprPath = ensembleEprPaths[i];

            if (ensembleEprPath == null) {
                continue;
    }

            final File f = new File(ensembleEprPath);
            if (!f.exists()) {
                continue;
            }

            final String handle = cloud.getCloud().getName();

            try {
            this.destroyCluster(ensembleEprPath,
                cloud.getCloud().getFactoryID(),
                handle,
                print);
            } catch (Throwable e) {
                print.errln("Failed to destroy '"+handle+"': "+e.toString());
            }
            print.errln("\nDestroyed '" + handle + "'");
        }
    }
   
    // -------------------------------------------------------------------------
    // START VIRTUAL CLUSTER
    // -------------------------------------------------------------------------

    public void startWorkspaceCluster(String workspaceFactoryURL,
                                      KnownHostsTask[] knownHostTasks,
                                      VirtualWorkspace_Type[] metadatas,
                                      String[] metadata_fileNames,
                                      WorkspaceDeployment_Type[] deploymentRequests,
                                      String[] deploymentRequest_fileNames,
                                      String[] printNames,
                                      Cloudcluster_Type[] clustersForUserData,
                                      boolean doContextLock,
                                      String sshfile,
                                      String ssh_hostsfile,
                                      String historyDir,
                                      long pollMs,
                                      String identityAuthorization,
                                      Print print,
                                      String brokerURL,
                                      String brokerIdentityAuthorization)

            throws ExecutionProblem, ExitNow {

        final File newdir = createNewClusterDir(historyDir, print);
        final String newdirPath = newdir.getAbsolutePath();
        final String clusterHandle = newdir.getName();

        final File runLog =
                HistoryUtil.newLogFile(newdir, RunTask.LOG_FILE_NAME, print);
        if (runLog != null) {
            try {
                print.getOpts().setInfoErrFile(runLog.getAbsolutePath());
            } catch (Exception e) {
                print.errln("Problem setting InfoErrFile: " + e.getMessage());
                // carry on
            }
        }

        final File debugLog =
               HistoryUtil.newLogFile(newdir, RunTask.DEBUG_LOG_FILE_NAME, print);
        if (debugLog != null) {
            try {
                print.getOpts().setAllOutFile(debugLog.getAbsolutePath());
            } catch (Exception e) {
                print.errln("Problem setting AllOutFile: " + e.getMessage());
                // carry on
            }
        }

        final String reportDirPath = makeDirectory(newdirPath, "reports-vm", print);
        final String eprIdIpDirPath = makeDirectory(newdirPath, "id-ip-dir", print);

        String knownHostsDirPath = null;
        if (knownHostTasks != null) {
            for (KnownHostsTask knownHostTask : knownHostTasks) {
                if (knownHostTask.perHostDir) {
                    final File newdir6 = new File(newdirPath, "knownhosts-dir");
                    knownHostsDirPath = newdir6.getAbsolutePath();
                    if (newdir6.mkdir()) {
                        print.debugln("Created directory: " + knownHostsDirPath);
                    } else {
                        throw new ExecutionProblem(
                                "Could not create directory '" +
                                        knownHostsDirPath + "'");
                    }
                    break;
                }
            }
        }

        // see comments inside loop about ensemble and context EPRs
        final File ensFile = new File(newdir,
                                      HistoryUtil.ENSEMBLE_EPR_FILE_NAME);
        final String ensembleEprPath = ensFile.getAbsolutePath();

        // do we need to handle contextualization?
        boolean usingContextBroker = false;
        for (Cloudcluster_Type oneclusta : clustersForUserData) {
            if (oneclusta != null) {
                usingContextBroker = true;
                break;
            }
        }

       
        final String ctxEprPath;
        final String ctxReportsDirPath;
        final String[] ctxUserDataPaths = new String[metadatas.length];

        if (!usingContextBroker) {
            ctxEprPath = null;
            ctxReportsDirPath = null;
        } else {

            final File ctxFile = new File(newdir,
                                          HistoryUtil.CONTEXT_EPR_FILE_NAME);
            ctxEprPath = ctxFile.getAbsolutePath();

            final File newdir3 = new File(newdirPath, "reports-ctx");
            ctxReportsDirPath = newdir3.getAbsolutePath();
            if (newdir3.mkdir()) {
                print.debugln("Created directory: " + ctxReportsDirPath);
            } else {
                throw new ExecutionProblem(
                        "Could not create directory '" + ctxReportsDirPath + "'");
            }

            final File newdir4 = new File(newdirPath, "ctx-tmp");
            final String ctxTempDirPath = newdir4.getAbsolutePath();
            if (newdir4.mkdir()) {
                print.debugln("Created directory: " + ctxTempDirPath);
            } else {
                throw new ExecutionProblem(
                        "Could not create directory '" + ctxTempDirPath + "'");
            }

            if (brokerURL == null) {
                int dx = workspaceFactoryURL.indexOf("WorkspaceFactoryService");
                brokerURL = workspaceFactoryURL.substring(0,dx);
                brokerURL += "NimbusContextBroker";
                print.debugln("No context broker URL was explicitly supplied," +
                        " so it has been deduced from the nimbus factory URL." +
                        " Using: " + brokerURL);

                // and so ID scheme for service must be copied
                if (brokerIdentityAuthorization == null
                        && identityAuthorization != null) {
                    brokerIdentityAuthorization = identityAuthorization;
                }
            }

            final BrokerContactType brokerContact;
            try {
                brokerContact = this.createCtx(brokerURL,
                                               brokerIdentityAuthorization,
                                               ctxEprPath,
                                               newdir4,
                                               !doContextLock,
                                               print);
            } catch (Exception e) {
                throw new ExecutionProblem("Problem creating new context at " +
                        "the context broker: " + e.getMessage(), e);
            }

            // prepare user data
            for (int i = 0; i < clustersForUserData.length; i++) {

                final Cloudcluster_Type oneCtx = clustersForUserData[i];

                if (oneCtx == null) {
                    ctxUserDataPaths[i] = null;
                    continue;
                }

                ctxUserDataPaths[i] = HistoryUtil.writeUserData(newdir4,
                    "userdata-" + i, brokerContact, oneCtx);
            }
        }

        final String[] allEPRpaths = new String[metadatas.length];

        final FutureTask[] tasks = new FutureTask[metadatas.length];
        for (int i = 0; i < metadatas.length; i++) {

            final String memberName;
            if (printNames[i] == null) {
                memberName = HistoryUtil.getMemberName(i+1);
            } else {
                memberName = printNames[i];
            }

            print.debugln("Creating runtask for " + memberName);
            print.debugln("");

            final String eprPath;
            if (deploymentRequests[i].getNodeNumber() > 1) {

                final File eprFile = new File(newdir, memberName + "-epr");
                eprPath = eprFile.getAbsolutePath();
                print.debugln("Group EPR will be written to:");
                print.debugln("  - '" + eprPath + "'");
                print.debugln("");

            } else {

                final File eprFile = new File(newdir, memberName + "-epr.xml");
                eprPath = eprFile.getAbsolutePath();
                print.debugln("EPR will be written to:");
                print.debugln("  - '" + eprPath + "'");
                print.debugln("");
            }
            allEPRpaths[i] = eprPath;


            /* ensemble related */

            // EPR path is the same for each, the different thing is whether
            // we trigger new ensemble/ctx creation (creating an EPR file) or
            // have the deployment join a previously created ensemble/ctx (using
            // path to the ensemble/ctx EPR file)
            //
            // If you were to not go one by one below and launch all requests
            // at once, the first would still need to be launched first.  The
            // rest would need to wait until the ensemble (and ctx) EPR file
            // appeared on the filesystem.

            boolean newEnsemble = false;
            if (i == 0) {
                newEnsemble = true;
            }

            tasks[i] = this.getWorkspaceTask(workspaceFactoryURL,
                                             eprPath,
                                             metadatas[i],
                                             metadata_fileNames[i],
                                             deploymentRequests[i],
                                             deploymentRequest_fileNames[i],
                                             sshfile,
                                             newdir,
                                             memberName,
                                             pollMs,
                                             identityAuthorization,
                                             true,
                                             null,
                                             ensembleEprPath,
                                             newEnsemble,
                                             true,
                                             print,
                                             ctxUserDataPaths[i],
                                             eprIdIpDirPath);
        }


        // Ensemble requests won't get time assignments, remove the
        // "will be set after lease is secured" messages when registering
        print.getOpts().codeRemove(
                PrCodes.CREATE__INSTANCE_CREATING_INIITIAL_START_TIME);
        print.getOpts().codeRemove(
                PrCodes.CREATE__INSTANCE_CREATING_INIITIAL_SHUTDOWN_TIME);
        print.getOpts().codeRemove(
                PrCodes.CREATE__INSTANCE_CREATING_INIITIAL_TERMINATION_TIME);
        print.getOpts().codeRemove(PrCodes.CREATE__GROUP_ID_PRINT);
        print.getOpts().codeRemove(PrCodes.ENSMONITOR__SINGLE_REPORT_NAMES);
        print.getOpts().codeRemove(PrCodes.CTXMONITOR__SINGLE_REPORT_NAMES);

        this.startAllMembersWithBackout(tasks,
                                        ensembleEprPath,
                                        identityAuthorization,
                                        clusterHandle,
                                        print);

        try {

            print.infoln("\nWaiting for launch updates.");

            final long launch_start = System.currentTimeMillis();

            // all started, launch ensemble monitor and wait for all
            // workspaces to move to state 'Running'
            this.clusterMonitor(ensembleEprPath,
                                identityAuthorization,
                                clusterHandle,
                                reportDirPath,
                                pollMs,
                                print);

            final long launch_stop = System.currentTimeMillis();
            print.debugln(timeStr("Hearing about launch",
                                  launch_stop - launch_start));

            if (!usingContextBroker) {
                print.debugln("\ndone (not using context broker)");
                return; // *** EARLY RETURN ***
            }

            print.infoln("\nWaiting for context broker updates.");

            // find specific EPR IPs in order to key the known_hosts request
            // correctly.
            final KnownHostsTask[] sendTasks;
            if (knownHostTasks != null) {
                sendTasks =
                    hostTaskIDs(knownHostTasks, allEPRpaths,
                                print, eprIdIpDirPath, knownHostsDirPath);
            } else {
                sendTasks = null;
            }

            final long ctx_start = System.currentTimeMillis();
           
            // all 'Running', launch context monitor and wait for all
            // workspaces to report 'OK' to the context broker
            this.ctxMonitor(ctxEprPath,
                            brokerIdentityAuthorization,
                            clusterHandle,
                            ctxReportsDirPath,
                            sendTasks,
                            ssh_hostsfile,
                            pollMs,
                            print);

            final long ctx_stop = System.currentTimeMillis();
            print.debugln(timeStr("Hearing about contextualization",
                                  ctx_stop - ctx_start)
                        + " more after hearing about launch");

        } catch (ExitNow e) {

            print.errln("\nProblem, attempting to destroy cluster.");
            this.destroyCluster(ensembleEprPath,
                                identityAuthorization,
                                clusterHandle,
                                print);
            print.errln("\nDestroyed '" + clusterHandle + "'");

            throw e;

        } catch (ExecutionProblem e) {

            print.errln("\nProblem, attempting to destroy cluster.");
            this.destroyCluster(ensembleEprPath,
                                identityAuthorization,
                                clusterHandle,
                                print);
            print.errln("\nDestroyed '" + clusterHandle + "'");

            throw e;
        }
    }

    public static String makeDirectory(String parentDir, String name, Print print)
        throws ExecutionProblem {
        final File newDir = new File(parentDir, name);
        final String newdir2Path = newDir.getAbsolutePath();
        if (newDir.mkdir()) {
            print.debugln("Created directory: " + newdir2Path);
        } else {
            throw new ExecutionProblem(
                    "Could not create directory '" + newdir2Path + "'");
        }
        return newdir2Path;
    }

    static File createNewClusterDir(String historyDir, Print print)
        throws ExecutionProblem {
        return createNewLaunchDir(historyDir, print,
            HistoryUtil.historyClusterDirPrefix);
    }

    static File createNewMultiClusterDir(String historyDir, Print print)
        throws ExecutionProblem {
        return createNewLaunchDir(historyDir, print,
            HistoryUtil.historyMultiClusterDirPrefix);
    }

    private static File createNewLaunchDir(String historyDir, Print print, String prefix)
        throws ExecutionProblem {

        final File topdir;
        try {
            topdir = CloudClientUtil.getHistoryDir(historyDir);
        } catch (ParameterProblem e) {
            throw new ExecutionProblem(e.getMessage(), e);
        }

        final int nextnum = HistoryUtil.findNextNumber(topdir, prefix, print);

        final String suffix = HistoryUtil.format.format(nextnum);
        final String newDirName = prefix + suffix;

        print.debugln("Next directory: " + newDirName);

        final File newdir = new File(topdir, newDirName);
        final String path = newdir.getAbsolutePath();
        if (newdir.mkdir()) {
            print.debugln("Created directory: " + path);
        } else {
            // could be a race condition on the name, or odd perm problem
            // (note we checked parent dir was writeable)
            throw new ExecutionProblem(
                    "Could not create directory '" + path + "'");
        }
        return newdir;
    }

    public void ctxClusterHelp(ClusterMember[] clusterMembers,
                               String brokerURL,
                               String brokerID,
                               boolean doContextLock,
                               String tempDirPath,
                               Print print)
        throws ExecutionProblem, ExitNow {

        if (clusterMembers == null || clusterMembers.length == 0) {
            throw new ExecutionProblem("no clusterMembers");
        }

        final boolean usingContextBroker =
                needsContextualization(clusterMembers);

        if (!usingContextBroker) {
            throw new ExecutionProblem("cluster doesn't need contextualization!");
        }

        File tempDir = new File(tempDirPath);
        if (!(tempDir.exists() && tempDir.isDirectory() && tempDir.canWrite())) {
            throw new ExecutionProblem("tempdir must exist and be writeable");
        }


        final File ctxFile = new File(tempDir,
                                          HistoryUtil.CONTEXT_EPR_FILE_NAME);
        final String ctxEprPath = ctxFile.getAbsolutePath();
        final String[] ctxUserDataPaths = new String[clusterMembers.length];

        final File manifestFile = new File(tempDir, "manifest.txt");

        createCtxAndUserdata(clusterMembers,
                    brokerURL,
                    brokerID,
                    doContextLock,
                    ctxEprPath,
                    ctxUserDataPaths,
                    tempDir,
                    print);

        // TODO arbitary!
        // This method needs to either Go Away or a better
        // serialization scheme needs to be used.

        StringBuilder sb = new StringBuilder();
        for (int i=0; i < clusterMembers.length; i++) {
            sb.append(clusterMembers[i].getImageName());
            sb.append("\t");
            sb.append(clusterMembers[i].getQuantity());
            sb.append("\t");
            sb.append(ctxUserDataPaths[i]);
            sb.append("\n");
        }

        try {
            FileUtils.writeStringToFile(sb.toString(),
                    manifestFile.getAbsolutePath());
        } catch (Exception e) {
            throw new ExecutionProblem("Problem writing cluster manifest",e);
        }

    }


    // -------------------------------------------------------------------------
    // EC2 CLUSTER HELP
    // -------------------------------------------------------------------------

    public void ec2ClusterHelp(ClusterMember[] clusterMembers,
                               String brokerURL,
                               String brokerID,
                               boolean doContextLock,
                               long pollMs,
                               String ec2ScriptPath,
                               String historyDir,
                               Print print
    )

            throws ExecutionProblem, ExitNow {

        if (clusterMembers == null || clusterMembers.length == 0) {
            throw new ExecutionProblem("no clusterMembers");
        }

        final File topdir;
        try {
            topdir = CloudClientUtil.getHistoryDir(historyDir);
        } catch (ParameterProblem e) {
            throw new ExecutionProblem(e.getMessage(), e);
        }

        final int nextnum = HistoryUtil.findNextEc2ClusterNumber(topdir, print);

        final String suffix = HistoryUtil.format.format(nextnum);
        final String newDirName =
                HistoryUtil.historyEc2ClusterDirPrefix + suffix;
        final String clusterHandle = newDirName; // redundant, but clearer later

        print.debugln("Next directory: " + newDirName);

        final File newdir = new File(topdir, newDirName);
        final String newdirPath = newdir.getAbsolutePath();
        if (newdir.mkdir()) {
            print.debugln("Created directory: " + newdirPath);
        } else {
            // could be a race condition on the name, or odd perm problem
            // (note we checked parent dir was writeable)
            throw new ExecutionProblem(
                    "Could not create directory '" + newdirPath + "'");
        }

        final File runLog =
                HistoryUtil.newLogFile(newdir, RunTask.LOG_FILE_NAME, print);
        if (runLog != null) {
            try {
                print.getOpts().setInfoErrFile(runLog.getAbsolutePath());
            } catch (Exception e) {
                print.errln("Problem setting InfoErrFile: " + e.getMessage());
                // carry on
            }
        }

        final File debugLog =
               HistoryUtil.newLogFile(newdir, RunTask.DEBUG_LOG_FILE_NAME, print);
        if (debugLog != null) {
            try {
                print.getOpts().setAllOutFile(debugLog.getAbsolutePath());
            } catch (Exception e) {
                print.errln("Problem setting AllOutFile: " + e.getMessage());
                // carry on
            }
        }

        // do we need to handle contextualization?
        final boolean usingContextBroker =
                needsContextualization(clusterMembers);

        final String ctxEprPath;
        final String ctxReportsDirPath;
        final String[] ctxUserDataPaths = new String[clusterMembers.length];

        if (!usingContextBroker) {
            ctxEprPath = null;
            ctxReportsDirPath = null;
        } else {

            final File ctxFile = new File(newdir,
                                          HistoryUtil.CONTEXT_EPR_FILE_NAME);
            ctxEprPath = ctxFile.getAbsolutePath();

            final File ctxReportDir = new File(newdirPath, "reports-ctx");
            ctxReportsDirPath = ctxReportDir.getAbsolutePath();
            if (ctxReportDir.mkdir()) {
                print.debugln("Created directory: " + ctxReportsDirPath);
            } else {
                throw new ExecutionProblem(
                    "Could not create directory '" + ctxReportsDirPath + "'");
            }

            final File ctxTempDir = new File(newdirPath, "ctx-tmp");
            final String ctxTempDirPath = ctxTempDir.getAbsolutePath();
            if (ctxTempDir.mkdir()) {
                print.debugln("Created directory: " + ctxTempDirPath);
            } else {
                throw new ExecutionProblem(
                        "Could not create directory '" + ctxTempDirPath + "'");
            }


            createCtxAndUserdata(clusterMembers,
                    brokerURL,
                    brokerID,
                    doContextLock,
                                               ctxEprPath,
                    ctxUserDataPaths,
                    ctxTempDir,
                                               print);
        }

        // write the ec2 commands to both screen and a file

        final StringBuffer buf = new StringBuffer();

        for (int i = 0; i < clusterMembers.length; i++) {
            buf.append("\nec2-run-instances")
               .append(" --instance-count ")
               .append(clusterMembers[i].getQuantity());

            if (usingContextBroker && ctxUserDataPaths[i] != null) {
                buf.append(" --user-data-file ")
                   .append(ctxUserDataPaths[i]);
            }
           
            buf.append(" --kernel aki-a71cf9ce --ramdisk ari-a51cf9cc");

            // m1.small, m1.large, m1.xlarge, c1.medium, and c1.xlarge
            buf.append(" --instance-type m1.small ");
            buf.append(" --key default ");
            buf.append(clusterMembers[i].getImageName());
            buf.append("\n");
        }

        final String cmds = buf.toString();

        print.infoln("\n** Sample EC2 commands:\n" + cmds);

        if (ec2ScriptPath != null) {

            final String toFile = "#!/bin/sh\n\n" + cmds + "\n";

            try {
                FileUtils.writeStringToFile(toFile, ec2ScriptPath);
            } catch (Exception e) {
                throw new ExecutionProblem("Problem writing sample EC2 " +
                        "commands to file: " + e.getMessage(), e);
            }

            print.infoln("\n** Wrote sample EC2 commands to '" +
                    ec2ScriptPath + "'\n");
        }

        if (!usingContextBroker) {
            print.debugln("\ndone (not using context broker)");
            return; // *** EARLY RETURN ***
        }

        print.infoln("\nWaiting for context broker updates.");

        final long ctx_start = System.currentTimeMillis();

        // all 'Running', launch context monitor and wait for all
        // EC2 VMs to report 'OK' to the context broker
        this.ctxMonitor(ctxEprPath,
                brokerID,
                        clusterHandle,
                        ctxReportsDirPath,
                        null,
                        null,
                        pollMs,
                        print);

        final long ctx_stop = System.currentTimeMillis();
        print.debugln(timeStr("Hearing about contextualization",
                              ctx_stop - ctx_start)
                    + " more after hearing about launch");

    }

    private boolean needsContextualization(ClusterMember[] clusterMembers) {
        boolean usingContextBroker = false;
        for (ClusterMember member : clusterMembers) {
            if (member.getClusterForUserData() != null) {
                usingContextBroker = true;
                break;
            }
        }
        return usingContextBroker;
    }

    private void createCtxAndUserdata(ClusterMember[] clusterMembers,
                                      String brokerURL,
                                      String brokerID,
                                      boolean doContextLock,
                                      String ctxEprPath,
                                      String[] ctxUserDataPaths,
                                      File ctxTempDir,
                                      Print print) throws ExitNow, ExecutionProblem {

        final BrokerContactType brokerContact;
        try {
            brokerContact = this.createCtx(brokerURL,
                    brokerID,
                    ctxEprPath,
                    ctxTempDir,
                    !doContextLock,
                    print);
        } catch (Exception e) {
            throw new ExecutionProblem("Problem creating new context at " +
                    "the context broker: " + e.getMessage(), e);
        }

        // prepare user data
        for (int i = 0; i < clusterMembers.length; i++) {
            ClusterMember member = clusterMembers[i];
            final Cloudcluster_Type oneCtx = member.getClusterForUserData();

            if (oneCtx == null) {
                ctxUserDataPaths[i] = null;
                continue;
            }

            final File datafile = new File(ctxTempDir, "userdata-" + i);

            ctxUserDataPaths[i] = datafile.getAbsolutePath();

            Nimbusctx_Type wrapper = new Nimbusctx_Type();
            wrapper.setCluster(oneCtx);
            wrapper.setContact(brokerContact);

            final QName qName = new QName("", "NIMBUS_CTX");

            try {
                final String data =
                        StringUtils.axisBeanToString(wrapper, qName);

                FileUtils.writeStringToFile(data, ctxUserDataPaths[i]);

            } catch (Exception e) {
                throw new ExecutionProblem("Problem turning the cluster " +
                        "information into text that the context agents " +
                        "on the VMs can consume: " + e.getMessage(), e);
            }
        }
    }

    private BrokerContactType createCtx(String brokerURL,
                                        String brokerID,
                                        String createdContextEprPath,
                                        File ctxTempDir,
                                        boolean expectInjections,
                                        Print print)
            throws ExitNow, ExecutionProblem {

        final String sectionTitle = "ACTION: CREATE CONTEXT";
        CommonPrint.printDebugSection(print, sectionTitle);

        final File brokerContactFile = new File(ctxTempDir, "contact.xml");
        final String contactPath = brokerContactFile.getAbsolutePath();

        final CreateContextTask ccTask =
                new CreateContextTask(brokerURL,
                                      createdContextEprPath,
                                      contactPath,
                                      expectInjections,
                                      brokerID,
                                      print);

        final FutureTask task = new FutureTask(ccTask);
       

        this.executor.submit(task);

        final BrokerContactType brokerContact;
        try {
            final Integer retCode = (Integer) task.get();
            if (retCode.intValue() == BaseClient.SUCCESS_EXIT_CODE) {
                brokerContact =
                        FileUtils.getBrokerContactFromFile(print,
                                                           contactPath);
                print.infoln("\nCreated new context with broker.");
            } else {
                print.errln("\nProblem creating new context with broker.");
                throw new ExitNow(retCode.intValue());
            }
        } catch (InterruptedException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        } catch (Exception e) {
            final String err = "Problem creating new context with " +
                    "broker: " + e.getMessage();
            throw new ExecutionProblem(err, e);
        }

        CommonPrint.printDebugSectionEnd(print, sectionTitle);

        return brokerContact;
    }

    private static String timeStr(String opname, long ms) {
        final long sec = ms/1000;
        final long min = sec/60;
        final long secRemaining = sec % 60;
        return "\n[[ " + opname + " took around " + min + " minutes, " +
                secRemaining + " seconds (" + sec  + " seconds)";
    }

    private static KnownHostsTask[] hostTaskIDs(KnownHostsTask[] tasks,
                                                String[] allEPRPaths,
                                                Print pr,
                                                String eprIdIpDirPath,
                                                String knownHostsDirPath) {

        if (tasks == null || tasks.length == 0) {
            return null;
        }

        if (allEPRPaths == null || allEPRPaths.length == 0) {
            throw new IllegalArgumentException("no allEPRPaths?");
        }

        final List newTaskList = new ArrayList(64);

        final IdIpPair[] pairs = getAllIdIpMappings(eprIdIpDirPath);
        if (pairs == null || pairs.length == 0) {
            pr.errln("Could not find IP addresses in order to obtain " +
                     "SSH hostkeys from the context broker.");
            return null;
        }

        // get all workspace IDs and IPs for each member
        for (final KnownHostsTask task : tasks) {
            // eprID was overloaded as member index
            final int[] allids = allIDs(allEPRPaths[task.eprID], pr);
            for (int j = 0; j < allids.length; j++) {

                String printName = task.printName;
                if (printName != null && allids.length > 1) {
                    // append number
                    printName = printName + " #" + j;
                }

                for (IdIpPair pair : pairs) {
                    if (pair.id == allids[j]) {
                        newTaskList.add(
                                new KnownHostsTask(allids[j],
                                                   pair.ip,
                                                   task.interfaceName,
                                                   printName,
                                                   knownHostsDirPath != null,
                                                   knownHostsDirPath));
                        break;
                    }
                }
            }
        }

        return (KnownHostsTask[]) newTaskList.toArray(
                                    new KnownHostsTask[newTaskList.size()]);
    }

    private static IdIpPair[] getAllIdIpMappings(String eprIdIpDirPath) {
        if (eprIdIpDirPath == null) {
            return new IdIpPair[0];
        }
        final File dir = new File(eprIdIpDirPath);
        if (!dir.exists()) {
            return new IdIpPair[0];
        }
        final File[] indvFiles = dir.listFiles();
        if (indvFiles == null) {
            return new IdIpPair[0];
        }

        final ArrayList all = new ArrayList();
        for (File indvFile : indvFiles) {
            String fName = indvFile.getName();
            String[] parts = fName.split("-");
            if (parts == null || parts.length != 2) {
                continue;
            }
            final int id = Integer.parseInt(parts[0]);
            all.add(new IdIpPair(id, parts[1].trim()));
        }

        return (IdIpPair[]) all.toArray(new IdIpPair[all.size()]);
    }

    private static class IdIpPair {
        private final int id;
        private final String ip;
        private IdIpPair(int id, String ip) {
            this.id = id;
            this.ip = ip;
        }
    }

    private static int[] allIDs(String pathPrefix, Print pr) {

        pr.debugln("\nFind allIDs:\n");

        final File f = new File(pathPrefix);
        final File dir = f.getParentFile();

        pr.debugln("f = " + f.getAbsolutePath());
        pr.debugln("dir = " + dir.getAbsolutePath());
        pr.debugln("prefixname = " + f.getName());

        final String[] eprFiles = dir.list(new prefixFilter(f.getName()));
        pr.debugln("eprFiles.length " + eprFiles.length);

        final List intList = new ArrayList(32);

        for (int i = 0; i < eprFiles.length; i++) {
            final File eprFile = new File(dir, eprFiles[i]);
            pr.debugln("onefile = " + eprFile.getAbsolutePath());
            try {
                final EndpointReferenceType epr =
                        FileUtils.getEPRfromFile(eprFile);
                pr.debugln("Found epr:\n" + epr.toString());
                final int id = EPRUtils.getIdFromEPR(epr);
                pr.debugln("\nFound id: " + id);
                intList.add(new Integer(id));
            } catch (Throwable t) {
                final String err = CommonUtil.genericExceptionMessageWrapper(t);
                pr.debugln("Problem examining EPR file @ '" +
                        eprFile.getAbsolutePath() + "': " + err);
                // keep going.
            }
        }

        final int[] ids = new int[intList.size()];
        for (int i = 0; i < ids.length; i++) {
            ids[i] = ((Number)intList.get(i)).intValue();
        }
        return ids;
    }
    private static class prefixFilter implements FilenameFilter {
        private final String prefix;
        private prefixFilter(String prefix) {
            this.prefix = prefix;
        }
        public boolean accept(File dir, String name) {
            final File test = new File(dir, name);
            if (prefix == null) {
                return true;
            }
            return test.getName().startsWith(this.prefix);
        }
    }

    private void startAllMembersWithBackout(FutureTask[] tasks,
                                            String ensembleEprPath,
                                            String identityAuthorization,
                                            String clusterName,
                                            Print print)
            throws ExitNow, ExecutionProblem {

        // Because this is an ensemble request, we go one by one with
        // the workspace service requests to make screen printing nice.
        // Because we've forced no subscriptions, the workspace service
        // requests will return immediately after creation

        // Once all the requests are sent to the workspace service, only then
        // does the ensemble "go" signal get sent in a separate operation
        // (this.clusterDone)


        // If not firstSucceeded, there is nothing to back out
        boolean firstSucceeded = false;

        try {

            for (int i = 0; i < tasks.length; i++) {

                this.executor.submit(tasks[i]);

                final String memberName = HistoryUtil.getMemberName(i+1);

                try {
                    final Integer retCode = (Integer) tasks[i].get();
                    if (retCode.intValue() == BaseClient.SUCCESS_EXIT_CODE) {
                        print.debugln("* Registered " + memberName);
                    } else {
                        print.errln("\nProblem registering " + memberName);
                        throw new ExitNow(retCode.intValue(),
                            "Failed to register "+ memberName);
                    }
                } catch (InterruptedException e) {
                    throw new ExecutionProblem(e.getMessage(), e);
                } catch (ExecutionException e) {
                    throw new ExecutionProblem(e.getMessage(), e);
                }

                if (i == 0) {
                    firstSucceeded = true;
                   
                    // only print factory URL once
                    print.getOpts().codeRemove(
                            PrCodes.CREATE__FACTORY_ENDPOINT);
                    print.infoln();
                }
            }

            this.clusterDone(ensembleEprPath,
                             identityAuthorization,
                             clusterName,
                             print);

        } catch (ExitNow e) {

            if (firstSucceeded) {
                print.errln("Problem, attempting to destroy cluster.");
                this.destroyCluster(ensembleEprPath,
                                    identityAuthorization,
                                    clusterName,
                                    print);
                print.errln("\nDestroyed '" + clusterName + "'");
            }

            throw e;

        } catch (ExecutionProblem e) {

            if (firstSucceeded) {
                print.errln("Problem, attempting to destroy cluster.");
                this.destroyCluster(ensembleEprPath,
                                    identityAuthorization,
                                    clusterName,
                                    print);
                print.errln("\nDestroyed '" + clusterName + "'");
            }

            throw e;
        }
    }

    private void destroyCluster(String ensembleEprPath,
                                String identityAuthorization,
                                String clusterName,
                                Print print) throws ExitNow, ExecutionProblem {

        final DestroyTask dTask = new DestroyTask(ensembleEprPath,
                                                  identityAuthorization,
                                                  clusterName,
                                                  print);

        final FutureTask task = new FutureTask(dTask);
        this.executor.submit(task);

        try {
            final Integer retCode = (Integer) task.get();
            if (retCode.intValue() != BaseClient.SUCCESS_EXIT_CODE) {
                throw new ExitNow(retCode.intValue());
            }
        } catch (InterruptedException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        } catch (ExecutionException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        }
    }

    private void clusterDone(String ensembleEprPath,
                             String identityAuthorization,
                             String clusterName,
                             Print print) throws ExitNow, ExecutionProblem {

        final ClusterDoneTask dTask =
                new ClusterDoneTask(ensembleEprPath,
                                    identityAuthorization,
                                    clusterName,
                                    print);

        final FutureTask task = new FutureTask(dTask);
        this.executor.submit(task);

        try {
            final Integer retCode = (Integer) task.get();
            if (retCode.intValue() != BaseClient.SUCCESS_EXIT_CODE) {
                throw new ExitNow(retCode.intValue());
            }
        } catch (InterruptedException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        } catch (ExecutionException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        }
    }

    private void clusterMonitor(String ensembleEprPath,
                                String identityAuthorization,
                                String clusterName,
                                String reportDirectory,
                                long pollMs,
                                Print print) throws ExitNow, ExecutionProblem {

        final ClusterMonitorTask mTask =
                new ClusterMonitorTask(ensembleEprPath,
                                       identityAuthorization,
                                       clusterName,
                                       reportDirectory,
                                       pollMs,
                                       print);

        final FutureTask task = new FutureTask(mTask);
        this.executor.submit(task);

        try {
            final Integer retCode = (Integer) task.get();
            if (retCode.intValue() != BaseClient.SUCCESS_EXIT_CODE) {
                throw new ExitNow(retCode.intValue());
            }
        } catch (InterruptedException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        } catch (ExecutionException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        }
    }

    private void ctxMonitor(String ctxEprPath,
                            String identityAuthorization,
                            String clusterName,
                            String reportDirectory,
                            KnownHostsTask[] knownHostTasks,
                            String sshKnownHostsFile,
                            long pollMs,
                            Print print) throws ExitNow, ExecutionProblem {

        final ContextMonitorTask mTask =
                new ContextMonitorTask(ctxEprPath,
                                       identityAuthorization,
                                       clusterName,
                                       reportDirectory,
                                       sshKnownHostsFile,
                                       knownHostTasks,
                                       pollMs,
                                       print);

        final FutureTask task = new FutureTask(mTask);
        this.executor.submit(task);

        try {
            final Integer retCode = (Integer) task.get();
            if (retCode.intValue() != BaseClient.SUCCESS_EXIT_CODE) {
                throw new ExitNow(retCode.intValue());
            }
        } catch (InterruptedException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        } catch (ExecutionException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        }
    }

    // -------------------------------------------------------------------------
    // START ONE WORKSPACE
    // -------------------------------------------------------------------------

    public void startOneWorkspace(String workspaceFactoryURL,
                                  VirtualWorkspace_Type metadata,
                                  String metadata_fileName,
                                  WorkspaceDeployment_Type deploymentRequest,
                                  String deploymentRequest_fileName,
                                  String sshfile,
                                  String historyDir,
                                  long pollMs,
                                  boolean useNotifications,
                                  String identityAuthorization,
                                  Print print)
           
            throws ExecutionProblem, ExitNow {

        boolean disableAllStateChecks = false;
        if (pollMs < 1 && !useNotifications) {
            disableAllStateChecks = true;
        }

        print.infoln("\nLaunching workspace.");

        final File topdir;
        try {
            topdir = CloudClientUtil.getHistoryDir(historyDir);
        } catch (ParameterProblem e) {
            throw new ExecutionProblem(e.getMessage(), e);
        }

        final int nextnum = HistoryUtil.findNextSingleNumber(topdir, print);

        final String suffix = HistoryUtil.format.format(nextnum);
        final String newDirName = HistoryUtil.historyDirPrefix + suffix;

        print.debugln("Next directory: " + newDirName);

        final File newdir = new File(topdir, newDirName);
        final String newdirPath = newdir.getAbsolutePath();
        if (newdir.mkdir()) {
            print.debugln("Created directory: " + newdirPath);
        } else {
            // could be a race condition on the name, or odd perm problem
            // (note we checked parent dir was writeable)
            throw new ExecutionProblem(
                    "Could not create directory '" + newdirPath + "'");
        }

        final File runLog =
                HistoryUtil.newLogFile(newdir, RunTask.LOG_FILE_NAME, print);
        if (runLog != null) {
            try {
                print.getOpts().setInfoErrFile(runLog.getAbsolutePath());
            } catch (Exception e) {
                print.errln("Problem setting InfoErrFile: " + e.getMessage());
                // carry on
            }
        }

        final File debugLog =
               HistoryUtil.newLogFile(newdir, RunTask.DEBUG_LOG_FILE_NAME, print);
        if (debugLog != null) {
            try {
                print.getOpts().setAllOutFile(debugLog.getAbsolutePath());
            } catch (Exception e) {
                print.errln("Problem setting AllOutFile: " + e.getMessage());
                // carry on
            }
        }

        final File eprFile = new File(newdir, HistoryUtil.SINGLE_EPR_FILE_NAME);
        final String eprPath = eprFile.getAbsolutePath();
        print.debugln("EPR will be written to:");
        print.debugln("  - '" + eprPath + "'");
        print.debugln("");

        final FutureTask task =
                  this.getWorkspaceTask(workspaceFactoryURL,
                                        eprPath,
                                        metadata,
                                        metadata_fileName,
                                        deploymentRequest,
                                        deploymentRequest_fileName,
                                        sshfile,
                                        newdir,
                                        newDirName,
                                        pollMs,
                                        identityAuthorization,
                                        disableAllStateChecks,
                                        "Running",
                                        null,
                                        false,
                                        false,
                                        print,
                                        null,
                                        null);

        this.executor.submit(task);

        try {
            final Integer retCode = (Integer) task.get();
            if (retCode.intValue() == BaseClient.SUCCESS_EXIT_CODE) {
                print.infoln("\nRunning: '" + newDirName + "'");
            } else {
                print.errln("\nProblem running '" + newDirName + "'.");
                throw new ExitNow(retCode.intValue());
            }
        } catch (InterruptedException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        } catch (ExecutionException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        }
    }


    // -------------------------------------------------------------------------
    // START WORKSPACE TASK
    // -------------------------------------------------------------------------

    private FutureTask getWorkspaceTask(String workspaceFactoryURL,
                                        String eprPath,
                                        VirtualWorkspace_Type metadata,
                                        String metadata_fileName,
                                        WorkspaceDeployment_Type deploymentRequest,
                                        String deploymentRequest_fileName,
                                        String sshfile,
                                        File newdir,
                                        String newDirName,
                                        long pollMs,
                                        String identityAuthorization,
                                        boolean disableAllStateChecks,
                                        String exitStateStr,
                                        String ensembleEprPath,
                                        boolean newEnsemble,
                                        boolean forceGroupPrint,
                                        Print print,
                                        String mdUserDataPath,
                                        String ipIdDir)

            throws ExecutionProblem, ExitNow {

        if (identityAuthorization == null) {
            print.debugln("Using host-based authorization of remote server");
        } else {
            print.debugln("Using identity-based authorization of remote " +
                                    "server: '" + identityAuthorization + "'");
        }

        String hostport;
        try {
            final URL url = new URL(workspaceFactoryURL);
            hostport = url.getHost();
            hostport += ":";
            hostport += url.getPort();
        } catch (MalformedURLException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        }

        try {
      final String newDirName_nospaces = newDirName.replace(' ', '_');
      final String runNameString = "https://" + hostport + "/" + newDirName_nospaces;
      print.debugln("name for metadata: '" + runNameString + "'");
            final URI runName = new URI(runNameString);
            metadata.setName(runName);
        } catch (URI.MalformedURIException e) {
            throw new ExecutionProblem(e.getMessage(), e);
        }

        final String metadataPath;
        try {
            metadataPath = HistoryUtil.writeMetadata(newdir,
                                                     metadata_fileName,
                                                     metadata);
        } catch (Exception e) {
            throw new ExecutionProblem(e.getMessage(), e);
        }

        print.debugln("Created workspace description:");
        print.debugln("  - '" + metadataPath + "'");

        final String deploymentPath;
        try {
            deploymentPath =
                    HistoryUtil.writeDeployment(newdir,
                                                deploymentRequest_fileName,
                                                deploymentRequest);
        } catch (Exception e) {
            throw new ExecutionProblem(e.getMessage(), e);
        }

        print.debugln("Created deployment request:");
        print.debugln("  - '" + deploymentPath + "'");

        final RunTask runTask = new RunTask(eprPath,
                                            workspaceFactoryURL,
                                            metadataPath,
                                            deploymentPath,
                                            sshfile,
                                            pollMs,
                                            disableAllStateChecks,
                                            newDirName,
                                            identityAuthorization,
                                            exitStateStr,
                                            ensembleEprPath,
                                            newEnsemble,
                                            forceGroupPrint,
                                            mdUserDataPath,
                                            ipIdDir,
                                            print);

        return new FutureTask(runTask);
    }

}
TOP

Related Classes of org.globus.workspace.cloud.client.util.ExecuteUtil$IdIpPair

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.