gov.llnl.lc.smt.command.privileged.SmtPrivileged.java Source code

Java tutorial

Introduction

Here is the source code for gov.llnl.lc.smt.command.privileged.SmtPrivileged.java

Source

/************************************************************
 * Copyright (c) 2015, Lawrence Livermore National Security, LLC.
 * Produced at the Lawrence Livermore National Laboratory.
 * Written by Timothy Meier, meier3@llnl.gov, All rights reserved.
 * LLNL-CODE-673346
 *
 * This file is part of the OpenSM Monitoring Service (OMS) package.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License (as published by
 * the Free Software Foundation) version 2.1 dated February 1999.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * OUR NOTICE AND TERMS AND CONDITIONS OF THE GNU GENERAL PUBLIC LICENSE
 *
 * Our Preamble Notice
 *
 * A. This notice is required to be provided under our contract with the U.S.
 * Department of Energy (DOE). This work was produced at the Lawrence Livermore
 * National Laboratory under Contract No.  DE-AC52-07NA27344 with the DOE.
 *
 * B. Neither the United States Government nor Lawrence Livermore National
 * Security, LLC nor any of their employees, makes any warranty, express or
 * implied, or assumes any liability or responsibility for the accuracy,
 * completeness, or usefulness of any information, apparatus, product, or
 * process disclosed, or represents that its use would not infringe privately-
 * owned rights.
 *
 * C. Also, reference herein to any specific commercial products, process, or
 * services by trade name, trademark, manufacturer or otherwise does not
 * necessarily constitute or imply its endorsement, recommendation, or favoring
 * by the United States Government or Lawrence Livermore National Security,
 * LLC. The views and opinions of authors expressed herein do not necessarily
 * state or reflect those of the United States Government or Lawrence Livermore
 * National Security, LLC, and shall not be used for advertising or product
 * endorsement purposes.
 *
 *        file: SmtPrivileged.java
 *
 *  Created on: Jun 3, 2013
 *      Author: meier3
 ********************************************************************/
package gov.llnl.lc.smt.command.privileged;

import java.util.Map;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;

import gov.llnl.lc.infiniband.core.IB_Address;
import gov.llnl.lc.infiniband.core.IB_Guid;
import gov.llnl.lc.infiniband.opensm.plugin.OsmNativeCommand;
import gov.llnl.lc.infiniband.opensm.plugin.net.OsmAdminApi;
import gov.llnl.lc.infiniband.opensm.plugin.net.OsmServiceManager;
import gov.llnl.lc.infiniband.opensm.plugin.net.OsmSession;
import gov.llnl.lc.smt.SmtConstants;
import gov.llnl.lc.smt.command.SmtCommand;
import gov.llnl.lc.smt.command.config.SmtConfig;
import gov.llnl.lc.smt.props.SmtProperty;
import gov.llnl.lc.system.CommandLineArguments;
import gov.llnl.lc.system.CommandLineResults;
import gov.llnl.lc.system.Console;

/**********************************************************************
 * The SmtPrivileged command is a convenient tool to invoke
 * commands that cause opensm to take an action or alter its behavior
 * that may directly or indirectly disturb the fabric.  This kind of
 * action requires elevated privileges.
 * <p>
 * @see  related classes and interfaces
 *
 * @author meier3
 * 
 * @version Jan 5, 2015 7:46:43 AM
 **********************************************************************/
public class SmtPrivileged extends SmtCommand {
    private static final String NODE_ID = "nodeid";
    private static final String PORT_ID = "portid";
    private static final String ARG_ID = "cmdArgs";

    private OsmSession ParentSession = null;

    /* the one and only OsmServiceManager */
    private volatile OsmServiceManager OsmService = null;

    /************************************************************
     * Method Name:
     *  doCommand
     **/
    /**
     * Describe the method here
     *
     * @see gov.llnl.lc.smt.command.SmtCommand#doCommand(gov.llnl.lc.smt.command.config.SmtConfig)
     *
     * @param config
     * @return
     * @throws Exception
     ***********************************************************/

