// Copyright 2012 Citrix Systems, Inc. Licensed under the // Apache License, Version 2.0 (the "License"); you may not use this // file except in compliance with the License. Citrix Systems, Inc. // reserves all rights not expressly granted by 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. // // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.hypervisor.vmware.resource; import java.io.File; import java.io.InputStream; import org.apache.log4j.Logger; import com.cloud.utils.Pair; import com.trilead.ssh2.ChannelCondition; public class SshHelper { private static int DEFAULT_CONNECT_TIMEOUT = 60000; private static int DEFAULT_KEX_TIMEOUT = 60000; private static final Logger s_logger = Logger.getLogger(SshHelper.class); public static Pair<Boolean, String> sshExecute(String host, int port, String user, File pemKeyFile, String password, String command) throws Exception { return sshExecute(host, port, user, pemKeyFile, password, command, 60000, 60000, 120000); } public static void scpTo(String host, int port, String user, File pemKeyFile, String password, String remoteTargetDirectory, String localFile, String fileMode) throws Exception { scpTo(host, port, user, pemKeyFile, password, remoteTargetDirectory, localFile, fileMode, DEFAULT_CONNECT_TIMEOUT, DEFAULT_KEX_TIMEOUT); } public static void scpTo(String host, int port, String user, File pemKeyFile, String password, String remoteTargetDirectory, byte[] data, String remoteFileName, String fileMode) throws Exception { scpTo(host, port, user, pemKeyFile, password, remoteTargetDirectory, data, remoteFileName, fileMode, DEFAULT_CONNECT_TIMEOUT, DEFAULT_KEX_TIMEOUT); } public static void scpTo(String host, int port, String user, File pemKeyFile, String password, String remoteTargetDirectory, String localFile, String fileMode, int connectTimeoutInMs, int kexTimeoutInMs) throws Exception { com.trilead.ssh2.Connection conn = null; com.trilead.ssh2.SCPClient scpClient = null; try { conn = new com.trilead.ssh2.Connection(host, port); conn.connect(null, connectTimeoutInMs, kexTimeoutInMs); if(pemKeyFile == null) { if(!conn.authenticateWithPassword(user, password)) { String msg = "Failed to authentication SSH user " + user + " on host " + host; s_logger.error(msg); throw new Exception(msg); } } else { if(!conn.authenticateWithPublicKey(user, pemKeyFile, password)) { String msg = "Failed to authentication SSH user " + user + " on host " + host; s_logger.error(msg); throw new Exception(msg); } } scpClient = conn.createSCPClient(); if(fileMode != null) scpClient.put(localFile, remoteTargetDirectory, fileMode); else scpClient.put(localFile, remoteTargetDirectory); } finally { if(conn != null) conn.close(); } } public static void scpTo(String host, int port, String user, File pemKeyFile, String password, String remoteTargetDirectory, byte[] data, String remoteFileName, String fileMode, int connectTimeoutInMs, int kexTimeoutInMs) throws Exception { com.trilead.ssh2.Connection conn = null; com.trilead.ssh2.SCPClient scpClient = null; try { conn = new com.trilead.ssh2.Connection(host, port); conn.connect(null, connectTimeoutInMs, kexTimeoutInMs); if(pemKeyFile == null) { if(!conn.authenticateWithPassword(user, password)) { String msg = "Failed to authentication SSH user " + user + " on host " + host; s_logger.error(msg); throw new Exception(msg); } } else { if(!conn.authenticateWithPublicKey(user, pemKeyFile, password)) { String msg = "Failed to authentication SSH user " + user + " on host " + host; s_logger.error(msg); throw new Exception(msg); } } scpClient = conn.createSCPClient(); if(fileMode != null) scpClient.put(data, remoteFileName, remoteTargetDirectory, fileMode); else scpClient.put(data, remoteFileName, remoteTargetDirectory); } finally { if(conn != null) conn.close(); } } public static Pair<Boolean, String> sshExecute(String host, int port, String user, File pemKeyFile, String password, String command, int connectTimeoutInMs, int kexTimeoutInMs, int waitResultTimeoutInMs) throws Exception { com.trilead.ssh2.Connection conn = null; com.trilead.ssh2.Session sess = null; try { conn = new com.trilead.ssh2.Connection(host, port); conn.connect(null, connectTimeoutInMs, kexTimeoutInMs); if(pemKeyFile == null) { if(!conn.authenticateWithPassword(user, password)) { String msg = "Failed to authentication SSH user " + user + " on host " + host; s_logger.error(msg); throw new Exception(msg); } } else { if(!conn.authenticateWithPublicKey(user, pemKeyFile, password)) { String msg = "Failed to authentication SSH user " + user + " on host " + host; s_logger.error(msg); throw new Exception(msg); } } sess = conn.openSession(); // There is a bug in Trilead library, wait a second before // starting a shell and executing commands, from http://spci.st.ewi.tudelft.nl/chiron/xref/nl/tudelft/swerl/util/SSHConnection.html Thread.sleep(1000); sess.execCommand(command); InputStream stdout = sess.getStdout(); InputStream stderr = sess.getStderr(); byte[] buffer = new byte[8192]; StringBuffer sbResult = new StringBuffer(); int currentReadBytes = 0; while (true) { if ((stdout.available() == 0) && (stderr.available() == 0)) { int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, waitResultTimeoutInMs); if ((conditions & ChannelCondition.TIMEOUT) != 0) { String msg = "Timed out in waiting SSH execution result"; s_logger.error(msg); throw new Exception(msg); } if ((conditions & ChannelCondition.EOF) != 0) { if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { break; } } } while (stdout.available() > 0) { currentReadBytes = stdout.read(buffer); sbResult.append(new String(buffer, 0, currentReadBytes)); } while (stderr.available() > 0) { currentReadBytes = stderr.read(buffer); sbResult.append(new String(buffer, 0, currentReadBytes)); } } String result = sbResult.toString(); if (sess.getExitStatus() != null && sess.getExitStatus().intValue() != 0) { s_logger.error("SSH execution of command " + command + " has an error status code in return. result output: " + result); return new Pair<Boolean, String>(false, result); } return new Pair<Boolean, String>(true, result); } finally { if(sess != null) sess.close(); if(conn != null) conn.close(); } } }