cloud.elasticity.elastman.App.java Source code

Java tutorial

Introduction

Here is the source code for cloud.elasticity.elastman.App.java

Source

/*
 * This file is part of the ElastMan Elasticity Manager
 * 
 * Copyright (C) 2013 Ahmad Al-Shishtawy
 *
 * 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 cloud.elasticity.elastman;

import java.io.BufferedReader;
import java.io.Console;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.PublicKey;
import java.util.Scanner;

import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.connection.channel.direct.Session;
import net.schmizz.sshj.connection.channel.direct.Session.Command;
import net.schmizz.sshj.transport.TransportException;
import net.schmizz.sshj.transport.verification.HostKeyVerifier;
import net.schmizz.sshj.userauth.UserAuthException;
import net.schmizz.sshj.userauth.keyprovider.KeyProvider;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.jclouds.openstack.nova.v2_0.domain.Flavor;
import org.jclouds.openstack.nova.v2_0.domain.Image;
import org.jclouds.openstack.nova.v2_0.domain.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//import org.jclouds.compute.ComputeServiceContext;
//import org.jclouds.PropertiesBuilder;

/**
 * This is the main ElastMan program. It is used to initialize the Voldemort
 * cluster, run system identification, test the controller under various workloads,
 * and run the controller in production.
 * 
 * @author Ahmad Al-Shishtawy <ahmadas@kth.se>
 *
 */
public class App {
    static Logger log = LoggerFactory.getLogger(App.class);

    private Cluster cluster;
    private Nova nova;

    /**
     * The {@link SyncServer} is used to make sure
     * that all Voldemort servers have the same cluster.xml file.
     * <p>
     * The SyncServer is used when creating new Voldemort VMs.
     * It is also optionally used to keep a log of what is happening
     * in the cluster.
     * 
     * @see SyncServer
     */
    private SyncServer sync;

    /**
     * Parsed command line arguments used to configure ElastMan.
     */
    private static CommandLine cmd = null;

    /**
     * The constructor.
     */
    public App() {

    }

    private static Scanner scanner = new Scanner(System.in);

    /**
     * The entry point to the ElastMan main program.
     * 
     * @param args   The first argument is the mode which can be inter, ident, or control
     * corresponding to interactive mode, system identification mode, or control mode.
     * The second argument is the configuration file
     * The third argument is password password  
     */
    public static void main(String[] args) {
        // 1) parse the command line
        // For more information http://commons.apache.org/cli/
        Options options = new Options();
        options.addOption("i", "ident", false, "Enter system identification mode.");
        options.addOption("c", "control", false, "Enter controller mode.");
        options.addOption("o", "options", true, "Configuration file. Default elastman.conf");
        options.addOption("u", "username", true, "Username in the form Tenant:UserName");
        options.addOption("p", "password", true, "User password");
        options.addOption("k", "keyname", true, "Name of SSH key to use");
        options.addOption("z", "zone", true, "The OpenStack availability zone such as the default RegionOne");
        options.addOption("e", "endpoint", true,
                "The URL to access OpenStack API such as http://192.168.1.1:5000/v2.0/");
        options.addOption("s", "syncserver", true, "The URL access the WebSyncServer");
        options.addOption("h", "help", false, "Print this help");

        CommandLineParser parser = new GnuParser();
        try {
            cmd = parser.parse(options, args);
        } catch (ParseException e2) {
            System.out.println(e2.getMessage());
            HelpFormatter formatter = new HelpFormatter();
            formatter.printHelp("ElastMan", options, true);
            System.exit(1);
        }

        // if h then show help and exit
        if (cmd.hasOption("h")) {
            HelpFormatter formatter = new HelpFormatter();
            formatter.printHelp("ElastMan", options, true);
            System.exit(0);
        }

        // 2) Try to load the properties file.
        // Command line arguments override settings in the properties file
        // If no properties file exists. defaults will be used

        String filename = "control.prop"; // the default file name
        if (cmd.hasOption("o")) {
            filename = cmd.getOptionValue("o");
        }
        Props.load(filename, cmd);
        //      Props.save(filename);
        //      System.exit(-1);

        // 3) If no password in command line nor in config file then ask the user
        if (Props.password == null) {
            Console cons;
            char[] passwd;
            if ((cons = System.console()) != null &&
            // more secure and without echo!
                    (passwd = cons.readPassword("[%s]", "Password:")) != null) {
                Props.password = new String(passwd);
            } else {
                // if you don't have a console! E.g., Running in eclipse
                System.out.print("Password: ");
                Props.password = scanner.nextLine();
            }
        }

        // 4) Start the UI
        App app = new App();
        app.textUI(args);

    }