    @Override
    public boolean doCommand(SmtConfig config) throws Exception {
        OsmService = OsmServiceManager.getInstance();
        OsmAdminApi adminInterface = null;
        String subCommand = null;
        CommandLineResults results = null;

        if (config != null) {
            // open a session for the command
            Map<String, String> map = config.getConfigMap();
            String hostNam = map.get(SmtProperty.SMT_HOST.getName());
            String portNum = map.get(SmtProperty.SMT_PORT.getName());

            try {
                ParentSession = OsmService.openSession(hostNam, portNum, null, null);
                adminInterface = ParentSession.getAdminApi();
            } catch (Exception e) {
                logger.severe(e.getStackTrace().toString());
                System.exit(0);
            }

            subCommand = map.get(SmtProperty.SMT_SUBCOMMAND.getName());
            if (subCommand == null)
                subCommand = SmtProperty.SMT_HELP.getName();

            // there should only be one subcommand
            if (subCommand.equalsIgnoreCase(SmtProperty.SMT_PRIV_EXT.getName())) {
                String cmdArgs = getCommandArgs(map);
                System.err.println("The command (" + cmdArgs + ")");
                results = adminInterface.invokePrivilegedCommand(new CommandLineArguments(cmdArgs));
            } else if (subCommand.equalsIgnoreCase(SmtProperty.SMT_PRIV_ENABLE.getName())) {
                String portid = getPortIdentification(map);
                results = ibportstate(portid + " enable");
            } else if (subCommand.equalsIgnoreCase(SmtProperty.SMT_PRIV_DISABLE.getName())) {
                String portid = getPortIdentification(map);
                results = ibportstate(portid + " disable");
            } else if (subCommand.equalsIgnoreCase(SmtProperty.SMT_PRIV_QUERY_PORT.getName())) {
                String portid = getPortIdentification(map);
                results = ibportstate(portid);
            } else if (subCommand.equalsIgnoreCase(SmtProperty.SMT_PRIV_UPDATE_DESC.getName())) {
                results = adminInterface.invokePrivilegedCommand(
                        new CommandLineArguments(OsmNativeCommand.OSM_NATIVE_UPDATE_DESC.getCommandName()));
            } else if (subCommand.equalsIgnoreCase(SmtProperty.SMT_PRIV_REROUTE.getName())) {
                results = adminInterface.invokePrivilegedCommand(
                        new CommandLineArguments(OsmNativeCommand.OSM_NATIVE_REROUTE.getCommandName()));
            } else if (subCommand.equalsIgnoreCase(SmtProperty.SMT_PRIV_PM_CLEAR.getName())) {
                results = adminInterface.invokePrivilegedCommand(
                        new CommandLineArguments(OsmNativeCommand.OSM_NATIVE_PCLEAR.getCommandName()));
            } else if (subCommand.equalsIgnoreCase(SmtProperty.SMT_PRIV_LT_SWEEP.getName())) {
                results = adminInterface.invokePrivilegedCommand(
                        new CommandLineArguments(OsmNativeCommand.OSM_NATIVE_LSWEEP.getCommandName()));
            } else if (subCommand.equalsIgnoreCase(SmtProperty.SMT_PRIV_HV_SWEEP.getName())) {
                results = adminInterface.invokePrivilegedCommand(
                        new CommandLineArguments(OsmNativeCommand.OSM_NATIVE_HSWEEP.getCommandName()));
            } else if (subCommand.equalsIgnoreCase(SmtProperty.SMT_PRIV_PM_SWEEP.getName())) {
                results = adminInterface.invokePrivilegedCommand(
                        new CommandLineArguments(OsmNativeCommand.OSM_NATIVE_PSWEEP.getCommandName()));
            } else if (subCommand.equalsIgnoreCase(SmtProperty.SMT_PRIV_OSM_LOG_LEVEL.getName())) {
                SmtProperty sc = SmtProperty.getByName(subCommand);

                // now use that property to find the sub commands argument
                if (sc != null) {
                    String subCommandArg = map.get(sc.getName());
                    if (subCommandArg != null) {
                        // needs to be in hex format, with 0x out front
                        results = adminInterface.invokePrivilegedCommand(new CommandLineArguments(
                                OsmNativeCommand.OSM_NATIVE_LOGLEVEL.getCommandName() + " " + subCommandArg));
                    }
                    System.err.println("The subcommand and args are: " + subCommand + ", " + subCommandArg);
                }
            } else if (subCommand.equalsIgnoreCase(SmtProperty.SMT_PRIV_PM_SWEEP_PERIOD.getName())) {
                SmtProperty sc = SmtProperty.getByName(subCommand);

                // now use that property to find the sub commands argument
                if (sc != null) {
                    String subCommandArg = map.get(sc.getName());
                    if (subCommandArg != null) {
                        // needs to be in seconds
                        results = adminInterface.invokePrivilegedCommand(new CommandLineArguments(
                                OsmNativeCommand.OSM_NATIVE_PPERIOD.getCommandName() + " " + subCommandArg));
                    }
                    System.err.println("The subcommand and args are: " + subCommand + ", " + subCommandArg);
                }
            } else {
                System.err.println("A priv command: " + subCommand + " was NOT handled");
            }

            if (results == null) {
                System.out.println("Privileged command denied");
                return false;
            }

            // show the results (color the System.err RED)
            if ((results.getOutput() != null) && (results.getOutput().length() > 1))
                System.out.println(results.getOutput());
            if ((results.getError() != null) && (results.getError().length() > 1)) {
                Console.textNormal();
                Console.textColor(Console.ConsoleColor.red);
                System.out.println(results.getError());
            }
            Console.textNormal();
            Console.backgroundNormal();
            return true;
        }
        return false;
    }

