Package org.apache.uima.ducc.common.main

Source Code of org.apache.uima.ducc.common.main.DuccAdmin

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.apache.uima.ducc.common.main;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;

import org.apache.activemq.camel.component.ActiveMQComponent;
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.dataformat.xstream.XStreamDataFormat;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.impl.DefaultClassResolver;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.uima.ducc.common.admin.event.DuccAdminEvent;
import org.apache.uima.ducc.common.admin.event.DuccAdminEventKill;
import org.apache.uima.ducc.common.admin.event.DuccAdminEventStopMetrics;
import org.apache.uima.ducc.common.authentication.BrokerCredentials;
import org.apache.uima.ducc.common.authentication.BrokerCredentials.Credentials;
import org.apache.uima.ducc.common.component.AbstractDuccComponent;
import org.apache.uima.ducc.common.launcher.ssh.DuccRemoteLauncher;
import org.apache.uima.ducc.common.launcher.ssh.DuccRemoteLauncher.ProcessCompletionCallback;
import org.apache.uima.ducc.common.launcher.ssh.DuccRemoteLauncher.ProcessCompletionResult;
import org.apache.uima.ducc.common.utils.Utils;

import com.thoughtworks.xstream.XStream;

/**
* This class implements support for sending Administrative commands to Ducc
* processes. Usage:
*
* DuccAdmin -killAll - stops all Ducc components
* DuccAdmin -quiesceAgents <node1,node2..>- quiesces named nodes
*/
public class DuccAdmin extends AbstractDuccComponent implements
    ProcessCompletionCallback {
  public static final String FileSeparator = System
      .getProperty("file.separator");

  public static enum DuccCommands {
    killAll, startAgents, quiesceAgents
  };

  private String brokerUrl;
  private ProducerTemplate pt;
  private String targetEndpoint;
  private CommandLine commandLine;

  public DuccAdmin(CamelContext context) {
    super("DuccServiceReaper", context);
    try {
      // Load ducc properties file and enrich System properties. It
      // supports
      // overrides for entries in ducc properties file. Any key in the
      // ducc
      // property file can be overriden with -D<key>=<value>
      loadProperties(DuccService.DUCC_PROPERTY_FILE);
      // fetch the broker URL from ducc.properties
      this.brokerUrl = System.getProperty("ducc.broker.url");
      try {
        String brokerCredentialsFile =
            System.getProperty("ducc.broker.credentials.file");
        // fetch the admin endpoint from the ducc.properties where
        // the admin events will be sent by the DuccServiceReaper
        targetEndpoint = System.getProperty("ducc.admin.endpoint");
        System.out.println("+++ Activating JMS Component for Endpoint:"
            + targetEndpoint + " Broker:" + brokerUrl);
       
        ActiveMQComponent duccAMQComponent = new ActiveMQComponent(context);
          duccAMQComponent.setBrokerURL(brokerUrl);
       
//        context.addComponent("activemq",
//            ActiveMQComponent.activeMQComponent(brokerUrl));
         
          if ( brokerCredentialsFile != null && brokerCredentialsFile.length() > 0 ) {
            String path ="";
            try {
                Utils.findDuccHome()// add DUCC_HOME to System.properties
                path = Utils.resolvePlaceholderIfExists(brokerCredentialsFile, System.getProperties());
                Credentials credentials = BrokerCredentials.get(path);
              if ( credentials.getUsername() != null && credentials.getPassword() != null ) {
              duccAMQComponent.setUserName(credentials.getUsername());
              duccAMQComponent.setPassword(credentials.getPassword());
               }  
            } catch(FileNotFoundException e) {
            System.out.println("DuccAdmin Failed - File Not Found:"+path+" Broker Credentials File:"+brokerCredentialsFile);
            System.exit(-1);
            }
          }
        context.addComponent("activemq",duccAMQComponent);
        this.pt = context.createProducerTemplate();
      } catch( Throwable exx) {
        System.out.println("DuccAdmin Failed:"+exx);
        System.exit(-1);
      }

    } catch (Exception e) {
      System.out
          .println("DuccAdmin was not able to load properties from "
              + (String) System
                  .getProperty(DuccService.DUCC_PROPERTY_FILE));
      System.exit(-1);
    }
  }

  /**
   * Sends the DuccAdminEvent (serialized as String) to the admin endpoint
   *
   * @param serializedEvent
   *            - serialized DuccAdminEvent
   * @throws Exception
   */
  public void dispatch(String serializedEvent) throws Exception {
    // this is a one-way send. Reply is not expected
    pt.sendBody(targetEndpoint, serializedEvent);
  }

  /**
   * Serializes DuccAdminEvent using XStream
   *
   * @param event
   *            - instance of DuccAdminEvent
   * @return - serialized DuccAdminEvent
   */
  public String serializeAdminEvent(DuccAdminEvent event) {
    XStreamDataFormat xStreamDataFormat = new XStreamDataFormat();
    XStream xStream = xStreamDataFormat
        .getXStream(new DefaultClassResolver());
    return xStream.toXML(event);
  }

  public Options getPosixOptions() {
    final Options posixOptions = new Options();
    posixOptions.addOption(DuccCommands.killAll.name(), false,
        "Kill All Ducc Processes");

    @SuppressWarnings("static-access")
    Option startAgentsOption = OptionBuilder
        .hasArgs(2)
        .withDescription(
            "starting agents defined in arg1 using command defined in arg2")
        .create("startAgents");
    posixOptions.addOption(startAgentsOption);

    @SuppressWarnings("static-access")
    Option quiesceAgentsOption = OptionBuilder
        .hasArgs(1)
        .withDescription(
            "quiescing agents defined in arg1")
        .create("quiesceAgents");
    posixOptions.addOption(quiesceAgentsOption);
   
    return posixOptions;
  }

  public void parseWithPosixParser(final String[] args) {
    final CommandLineParser cmdLinePosixParser = new PosixParser();
    final Options posixOptions = getPosixOptions();
    try {
      commandLine = cmdLinePosixParser.parse(posixOptions, args);
    } catch (ParseException parseException) {
      System.err
          .println("Exception while parsing using commandling with PosixParser:\n"
              + parseException.getMessage());
    }
  }

  /**
   * This method facilitates complete DUCC system shutdown by sending
   * DuccEventKill event to all Ducc components. Each Ducc component has
   * special purpose JMS channel where it listens for Ducc Admin events. When
   * an event is received the component shuts itself down.
   *
   * @throws Exception
   */
  private void killAll() throws Exception {
    // send kill event to all Ducc components via Ducc Admin Channel. This
    // call is
    // non-blocking
    dispatch(serializeAdminEvent(new DuccAdminEventKill()));
    System.out.println("DuccAdmin sent Kill to all Ducc processes ...");
  }

  private void quiesceAgents(String nodes) throws Exception {
    dispatch(serializeAdminEvent(new DuccAdminEventStopMetrics(nodes)));
    System.out.println("DuccAdmin sent Quiesce request to Ducc Agents ...");
  }
  /**
   * Return contents of the provided command file.
   *
   * @param commandFile - file containing command to run
   * @return - contents of the command file
   *
   * @throws FileNotFoundException
   * @throws IOException
   */
  private String readCommand(String commandFile)
      throws FileNotFoundException, IOException {
    File file = new File(commandFile);
    InputStream in = new FileInputStream(file);
    // Get the size of the file
    long length = file.length();
    // Create the byte array to hold a command
    byte[] bytes = new byte[(int) length];

    // Read in the bytes
    int offset = 0;
    int numRead = 0;
    while (offset < bytes.length
        && (numRead = in.read(bytes, offset, bytes.length - offset)) >= 0) {
      offset += numRead;
    }
    in.close();
    return new String(bytes);
  }
  /**
   * Launches agents on nodes identified in nodesFile. The commandFile
   * contains a command that will be used to execute the agent.
   */
  private void startAgents(String nodesFile, String commandFile) {
    InputStream in = null;
    try {
      //  get the command line to start agent process
      String command = readCommand(commandFile);
     
      command = Utils.resolvePlaceholderIfExists(command, System.getProperties());
      System.out.println("Command To Run:"+command);
      in = new FileInputStream(nodesFile);
      BufferedReader br = new BufferedReader(new InputStreamReader(
          new DataInputStream(in)));
      String strLine;

      String sshUser = System.getenv("USER");
      String userHome = System.getProperty("user.home");
      String sshIdentityLocation = userHome + FileSeparator + ".ssh"
          + FileSeparator + "id_dsa";
      DuccRemoteLauncher remoteLauncher = new DuccRemoteLauncher(
          sshUser, sshIdentityLocation, System.out);
      //remoteLauncher.initialize();
      List<Future<ProcessCompletionResult>> results = new ArrayList<Future<ProcessCompletionResult>>();

      while ((strLine = br.readLine()) != null) {
        results.add(remoteLauncher.execute(strLine.trim(), command,
            this));
      }
      // Close the input stream
      in.close();
      for (Future<ProcessCompletionResult> result : results) {
        result.get();
      }
    } catch (Exception e) {
      throw new RuntimeException(e);
    } finally {
      if (in != null) {
        try {
          in.close();
        } catch (IOException ex) {
          // ignore
        }
      }
    }
  }

  /**
   * Interprets and executes Admin command
   *
   * @throws Exception
   */
  public void process() throws Exception {
    if (commandLine.hasOption(DuccCommands.killAll.name())) {
      killAll();
    } else if (commandLine.hasOption(DuccCommands.startAgents.name())) {
      System.out.println("---------- Starting Agents");
      String[] args = commandLine
          .getOptionValues(DuccCommands.startAgents.name());
      startAgents(args[0], args[1]);
    } else if (commandLine.hasOption(DuccCommands.quiesceAgents.name())) {
      System.out.println("---------- Quiescing Agents");
      String[] args = commandLine
          .getOptionValues(DuccCommands.quiesceAgents.name());
      quiesceAgents(args[0]);
    }

  }

  public static void main(String[] args) {
    try {
      DuccAdmin admin = new DuccAdmin(new DefaultCamelContext());
      admin.parseWithPosixParser(args);
      admin.process();
    } catch (Throwable e) {
      e.printStackTrace();
    } finally {
      System.exit(-1);
    }
  }

 
  public void completed(ProcessCompletionResult result) {
    StringBuffer sb = new StringBuffer();
    if (result.exitCode != 0) {
      sb.append("DuccRemoteLauncher Failure. Host:").append(result.host)
          .append(" Error:").append(result.stderr)
          .append("\nCommand:").append(result.command);
    } else {
      sb.append("DuccRemoteLauncher Launched Command on Host:").append(
          result.host);
    }
    System.out.println(sb.toString());
  }

}
TOP

Related Classes of org.apache.uima.ducc.common.main.DuccAdmin

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.