/******************************************************************************* * =========================================================== * Ankush : Big Data Cluster Management Solution * =========================================================== * * (C) Copyright 2014, by Impetus Technologies * * This is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License (LGPL v3) as * published by the Free Software Foundation; * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ******************************************************************************/ package com.impetus.ankush2.utils; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.neoremind.sshxcute.core.ConnBean; import net.neoremind.sshxcute.core.Result; import net.neoremind.sshxcute.core.SSHExec; import net.neoremind.sshxcute.exception.TaskExecFailException; import net.neoremind.sshxcute.task.CustomTask; import net.neoremind.sshxcute.task.impl.ExecCommand; import com.impetus.ankush.common.exception.AnkushException; import com.impetus.ankush.common.scripting.AnkushTask; import com.impetus.ankush.common.scripting.impl.AppendFileUsingEcho; import com.impetus.ankush.common.scripting.impl.MakeDirectory; import com.impetus.ankush.common.scripting.impl.Untar; import com.impetus.ankush.common.scripting.impl.Unzip; import com.impetus.ankush.common.scripting.impl.Wget; import com.impetus.ankush.common.utils.FileNameUtils; import com.impetus.ankush.common.utils.SSHConnection; import com.impetus.ankush2.agent.AgentConstant; import com.impetus.ankush2.constant.Constant; import com.impetus.ankush2.framework.config.AuthConfig; import com.impetus.ankush2.framework.config.ComponentConfig; import com.impetus.ankush2.framework.config.ComponentConfig.SourceType; import com.impetus.ankush2.framework.config.NodeConfig; import com.impetus.ankush2.ganglia.GangliaConstants; import com.impetus.ankush2.hadoop.utils.HadoopConstants; import com.impetus.ankush2.logger.AnkushLogger; public class SSHUtils { private static AnkushLogger logger = new AnkushLogger(SSHUtils.class); public static SSHExec connectToNode(String host, AuthConfig authConfig) { if (authConfig.isUsingPassword()) { return connectToNode(host, authConfig.getUsername(), authConfig.getPassword(), null); } else { return connectToNode(host, authConfig.getUsername(), null, authConfig.getPrivateKey()); } } public static SSHExec connectToNode(String node, String username, String password, String privateKey) { try { // create connection bean if (node == null || node.isEmpty()) { return null; } if (username == null || username.isEmpty()) { return null; } ConnBean connectionBean = new ConnBean(node, username, password, privateKey); // singleton bug fix SSHExec connection = new SSHExec(connectionBean); // connect to node/machine Boolean isConnected = connection.connect(); if (isConnected) { return connection; } else { return null; } } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } public static boolean getAndExtractComponent(SSHExec connection, ComponentConfig conf, String componentName) throws Exception { String bundlePath = new String(); String componentExtension = null; try { AnkushTask makeHomeDir = new MakeDirectory(conf.getHomeDir()); if (!connection.exec(makeHomeDir).isSuccess) { throw new AnkushException( "Could not create home directory for " + componentName + " using command - " + makeHomeDir.getCommand()); } // upload from server to master node if (conf.getSourceType().equals(SourceType.UPLOAD) && !conf.getSource().isEmpty()) { componentExtension = FileNameUtils.getFileExtension(conf .getSource()); bundlePath = conf.getInstallPath() + FileNameUtils.getName(conf.getSource()); // Uploading tarball from server to master node connection.uploadSingleDataToServer(conf.getSource(), bundlePath); } // tarball exists locally if (conf.getSourceType().equals(SourceType.LOCAL) && !conf.getSource().isEmpty()) { // getting local tarball path componentExtension = FileNameUtils.getFileExtension(conf .getSource()); bundlePath = conf.getSource(); } // download through wget if (conf.getSourceType().equals(SourceType.DOWNLOAD) && !conf.getSource().isEmpty()) { componentExtension = FileNameUtils.getFileExtension(conf .getSource()); bundlePath = conf.getInstallPath() + FileNameUtils.getName(conf.getSource()); // Wget tarball AnkushTask wgetTask = new Wget(conf.getSource(), bundlePath); connection.exec(wgetTask); } CustomTask task = null; if (FileNameUtils.isTarGz(componentExtension)) { // untar binary task = new Untar(bundlePath, conf.getHomeDir()); } if (FileNameUtils.isZip(componentExtension)) { // unzip binary task = new Unzip(bundlePath, conf.getHomeDir()); } if (FileNameUtils.isUnsupported(componentExtension)) { // Invalid component file return false; } Result res = connection.exec(task); if (!res.isSuccess) { throw new AnkushException("Could not extract " + componentName + " using command - " + task.getCommand()); } return res.isSuccess; } catch (AnkushException e) { throw e; } catch (TaskExecFailException e) { throw new Exception(e.getMessage(), e); } catch (Exception e) { throw new Exception(e.getMessage(), e); } } /** * Get JavaHome path from remote machine. * * @param hostname * the hostname * @param username * the username * @param authInfo * password/sharedkey * @param authUsingPassword * the auth using password * @return the java home */ public static String getJavaVersion(String hostname, String username, String authInfo, boolean authUsingPassword) { /* Making connection to the node. */ SSHConnection connection = new SSHConnection(hostname, username, authInfo, authUsingPassword); /* Executing the command. */ if (connection.exec("java -version")) { String output = connection.getOutput(); if (output == null) { output = connection.getError(); } if (output != null) { String strJavaVersion = output.substring(0, output.indexOf("\n")); String javaVersion = strJavaVersion.substring( strJavaVersion.indexOf("\""), strJavaVersion.length() - 1); return javaVersion; } } return null; } public static String getFileContents(String filePath, NodeConfig host) { String output = null; try { if (host.getConnection() == null) { logger.error("Invalid connection for host - " + host.getHost()); return null; } CustomTask task = new ExecCommand("cat " + filePath); Result res = host.getConnection().exec(task); /* Executing the command. */ if (res.rc != 0) { logger.error("Unable to read file " + filePath + " for host - " + host.getHost()); return null; } else { output = res.sysout; } return output; } catch (Exception e) { logger.error("Unable to read file " + filePath + " for host - " + host.getHost()); return null; } } public static String getFileContents(String filePath, SSHExec connection) { String output = null; try { if (connection == null) { logger.error("Invalid connection"); return null; } CustomTask task = new ExecCommand("cat " + filePath); Result res = connection.exec(task); /* Executing the command. */ if (res.rc != 0) { logger.error("Unable to read file " + filePath + "."); return null; } else { output = res.sysout; } return output; } catch (Exception e) { logger.error("Unable to read file " + filePath + "."); return null; } } public static String getCommandOutput(String command, String hostname, AuthConfig authConfig) throws Exception { String output = null; /* Making connection to the node. */ SSHConnection connection = new SSHConnection(hostname, authConfig.getUsername(), authConfig.getPassword(), authConfig.getPrivateKey()); /* Executing the command. */ if (connection.exec(command)) { if (connection.getExitStatus() != 0) { output = connection.getError(); throw new Exception(connection.getError()); } /* Getting the output from connection object. */ output = connection.getOutput(); } /* Returning the output of command. */ return output; } public static List<String> listDirectory(String hostname, String directoryPath, AuthConfig authConfig) throws Exception { // Create ls command String lsCommand = "ls " + directoryPath; // Executing command and getting the command output String commandOutput = SSHUtils.getCommandOutput(lsCommand, hostname, authConfig); // Create list object List<String> paths = new ArrayList<String>(); // if command output not null. if (commandOutput != null) { // Splitting the output by '\n' String[] fileNameList = commandOutput .split(Constant.Strings.LINE_SEPERATOR); // Iterating over the filename list. paths.addAll(Arrays.asList(fileNameList)); } else { // throwing the exception throw new Exception("Unable to connect to node."); } return paths; } public static String getFileContents(String filePath, String hostname, AuthConfig authConf) throws Exception { String output = null; // Making the SSH Connection. SSHConnection connection = new SSHConnection(hostname, authConf.getUsername(), authConf.getPassword(), authConf.isUsingPassword()); if (!connection.isConnected()) { throw new Exception("Unable to connect to node."); } /* Executing the command. */ if (connection.exec("cat " + filePath)) { if (connection.getExitStatus() == 0) { // Getting the output of command. output = connection.getOutput(); } else { String error = connection.getError(); if (error.contains("No such file")) { throw new Exception(filePath + " does not exists"); } else if (error.contains("Permission denied")) { throw new Exception("Invalid permissions on " + filePath); } } } return output; } public static boolean generateRSAKeyFiles(NodeConfig host) { try { CustomTask task = new ExecCommand( HadoopConstants.Command.GENERATE_RSA_KEYS); if (host.getConnection().exec(task).rc != 0) { logger.error("Unable to generate RSA Keys for host - " + host.getHost()); return false; } } catch (Exception e) { logger.error("Unable to generate RSA Keys for host - " + host.getHost()); return false; } return true; } public static String getOS(String hostname, String username, String authInfo, boolean authUsingPassword) { SSHExec connection = null; try { /* Making connection to the node. */ if (authUsingPassword) { connection = connectToNode(hostname, username, authInfo, null); } else { connection = connectToNode(hostname, username, null, authInfo); } if (connection == null) { throw new AnkushException( "Could not create connection with node to get OS details"); } return getOS(connection, hostname); } catch (AnkushException e) { logger.error(e.getMessage()); } catch (Exception e) { logger.error("Could not gte OS details."); } finally { if (connection != null) { connection.disconnect(); } } return null; } /** * Method to get OS Name * * @param connection * {@link SSHExec} * @return {@link String} */ public static String getOS(SSHExec connection, String host) throws AnkushException { Result rs = null; try { String command = "cat /etc/*-release"; CustomTask task = new ExecCommand(command); /* Executing the command. */ rs = connection.exec(task); if (rs.rc != 0) { throw new AnkushException("Could not execute " + command + " on node " + host + " to find OS."); } String output = rs.sysout.toLowerCase(); if (output != null) { Pattern pattern = Pattern.compile("NAME=\"(.*?)\""); Matcher matcher = pattern.matcher(output); if (matcher.find()) { return getOSName(matcher.group(1)); } else { return getOSName(output); } } else { throw new AnkushException("Could not get OS name on node : " + host); } } catch (AnkushException e) { throw e; } catch (Exception e) { throw new AnkushException( "There is some exception while getting OS detail on node : " + host + "." + GangliaConstants.EXCEPTION_STRING, e); } } private static String getOSName(String output) throws AnkushException { if (output.contains("ubuntu")) { return "Ubuntu"; } if (output.contains("centos")) { return "CentOS"; } if (output.contains("red hat enterprise linux")) { return "RHEL"; } if (output.contains("opensuse")) { return "openSUSE"; } if (output.contains("fedora")) { return "Fedora"; } throw new AnkushException("Could not get OS Name"); } public static String getCommandOutput(String command, String hostname, String username, String authInfo, boolean authUsingPassword) throws Exception { String output = null; /* Making connection to the node. */ SSHConnection connection = new SSHConnection(hostname, username, authInfo, authUsingPassword); /* Executing the command. */ if (connection.exec(command)) { if (connection.getExitStatus() != 0) { output = connection.getError(); throw new Exception(connection.getError()); } /* Getting the output from connection object. */ output = connection.getOutput(); } /* Returning the output of command. */ return output; } public static Map getCommandOutputAndError(String command, String hostName, AuthConfig authInfo) { Map map = new HashMap(); String output = null; boolean status = false; /* Making connection to the node. */ SSHConnection connection = new SSHConnection(hostName, authInfo.getUsername(), authInfo.getPassword(), authInfo.isUsingPassword()); /* Executing the command. */ if (!connection.exec(command) || connection.getExitStatus() != 0) { /* Getting the error from connection object. */ output = connection.getError(); } else { /* Getting the output from connection object. */ output = connection.getOutput(); status = true; } /* Returning the output of command. */ map.put(com.impetus.ankush2.constant.Constant.Keys.STATUS, status); map.put(com.impetus.ankush2.constant.Constant.Keys.OUTPUT, output); return map; } /** * Method to execute list of tasks. If any one fails it return backs the * result of failed task otherwise the last task result. * * @param tasks * @return */ public static Result executeTasks(List<AnkushTask> tasks, SSHExec connection) { Result result = null; try { // iterating over the tasks. for (AnkushTask task : tasks) { // executing command result = connection.exec(task); // if command execution failed break the for loop if (result.rc != 0) { break; } } } catch (Exception e) { logger.error("Could not execute the tasks.", e); } // returning result. return result; } /** * Adds the process info. * */ public static boolean addInAgentTaskableFile(SSHExec connection, String className, String agentHomeDir) { try { // JPS service status monitor class name. className = Constant.Strings.LINE_SEPERATOR + className; // add task information in taskable conf. AnkushTask task = new AppendFileUsingEcho(className, agentHomeDir + AgentConstant.Relative_Path.TASKABLE_FILE); connection.exec(task); return true; } catch (TaskExecFailException e) { logger.error("Error in adding agent informations..", e); } catch (Exception e) { logger.error("Error in adding agent informations..", e); } return false; } }