    private void textUI(String[] args) {

        System.out.println("Welcome to ElastMan (v0.0.9)");

        System.out.print("Starting Nova Client...");
        nova = new Nova(Props.username, Props.password, Props.keyname, Props.zone, Props.endpoint);
        sync = new WebSyncServer(Props.webSyncServer);
        cluster = new Cluster(nova, sync);
        cluster.setVoldPrefix(Props.voldPrefix);
        cluster.setVoldImage(Props.voldImage);
        cluster.setVoldFlavor(Props.voldFlavor);
        cluster.setReplicationFactor(Props.voldReplicationFactor);
        cluster.setYcsbPrefix(Props.ycsbPrefix);
        cluster.setYcsbImage(Props.ycsbImage);
        cluster.setYcsbFlavor(Props.ycsbFlavor);

        nova.open();
        System.out.println("OK");

        if (cmd.hasOption("i")) { // enter identification mode
            cluster.updateVMs();
            new ElastManServer(false, cluster).run(); // start in this thread instead of .start();
            System.exit(0); // don't go to interactive mode
        }

        if (cmd.hasOption("c")) { // enter identification mode
            cluster.updateVMs();
            new ElastManServer(true, cluster).run(); // start in this thread instead of .start();
            System.exit(0); // don't go to interactive mode
        }

        int command;

        while (true) {
            System.out.println(
                    "\n0 - Exit\t1 - Status\t2 - Delete all\t3 - Images\t4 - flavors\t5 - create\t6 - Generate Cluster.xml\t7 - Identify\t8 - control");
            System.out.print("command > ");

            if ((command = getInt()) == -1)
                continue;

            switch (command) {
            case 0:
                nova.close();
                System.out.println("Good bye!");
                System.exit(0);
                break;

            case 1:
                System.out.println("1 - All our VMs\t2 - Voldemort \t3 - YCSB");
                System.out.print("command > ");

                if ((command = getInt()) == -1)
                    break;

                switch (command) {
                case 1:
                    cluster.updateVMs();
                    showStatus(null);
                    break;
                case 2:
                    cluster.updateVMs();
                    showStatus(cluster.getVoldPrefix());
                    break;
                case 3:
                    cluster.updateVMs();
                    showStatus(cluster.getYcsbPrefix());
                    break;
                default:
                    System.out.println("Don't know this command yet! Try again later :P");
                    break;
                }
                break;
            case 2:
                //            System.out.print("Are you sure? (y/n)? ");
                //            if(scanner.next().toLowerCase().equals("y")) {
                //               deleteVMs();
                //            }
                System.out.print("Enter prefix ( * for all ) > ");
                String prefix = scanner.next();
                if (prefix.equals("*")) {
                    cluster.deleteVMs(null);
                } else {
                    cluster.deleteVMs(prefix);
                }
                break;
            case 3:
                for (Image image : nova.getImages()) {
                    System.out.println("\tID: " + image.getId() + "\tName: " + image.getName());
                }
                break;
            case 4:
                for (Flavor flavor : nova.getFlavors()) {
                    System.out.println("\tID: " + flavor.getId() + "\tName: " + flavor.getName());
                }
                break;
            case 5:
                int count;
                System.out.print("Please enter: count prefix image_ID flavor_ID: ");
                count = getInt();
                cluster.createVMs(count, scanner.next(), scanner.next(), scanner.next());
                System.out.println("Done!");
                break;
            case 6:
                int nodes;
                System.out.print("Enter number of VMs in cluster, -1 for all: ");
                nodes = getInt();
                sync.reset();
                cluster.updateVMs();
                cluster.genCluster(nodes);
                sync.unlock();
                break;
            case 7:
                new ElastManServer(false, cluster).start();
                break;
            case 8:
                new ElastManServer(true, cluster).start();
                break;
            case 9:
                break;
            case 10:
                SSHClient ssh = new SSHClient();
                try {
                    HostKeyVerifier hkv = new HostKeyVerifier() {

                        //@Override
                        public boolean verify(String hostname, int port, PublicKey key) {
                            System.out.println(hostname + " " + port + " " + key);
                            return true;
                        }
                    }; // this ignores known_hosts and accepts any host. Less secure!

                    ssh.addHostKeyVerifier(hkv);
                    ssh.connect("cloud2.sics.se");
                    //               ssh.authPassword("ahmad", "xxx");
                    String username = "ahmad";
                    File privateKey = new File("C:\\Users\\Admin\\Documents\\MyDocs\\Misc\\Ahmad\\ahmad");
                    KeyProvider keys = ssh.loadKeys(privateKey.getPath());
                    ssh.authPublickey(username, keys);
                    final Session session = ssh.startSession();
                    Command cmd = session.exec("date; hostname");
                    BufferedReader in = new BufferedReader(new InputStreamReader(cmd.getInputStream()));
                    String res;
                    while ((res = in.readLine()) != null) {
                        System.out.println(res);
                    }
                    // SSHClient client = new SSHClient();
                    //               String username = "johndoe";
                    //               File privateKey = new File("~/.ssh/id_rsa");
                    //               KeyProvider keys = client.loadKeys(privateKey.getPath());
                    //               client.authPublicKey(username, keys);

                } catch (UserAuthException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (TransportException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                break;
            default:
                System.out.println("Don't know this command yet! Try again later :P");
                break;
            }
        }
    }

    private static int getInt() {

        try {
            return scanner.nextInt();
        } catch (Exception e) {
            System.out.println("Invalid Input!");
            scanner.nextLine();
            return -1;
        }
    }

    ///////////////////////////////////////////

    private void showStatus(String namePrefix) {

        int hosts = 0, vms = 0;
        boolean print = true; // to print host name only if VMs found on it
        System.out.println("===========================");
        for (String hostId : cluster.getHosts()) {
            for (Server s : cluster.getVMsOnHost(hostId)) {
                if (namePrefix == null || s.getName().startsWith(namePrefix)) {
                    if (print) {
                        hosts++;
                        System.out.println(Cluster.getHostName(hostId));
                        print = false;
                    }
                    System.out.println(s.getName() + "\t" + Nova.getAddr(s) + "\t" + s.getId());
                    vms++;
                }
            }
            if (!print) { // this means that we printed something so we put a line to separate hosts and reset print
                print = true;
                System.out.println("===========================");
            }
        }
        System.out.println("found " + vms + " VMs running on " + hosts + " hosts!");

    }

}