    /************************************************************
     * Method Name:
     *  init
     **/
    /**
     * Describe the method here
     *
     * @see gov.llnl.lc.smt.command.SmtCommand#init()
     *
     * @return
     ***********************************************************/

    @Override
    public boolean init() {
        USAGE = "[-v] [-?]  ";
        HEADER = "smt-priv - invokes a privileged command (requires a connection)";
        EXAMPLE = "examples:" + SmtConstants.NEW_LINE
                + "> smt-priv -pn 10011 -X \"hostname\"  - invoke the hostname command on the OMS node, and return the results"
                + SmtConstants.NEW_LINE + "> smt-priv -pn 10013 -dP 14 3       - disable port 3 of node with lid 14"
                + SmtConstants.NEW_LINE + "> smt-priv -pn 10011 -rt            - re-routes the fabric"
                + SmtConstants.NEW_LINE + "> smt-priv -pn 10013 -uD            - updates the node descriptions"
                + SmtConstants.NEW_LINE + "."; // terminate with nl

        // create and initialize the common options for this command
        initConnectionOptions();

        // initialize the command specific options
        SmtProperty sp = SmtProperty.SMT_PRIV_EXT;
        Option ext = OptionBuilder.hasArg(true).hasArgs().withArgName(sp.getArgName()).withValueSeparator('=')
                .withDescription(sp.getDescription()).withLongOpt(sp.getName()).create(sp.getShortName());

        sp = SmtProperty.SMT_PRIV_ENABLE;
        Option enable = OptionBuilder.hasArg(true).hasArgs(2).withArgName(sp.getArgName()).withValueSeparator('=')
                .withDescription(sp.getDescription()).withLongOpt(sp.getName()).create(sp.getShortName());
        sp = SmtProperty.SMT_PRIV_DISABLE;
        Option disable = OptionBuilder.hasArg(true).hasArgs(2).withArgName(sp.getArgName()).withValueSeparator('=')
                .withDescription(sp.getDescription()).withLongOpt(sp.getName()).create(sp.getShortName());
        sp = SmtProperty.SMT_PRIV_QUERY_PORT;
        Option query = OptionBuilder.hasArg(true).hasArgs(2).withArgName(sp.getArgName()).withValueSeparator('=')
                .withDescription(sp.getDescription()).withLongOpt(sp.getName()).create(sp.getShortName());

        sp = SmtProperty.SMT_PRIV_OSM_LOG_LEVEL;
        Option logLevel = OptionBuilder.hasArg(true).hasArgs(1).withArgName(sp.getArgName()).withValueSeparator('=')
                .withDescription(sp.getDescription()).withLongOpt(sp.getName()).create(sp.getShortName());
        sp = SmtProperty.SMT_PRIV_PM_SWEEP_PERIOD;
        Option sPeriod = OptionBuilder.hasArg(true).hasArgs(1).withArgName(sp.getArgName()).withValueSeparator('=')
                .withDescription(sp.getDescription()).withLongOpt(sp.getName()).create(sp.getShortName());

        sp = SmtProperty.SMT_PRIV_UPDATE_DESC;
        Option update = OptionBuilder.hasArg(false).withDescription(sp.getDescription()).withLongOpt(sp.getName())
                .create(sp.getShortName());
        sp = SmtProperty.SMT_PRIV_REROUTE;
        Option reroute = OptionBuilder.hasArg(false).withDescription(sp.getDescription()).withLongOpt(sp.getName())
                .create(sp.getShortName());
        sp = SmtProperty.SMT_PRIV_PM_CLEAR;
        Option clear = OptionBuilder.hasArg(false).withDescription(sp.getDescription()).withLongOpt(sp.getName())
                .create(sp.getShortName());
        sp = SmtProperty.SMT_PRIV_LT_SWEEP;
        Option lsweep = OptionBuilder.hasArg(false).withDescription(sp.getDescription()).withLongOpt(sp.getName())
                .create(sp.getShortName());
        sp = SmtProperty.SMT_PRIV_HV_SWEEP;
        Option hsweep = OptionBuilder.hasArg(false).withDescription(sp.getDescription()).withLongOpt(sp.getName())
                .create(sp.getShortName());
        sp = SmtProperty.SMT_PRIV_PM_SWEEP;
        Option psweep = OptionBuilder.hasArg(false).withDescription(sp.getDescription()).withLongOpt(sp.getName())
                .create(sp.getShortName());

        options.addOption(ext);
        options.addOption(enable);
        options.addOption(disable);
        options.addOption(query);

        options.addOption(logLevel);
        options.addOption(sPeriod);

        options.addOption(update);
        options.addOption(reroute);
        options.addOption(clear);
        options.addOption(lsweep);
        options.addOption(hsweep);
        options.addOption(psweep);

        return true;
    }

