/** * Licensed to Ravel, Inc. under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. Ravel, Inc. 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.goldenorb.util; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import org.apache.zookeeper.ZooKeeper; import org.goldenorb.conf.OrbConfiguration; import org.goldenorb.zookeeper.OrbZKFailure; import org.goldenorb.zookeeper.ZookeeperUtils; /** * This class provides a command line interface utility class for GoldenOrb. * */ public class CommandLineUtils { private static SortedMap<String,String> helpMap; private static SortedMap<String,SortedMap<String,String>> validArguments; private static String connectString; /** * Main method for the CLI. * * @param args */ public static void main(String[] args) { if (args.length == 0) { System.out.println("ERROR : No command received. Use command 'Help' for a list of commands."); System.exit(-1); } if (args[0].equalsIgnoreCase("Help")) { if(args[args.length -1].startsWith("-connectString=")) { connectString = args[args.length - 1].substring(15); } help(args); } else if (args[0].equalsIgnoreCase("Job")) { if(args[args.length -1].startsWith("-connectString=")) { connectString = args[args.length - 1].substring(15); } if (args.length >= 1) job(args); else { System.out.println("Job command requires arguments."); } } else { // Invalid Command System.out.println("Error : Invalid Command. Command '" + args[0] + "' not recognized."); System.exit(-1); } } /** * Provides a "help" command in the CLI. * * @param args * - String[] */ public static void help(String[] args) { initializeHelpMaps(); Set<String> commandsSet = helpMap.keySet(); if (args.length == 1) { for (String command : commandsSet) { System.out.print(command + "\t" + helpMap.get(command)); if (!command.equalsIgnoreCase("Help")) { System.out.println(" Use 'Help -" + command + "' to view a list of valid arguments"); } } } else { // option provided String command = args[1].replaceFirst("-", ""); if (commandsSet.contains(command)) { System.out.println("Help for command '" + command + "'."); System.out.println(command + "\t" + helpMap.get(command)); System.out.println("List of valid arguments for command '" + command + "' : "); SortedMap<String,String> argMap = validArguments.get(command); Set<String> arguments = argMap.keySet(); for (String arg : arguments) { System.out.println(command + "\t" + argMap.get(arg)); } } else { System.out.println(args[0] + " is not a valid command."); } } } /** * Initializes the helpMaps used for the CLI. */ public static void initializeHelpMaps() { helpMap = new TreeMap<String,String>(); // Job helpMap.put("Job", "Lets you kill jobs and view job status."); // Help helpMap.put("Help", "Displays all of the commands and their general purpose."); validArguments = new TreeMap<String,SortedMap<String,String>>(); // Job validArguments.put("Job", jobHelpValidArguments()); } /** * Defines valid arguments. * * @returns SortedMap<String,String> */ public static SortedMap<String,String> jobHelpValidArguments() { SortedMap<String,String> map = new TreeMap<String,String>(); // kill map.put("-kill", "Terminates the job whose JobID is supplied. ex. Job -kill ClusterName Job1234 ,\n\t\t" + "would kill the job whose JobID is '1234' on cluster 'ClusterName."); // status map.put( "-status", "If supplied a JobID and cluster, it will display the job status of that specific job.\n\t\t" + "If no JobID is provided, but a cluster name is provied, it will list the status of all jobs on that cluster.\n\t\t" + "ex. Job -status ClusterName Job1234 , would display the status of 'Job1234' on cluster 'ClusterName'."); return map; } /** * Provides a "job" command in the CLI. * * @param args * - String[] */ public static void job(String[] args) { ZooKeeper zk = connectZookeeper(); if (args[1].equalsIgnoreCase("-kill")) { jobKill(args, zk); } else if (args[1].equalsIgnoreCase("-status")) { jobStatus(args, zk); } else { System.out .println(args[1] + "is an invalid argument for 'Job'. Use 'Help -Job' for a list of valid arguments."); } } /** * Kills a Job. * * @param args * - String[] * @param zk * - ZooKeeper */ public static void jobKill(String[] args, ZooKeeper zk) { if (args.length < 3) { System.out.println("'Job -kill' requires a cluster name and Job ID!"); } else if (args.length == 3) { System.out.println("'Job -kill' requires a Job ID!"); } else if (ZookeeperUtils.nodeExists(zk, "/GoldenOrb/" + args[2])) { // cluster exists if (ZookeeperUtils.nodeExists(zk, "/GoldenOrb/" + args[2] + "/JobQueue/" + args[3])) { // job is in // queue try { ZookeeperUtils.deleteNodeIfEmpty(zk, "/GoldenOrb/" + args[2] + "/JobQueue/" + args[3]); System.out.println("Killed " + args[2] + " on cluster " + args[3]); } catch (OrbZKFailure e) { System.err.println("Error occured while trying delete " + args[3] + " from the JobQueue."); e.printStackTrace(); System.exit(-1); } } else if (ZookeeperUtils.nodeExists(zk, "/GoldenOrb/" + args[2] + "/JobsInProgress/" + args[3])) { // job // is // running try { ZookeeperUtils.tryToCreateNode(zk, "/GoldenOrb/" + args[2] + "/JobsInProgress/" + args[3] + "/messages/death"); System.out.println("Killed " + args[2] + " on cluster " + args[3]); } catch (OrbZKFailure e) { System.err.println("Error occured while trying kill " + args[3] + " on cluster " + args[2]); e.printStackTrace(); System.exit(-1); } } else { // Job does not exist System.out.println("Job " + args[3] + " on cluster " + args[2] + " does not exist."); } } else { System.out.println("Cluster " + args[2] + " does not exist."); } } /** * Checks the status of a Job. * * @param args * - String[] * @param zk * - ZooKeeper */ public static void jobStatus(String[] args, ZooKeeper zk) { if (args.length < 3) { System.out.println("No cluster name provided."); } else if (!ZookeeperUtils.nodeExists(zk, "/GoldenOrb/" + args[2])) { System.out.println("Cluster " + args[2] + " does not exist."); } else if (args.length == 3) { // display status of all jobs on cluster try { List<String> jobsInQueue = zk.getChildren("/GoldenOrb/" + args[2] + "/JobQueue", false); List<String> jobsInProgress = zk.getChildren("/GoldenOrb/" + args[2] + "/JobsInProgress", false); System.out.println(jobsInQueue.size() + " jobs in JobQueue :"); Collections.sort(jobsInQueue); for (String job : jobsInQueue) { System.out.println("\t" + job); } System.out.println("\n" + jobsInProgress.size() + " jobs in progress :"); for (String job : jobsInProgress) { System.out.println("\t" + job); } } catch (Exception e) { System.err.println("Error occured while attempting to get status of jobs on cluster " + args[2]); e.printStackTrace(); System.exit(-1); } } else { // JobID is provided if (ZookeeperUtils.nodeExists(zk, "/GoldenOrb/" + args[2] + "/JobQueue/" + args[3])) { try { List<String> children = zk.getChildren("/GoldenOrb/" + args[2] + "/JobQueue", false); Collections.sort(children); int place = children.indexOf(args[3]) + 1; String placeInQueue; if (place == 1) { placeInQueue = "1st"; } else if (place == 2) { placeInQueue = "2nd"; } else if (place == 3) { placeInQueue = "3rd"; } else { placeInQueue = place + "th"; } System.out.println(args[3] + " is " + placeInQueue + " in the JobQueue."); } catch (Exception e) { System.err.println("Error occurred while looking up job status : "); e.printStackTrace(); } } else if (ZookeeperUtils.nodeExists(zk, "/GoldenOrb/" + args[2] + "/JobsInProgress/" + args[3])) { System.out.println(args[3] + " is in progress."); } else { System.out.println("Job " + args[3] + " does not exist on cluster " + args[2] + "."); } } } /** * Connects to ZooKeeper. * * @returns ZooKeeper */ public static ZooKeeper connectZookeeper() { OrbConfiguration orbConf = new OrbConfiguration(true); ZooKeeper zk = null; if (connectString == null) { connectString = orbConf.getOrbZooKeeperQuorum(); } try { zk = ZookeeperUtils.connect(connectString); } catch (IOException e) { System.err.println("Could not connect : "); e.printStackTrace(); System.exit(-1); } catch (InterruptedException e) { System.err.println("Could not connect : "); e.printStackTrace(); System.exit(-1); } return zk; } public static void setConnectString(String _connectString) { connectString = _connectString; } }