org.globus.workspace.client.modes.EnsembleMonitor.java Source code

Java tutorial

Introduction

Here is the source code for org.globus.workspace.client.modes.EnsembleMonitor.java

Source

/*
 * 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.client.modes;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.axis.message.addressing.EndpointReferenceType;
import org.globus.workspace.client_core.actions.Ensemble_Report;
import org.globus.workspace.client_core.StubConfigurator;
import org.globus.workspace.client_core.ParameterProblem;
import org.globus.workspace.client_core.ExecutionProblem;
import org.globus.workspace.client_core.ExitNow;
import org.globus.workspace.client_core.repr.Workspace;
import org.globus.workspace.client_core.repr.State;
import org.globus.workspace.client_core.repr.Networking;
import org.globus.workspace.client_core.repr.Nic;
import org.globus.workspace.client_core.repr.Schedule;
import org.globus.workspace.client_core.utils.EPRUtils;
import org.globus.workspace.client_core.utils.StringUtils;
import org.globus.workspace.client_core.utils.FileUtils;
import org.globus.workspace.client_core.utils.ScheduleUtils;
import org.globus.workspace.client_core.print.PrCodes;
import org.globus.workspace.common.print.Print;
import org.nimbustools.messaging.gt4_0.common.CommonUtil;
import org.globus.workspace.common.client.CommonPrint;
import org.globus.workspace.client.AllArguments;
import org.globus.workspace.client.modes.aux.CommonLogs;
import org.globus.workspace.client_common.CommonStrings;
import org.nimbustools.messaging.gt4_0.generated.types.WorkspaceUnknownFault;
import org.nimbustools.messaging.gt4_0.generated.types.CurrentState_Enumeration;
import org.nimbustools.messaging.gt4_0.generated.ensemble.WorkspaceEnsembleFault;
import org.globus.wsrf.encoding.SerializationException;
import org.oasis.wsrf.faults.BaseFaultType;

import java.io.File;
import java.io.IOException;
import java.text.NumberFormat;
import java.text.DateFormat;
import java.util.Calendar;

public class EnsembleMonitor extends Mode {

    // -------------------------------------------------------------------------
    // STATIC VARIABLES
    // -------------------------------------------------------------------------

    private static final Log logger = LogFactory.getLog(EnsembleMonitor.class.getName());

    private static final DateFormat localFormat = DateFormat.getDateTimeInstance();
    public static String newline = System.getProperty("line.separator");

    public static final int DEFAULT_POOL_SIZE = 4;

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

    private String nameToPrint;
    private Ensemble_Report ensembleReport;
    private EndpointReferenceType epr;
    private boolean dryrun;
    private long pollDelayMs;
    private CurrentState_Enumeration targetState;
    private State compareState;

    // -------------------------------------------------------------------------
    // CONSTRUCTOR
    // -------------------------------------------------------------------------

    public EnsembleMonitor(Print print, AllArguments arguments, StubConfigurator stubConfigurator) {
        super(print, arguments, stubConfigurator);
    }

    // -------------------------------------------------------------------------
    // extends Mode
    // -------------------------------------------------------------------------

    public String name() {
        return "Monitor-ensemble";
    }

    public void validateOptionsImpl() throws ParameterProblem {

        this.handlePollDelay();
        this.handleExitState();
        this.validateEndpoint();
        this.setName();
        this.validateReportdir();
        this.dryrun = this.args.dryrun;
        CommonLogs.logBoolean(this.dryrun, "dryrun mode", this.pr, logger);
    }

    public void runImpl() throws ParameterProblem, ExecutionProblem, ExitNow {
        this._runImpl();
    }

    // -------------------------------------------------------------------------
    // VALIDATION
    // -------------------------------------------------------------------------

    private void handlePollDelay() throws ParameterProblem {

        if (this.args.pollDelayString == null) {
            throw new ParameterProblem("poll delay is required");
        }

        try {
            this.pollDelayMs = Long.parseLong(this.args.pollDelayString);
        } catch (NumberFormatException e) {
            throw new ParameterProblem(
                    "Given poll delay is not valid: '" + this.args.pollDelayString + "': " + e.getMessage(), e);
        }

        if (this.pollDelayMs < 1) {
            throw new ParameterProblem("Given poll delay is less than 1ms: " + this.pollDelayMs + "ms");
        }
    }

    private void handleExitState() throws ParameterProblem {

        if (this.args.exitStateString == null) {
            this.targetState = CurrentState_Enumeration.Running;
            this.compareState = new State("Running");
            return; // *** EARLY RETURN ***
        }

        if (!State.testValidState(this.args.exitStateString)) {
            throw new ParameterProblem(
                    "Provided exit string is not a " + "valid state: '" + this.args.exitStateString + "'");
        }

        this.compareState = new State(this.args.exitStateString);

        if (this.pr.enabled()) {
            final String dbg = "Exit state: " + this.compareState.toString();
            if (this.pr.useThis()) {
                this.pr.dbg(dbg);
            } else if (this.pr.useLogging()) {
                logger.debug(dbg);
            }
        }

        if (!this.compareState.isOKState()) {
            throw new ParameterProblem(
                    "Provided exit string is not a " + "valid target state: '" + this.args.exitStateString + "'");
        }

        this.targetState = CurrentState_Enumeration.fromString(this.compareState.toString());
    }

    private void validateEndpoint() throws ParameterProblem {

        this.epr = this.stubConf.getEPR();

        if (this.epr == null) {
            throw new ParameterProblem(name() + " requires EPR");
        }

        final String eprStr;
        try {
            eprStr = EPRUtils.eprToString(this.epr);
        } catch (Exception e) {
            final String err = CommonUtil.genericExceptionMessageWrapper(e);
            throw new ParameterProblem(err, e);
        }

        if (this.pr.enabled()) {
            // xml print
            final String dbg = "\nGiven EPR:\n----------\n" + eprStr + "----------\n";

            if (this.pr.useThis()) {
                this.pr.dbg(dbg);
            } else if (this.pr.useLogging()) {
                logger.debug(dbg);
            }
        }

        this.ensembleReport = new Ensemble_Report(this.epr, this.stubConf, this.pr);
    }

    private void validateReportdir() throws ParameterProblem {

        if (this.args.reportDir == null) {
            return; // *** EARLY RETURN ***
        }

        final File f = new File(this.args.reportDir);
        if (!f.exists()) {
            throw new ParameterProblem(
                    "Given path for reports directory ('" + this.args.reportDir + "') does not exist.");
        }

        if (!f.isDirectory()) {
            throw new ParameterProblem(
                    "Given path for reports directory ('" + this.args.reportDir + "') is not a directory.");
        }

        if (!f.canWrite()) {
            throw new ParameterProblem(
                    "Given path for reports directory ('" + this.args.reportDir + "') is not writable.");
        }
    }

    private void setName() {

        if (this.args.shortName != null) {
            this.nameToPrint = this.args.shortName;
        } else {
            this.nameToPrint = "ensemble \"" + EPRUtils.getEnsembleIdFromEPR(this.epr) + "\"";

            final String service = StringUtils.commonAtServiceAddressSuffix(this.epr);

            if (service != null) {
                this.nameToPrint += service;
            }
        }

        if (this.pr.enabled()) {
            final String dbg = "Name to print: '" + this.nameToPrint + "'";
            if (this.pr.useThis()) {
                this.pr.dbg(dbg);
            } else if (this.pr.useLogging()) {
                logger.debug(dbg);
            }
        }
    }

    // -------------------------------------------------------------------------
    // RUN
    // -------------------------------------------------------------------------

    private void _runImpl() throws ParameterProblem, ExecutionProblem, ExitNow {

        if (this.dryrun) {

            if (this.pr.enabled()) {
                final String msg = "Dryrun, done.";
                if (this.pr.useThis()) {
                    this.pr.infoln(PrCodes.ENSEMBLEREPORT__DRYRUN, msg);
                } else if (this.pr.useLogging()) {
                    logger.info(msg);
                }
            }

            return; // *** EARLY RETURN ***
        }

        Result result = null;
        try {

            while (true) {
                try {
                    result = this.runQuery();
                    if (result.allAtState || result.oneErrorExists) {
                        break;
                    }
                    Thread.sleep(this.pollDelayMs);
                } catch (InterruptedException e) {
                    // ignore
                }
            }

        } catch (BaseFaultType e) {
            final String err = CommonStrings.faultStringOrCommonCause(e, "ensemble");
            throw new ExecutionProblem(err, e);
        }

        if (result.oneErrorExists) {

            if (this.pr.enabled()) {
                final String msg = "Encountered a problem launching " + this.nameToPrint;
                if (this.pr.useThis()) {
                    this.pr.infoln(PrCodes.ENSMONITOR__ONE_ERROR, msg);
                } else if (this.pr.useLogging()) {
                    logger.info(msg);
                }
            }

        } else if (result.allAtState) {

            if (this.pr.enabled()) {
                final String msg = this.nameToPrint + ": all members are " + this.targetState.toString();
                if (this.pr.useThis()) {
                    this.pr.infoln(PrCodes.ENSMONITOR__ALL_RUNNING, "  - " + msg);
                } else if (this.pr.useLogging()) {
                    logger.info(msg);
                }
            }

        } else {
            throw new ExecutionProblem("Incorrect response from report query?");
        }

        if (result.workspaces == null) {
            throw new ExecutionProblem("Incorrect response from report query?");
        }

        // both oneErrorExists and allRunning trigger report(s) if path is configured
        if (this.args.reportDir != null) {
            this.writeReports(result);
        }

        if (!result.allAtState) {
            throw new ExitNow(1);
        }
    }

    private Result runQuery()
            throws ExecutionProblem, WorkspaceUnknownFault, WorkspaceEnsembleFault, ParameterProblem {

        if (this.ensembleReport == null) {
            throw new IllegalStateException("there is no port type to call ensemble-report");
        }

        this.ensembleReport.setResponseOnlyIfError(true);
        this.ensembleReport.setReturnOnlyIfAll(this.targetState);
        final Workspace[] workspaces = this.ensembleReport.report();
        if (workspaces.length == 0) {
            return new Result(false, false, null);
        } else {
            return this.analyzeResult(workspaces);
        }
    }

    private Result analyzeResult(Workspace[] workspaces) {

        boolean allAtState = true;
        boolean oneErrorExists = false;

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

            final Workspace workspace = workspaces[i];
            final State state = workspace.getCurrentState();

            if (state == null) {

                allAtState = false;

            } else {

                if (state.isCancelled() || state.isCorrupted()) {
                    oneErrorExists = true;
                    allAtState = false;
                    break; // definitive
                }

                if (!this.compareState.equals(state)) {
                    allAtState = false;
                }
            }
        }

        return new Result(oneErrorExists, allAtState, workspaces);
    }

    private class Result {
        final boolean oneErrorExists;
        final boolean allAtState;
        final Workspace[] workspaces;

        private Result(boolean oneErrorExists, boolean allAtState, Workspace[] workspaces) {
            this.oneErrorExists = oneErrorExists;
            this.allAtState = allAtState;
            this.workspaces = workspaces;
        }
    }

    // -------------------------------------------------------------------------
    // REPORT WRITING
    // -------------------------------------------------------------------------

    protected void writeReports(Result result) {

        if (result == null) {
            throw new IllegalArgumentException("result may not be null");
        }
        if (result.workspaces == null) {
            throw new IllegalArgumentException("workspaces may not be null");
        }

        final Workspace[] workspaces = result.workspaces;

        final short numDigits;
        if (workspaces.length > 1000) {
            numDigits = 4;
        } else if (workspaces.length > 100) {
            numDigits = 3;
        } else if (workspaces.length > 10) {
            numDigits = 2;
        } else {
            numDigits = 1;
        }

        final NumberFormat format = NumberFormat.getInstance();
        format.setMinimumIntegerDigits(numDigits);
        this._writeReports(workspaces, this.args.reportDir, format);

        if (this.pr.enabled()) {
            final String msg = "wrote reports to '" + this.args.reportDir + "'";
            if (this.pr.useThis()) {
                this.pr.infoln(PrCodes.ENSMONITOR__REPORT_DIR, "  - " + msg);
            } else if (this.pr.useLogging()) {
                logger.info(msg);
            }
        }
    }

    private void _writeReports(Workspace[] workspaces, String reportDir, NumberFormat format) {

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

            final String suffix = this.getSuffix(workspaces[i]);
            final String prefix = this.getStateString(workspaces[i]) + "-vm-";
            final String path = prefix + format.format(i + 1) + suffix;

            try {
                this.writeOneReport(workspaces[i], reportDir, path);
            } catch (Exception e) {
                // print error and continue
                if (this.pr.enabled()) {
                    final String msg = CommonUtil.genericExceptionMessageWrapper(e);
                    if (this.pr.useThis()) {
                        this.pr.err(msg);
                    } else if (this.pr.useLogging()) {
                        if (logger.isDebugEnabled()) {
                            logger.error(msg, e);
                        } else {
                            logger.error(msg);
                        }
                    }
                }
            }
        }

    }

    protected String getStateString(Workspace w) {
        final State state = w.getCurrentState();
        if (state == null) {
            return "UNKNOWN";
        }
        return state.getState().toUpperCase();
    }

    protected String getSuffix(Workspace w) {
        final EndpointReferenceType EPR = w.getEpr();
        final String tail;
        if (EPR != null) {
            tail = "_eprkey-" + EPRUtils.getIdFromEPR(EPR) + ".txt";
        } else {
            tail = ".txt";
        }
        return tail;
    }

    protected void writeOneReport(Workspace w, String dir, String file) throws SerializationException, IOException {

        final File f = new File(dir, file);
        FileUtils.writeStringToFile(this.getOneReportText(w), f.getAbsolutePath());

        if (this.pr.enabled()) {
            final String msg = "    Wrote '" + file + "'";
            if (this.pr.useThis()) {
                this.pr.infoln(PrCodes.ENSMONITOR__SINGLE_REPORT_NAMES, msg);
            } else if (this.pr.useLogging()) {
                logger.info(msg);
            }
        }
    }

    protected String getOneReportText(Workspace w) {

        final StringBuffer buf = new StringBuffer(16384);

        final String now = localFormat.format(Calendar.getInstance().getTime());

        buf.append("## File autogenerated at ").append(now);
        add2Newlines(buf);

        buf.append(CommonPrint.textDebugSection("STATUS"));
        add2Newlines(buf);
        buf.append(this.getOneStatus(w.getCurrentState()));
        add2Newlines(buf);

        buf.append(CommonPrint.textDebugSection("NETWORK"));
        add2Newlines(buf);
        buf.append(this.getOneNetwork(w.getCurrentNetworking()));
        add2Newlines(buf);

        buf.append(CommonPrint.textDebugSection("SCHEDULE"));
        add2Newlines(buf);
        buf.append(this.getOneSchedule(w.getCurrentSchedule()));
        add2Newlines(buf);

        buf.append(CommonPrint.textDebugSection("EPR/IDENTITY"));
        add2Newlines(buf);
        buf.append(this.getOneEPR(w.getEpr()));
        add2Newlines(buf);

        return buf.toString();
    }

    private static void addNewline(StringBuffer buf) {
        buf.append(newline);
    }

    private static void add2Newlines(StringBuffer buf) {
        buf.append(newline).append(newline);
    }

    // -------------------------------------------------------------------------

    protected String getOneStatus(State state) {
        if (state == null) {
            return "State: no information";
        }
        final StringBuffer buf = new StringBuffer(2048);
        buf.append("State: ").append(state.getState());
        addNewline(buf);
        final Exception e = state.getProblem();
        if (e != null) {
            buf.append("Problem: ").append(CommonUtil.genericExceptionMessageWrapper(e));
        }
        return buf.toString();
    }

    protected String getOneSchedule(Schedule sched) {
        if (sched == null) {
            return "Schedule: no information";
        }
        final StringBuffer buf = new StringBuffer(2048);

        buf.append(ScheduleUtils.getDurationMessage(sched));
        addNewline(buf);
        buf.append(ScheduleUtils.getStartTimeMessage(sched));
        addNewline(buf);
        buf.append(ScheduleUtils.getShutdownMessage(sched));
        addNewline(buf);
        buf.append(ScheduleUtils.getTerminationMessage(sched));
        addNewline(buf);
        return buf.toString();
    }

    protected String getOneNetwork(Networking networking) {
        if (networking == null) {
            return "Networking: no information";
        }
        final StringBuffer buf = new StringBuffer(2048);
        final Nic[] nics = networking.nics();
        for (int i = 0; i < nics.length; i++) {
            buf.append(this.getOneNIC(nics[i]));
            addNewline(buf);
        }
        return buf.toString();
    }

    protected String getOneNIC(Nic nic) {
        if (nic == null) {
            return "NIC: no information";
        }
        final String name = "NIC: " + nic.getName();
        final String host = "  - Hostname: " + nic.getHostname();
        final String ip = "  - IP: " + nic.getIpAddress();
        final String gateway = "  - Gateway: " + nic.getGateway();
        final String assoc = "  - Association: " + nic.getAssociation();

        final StringBuffer buf = new StringBuffer(name);
        buf.append(newline).append(host).append(newline).append(ip).append(newline).append(gateway).append(newline)
                .append(assoc);
        return buf.toString();
    }

    protected String getOneEPR(EndpointReferenceType wepr) {
        if (wepr == null) {
            return "EPR: none";
        }
        final StringBuffer buf = new StringBuffer(2048);
        buf.append("Workspace ID: ").append(EPRUtils.getIdFromEPR(wepr));
        addNewline(buf);
        try {
            buf.append(EPRUtils.eprToString(wepr));
        } catch (Exception e) {
            buf.append("Problem deserializing EPR: ").append(CommonUtil.genericExceptionMessageWrapper(e));
        }
        return buf.toString();
    }
}