    /************************************************************
     * Method Name:
     *  parseCommands
     **/
    /**
    * Every command gets its command line options parsed and saved by an instance
     * of SmtConfig. After normal parsing, additional command specific parsing can
     * occur in this method. It is typically used to persist additional command
     * line arguments in the config map for future use.
     * 
     * @see gov.llnl.lc.smt.command.SmtConfig#parseCommandLineOptions
     * @see gov.llnl.lc.smt.command.SmtCommandInterface#parseCommands(java.util.Map,
     *      org.apache.commons.cli.CommandLine)
     * 
     * @param config
     * @param line
     * @return
     ***********************************************************/

    @Override
    public boolean parseCommands(Map<String, String> config, CommandLine line) {
        // set the command and sub-command
        config.put(SmtProperty.SMT_COMMAND.getName(), this.getClass().getName());

        // parse (only) the command specific options (see init() )
        SmtProperty sp = SmtProperty.SMT_PRIV_EXT;
        saveCommandArgs(sp.getName(), config, line);

        // these commands take exactly two arguments (last one wins)
        sp = SmtProperty.SMT_PRIV_ENABLE;
        savePortIdentification(sp.getName(), config, line);
        sp = SmtProperty.SMT_PRIV_DISABLE;
        savePortIdentification(sp.getName(), config, line);
        sp = SmtProperty.SMT_PRIV_QUERY_PORT;
        savePortIdentification(sp.getName(), config, line);

        // these commands take exactly one argument
        sp = SmtProperty.SMT_PRIV_OSM_LOG_LEVEL;
        if (line.hasOption(sp.getName())) {
            config.put(SmtProperty.SMT_SUBCOMMAND.getName(), sp.getName());
            config.put(sp.getName(), line.getOptionValue(sp.getName()));
        }
        sp = SmtProperty.SMT_PRIV_PM_SWEEP_PERIOD;
        if (line.hasOption(sp.getName())) {
            config.put(SmtProperty.SMT_SUBCOMMAND.getName(), sp.getName());
            config.put(sp.getName(), line.getOptionValue(sp.getName()));
        }

        // the remainder of the commands don't take arguments
        saveSubCommand(SmtProperty.SMT_PRIV_UPDATE_DESC.getName(), config, line);
        saveSubCommand(SmtProperty.SMT_PRIV_REROUTE.getName(), config, line);
        saveSubCommand(SmtProperty.SMT_PRIV_PM_CLEAR.getName(), config, line);
        saveSubCommand(SmtProperty.SMT_PRIV_LT_SWEEP.getName(), config, line);
        saveSubCommand(SmtProperty.SMT_PRIV_HV_SWEEP.getName(), config, line);
        saveSubCommand(SmtProperty.SMT_PRIV_PM_SWEEP.getName(), config, line);

        return true;
    }

    private boolean savePortIdentification(String cName, Map<String, String> config, CommandLine line) {
        if (line.hasOption(cName)) {
            // there should be a guid or lid, followed by a port number
            String[] args = line.getOptionValues(cName);
            if (args.length != 2) {
                // log an error, and exit
                System.err.println("command requires a two arguments");
                return false;
            }
            // save the nodeid and port number
            config.put(NODE_ID, args[0]);
            config.put(PORT_ID, args[1]);

            config.put(SmtProperty.SMT_SUBCOMMAND.getName(), cName);
            return true;
        }
        return false;
    }

    private boolean saveCommandArgs(String cName, Map<String, String> config, CommandLine line) {
        if (line.hasOption(cName)) {
            config.put(SmtProperty.SMT_SUBCOMMAND.getName(), cName);
            config.put(ARG_ID, "");

            // there may be command arguments, get them all, and concatenate them
            String[] args = line.getOptionValues(cName);
            if ((args == null || args.length < 0)) {
                // log an error, and exit
                System.err.println("argument error");
                return false;
            }
            // save all the arguments in a single parameter
            StringBuffer cmdArgs = new StringBuffer();
            for (String arg : args) {
                cmdArgs.append(arg + " ");
            }
            config.put(ARG_ID, cmdArgs.toString().trim());
            config.put(cName, cmdArgs.toString().trim());
            return true;
        }
        return false;
    }

    private boolean saveSubCommand(String cName, Map<String, String> config, CommandLine line) {
        if (line.hasOption(cName)) {
            config.put(SmtProperty.SMT_SUBCOMMAND.getName(), cName);
            return true;
        }
        return false;
    }

    private String getCommandArgs(Map<String, String> map) {
        String cmdArgs = map.get(ARG_ID);

        // don't allow multiple commands
        int ndex = cmdArgs.indexOf(';');
        if (ndex > -1)
            return cmdArgs.substring(0, ndex).trim();
        return cmdArgs.trim();
    }

    private String getPortIdentification(Map<String, String> map) {
        String nodeid = map.get(NODE_ID);
        String portid = map.get(PORT_ID);
        IB_Guid g = null;
        int nodeLid = 0;
        int portN = 0;
        // arg will be a guid, string, or long
        logger.severe("Attempting to query a node: " + nodeid);
        // if this starts with an 0x, 0X, then assume it is hex
        // if this is a very long number, assume it is a long
        // if this is a short number, assume it is a lid
        if (nodeid != null) {
            if (nodeid.length() < 10) {
                // must be a lid
                nodeLid = IB_Address.toLidValue(nodeid);
            } else {
                // an IB_Guid or a long
                g = new IB_Guid(nodeid);
            }
            if (g != null)
                logger.severe("The guid is: " + g.toColonString());
            else
                logger.severe("The lid is: " + nodeLid);

        } else {
            // shouldn't be here, print message and bail
            System.err.println("Some form of node identification is required for this command");
            System.exit(0);
        }
        if (portid != null) {
            portN = Integer.parseInt(portid);
        } else {
            // shouldn't be here, print message and bail
            System.err.println("A port number is required for this command");
            System.exit(0);
        }
        StringBuffer cmdArgs = new StringBuffer();
        if (g != null)
            cmdArgs.append("-G 0x" + g.toString());
        else
            cmdArgs.append(nodeLid);

        cmdArgs.append(" " + portN);
        return cmdArgs.toString();
    }

    private CommandLineResults ibportstate(String args) throws Exception {
        OsmAdminApi adminInterface = ParentSession.getAdminApi();
        return adminInterface.invokePrivilegedCommand(new CommandLineArguments("ibportstate " + args));
    }

    /************************************************************
     * Method Name:
     *  main
     **/
    /**
     * Describe the method here
     *
     * @see     describe related java objects
     *
     * @param args
     ***********************************************************/
    public static void main(String[] args) throws Exception {
        System.exit((new SmtPrivileged().execute(args)) ? 0 : -1);
    }
}