package org.zstack.utils.ssh; import org.apache.commons.io.FileUtils; import org.zstack.utils.DebugUtils; import org.zstack.utils.ShellResult; import org.zstack.utils.ShellUtils; import org.zstack.utils.Utils; import org.zstack.utils.logging.CLogger; import org.zstack.utils.path.PathUtil; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import static org.zstack.utils.StringDSL.ln; import static org.zstack.utils.StringDSL.s; /** * Created by frank on 12/5/2015. */ public class SshShell { private static final CLogger logger = Utils.getLogger(SshShell.class); private String hostname; private String username; private String password; private String privateKeyFile; private int port = 22; private void checkParams() { DebugUtils.Assert(hostname != null, "hostname cannot be null"); DebugUtils.Assert(username != null, "username cannot be null"); DebugUtils.Assert(password != null || privateKeyFile != null, "password and privateKeyFile must have at least one set"); } public SshResult runCommand(String cmd) { checkParams(); String ssh; File tempPasswordFile = null; try { if (privateKeyFile != null) { ssh = String.format("ssh -i %s -o UserKnownHostsFile=/dev/null -o PasswordAuthentication=no -o StrictHostKeyChecking=no -p %s %s@%s '%s'", privateKeyFile, port, username, hostname, cmd); } else { tempPasswordFile = File.createTempFile("zstack", "tmp"); FileUtils.writeStringToFile(tempPasswordFile, password); ssh = String.format("sshpass -f%s ssh -o UserKnownHostsFile=/dev/null -o PubkeyAuthentication=no -o StrictHostKeyChecking=no -p %s %s@%s '%s'", tempPasswordFile.getAbsolutePath(), port, username, hostname, cmd); } if (logger.isTraceEnabled()) { logger.trace(String.format("[ssh shell]: %s", ssh)); } ShellResult ret = ShellUtils.runAndReturn(ssh); SshResult sret = new SshResult(); sret.setCommandToExecute(cmd); sret.setReturnCode(ret.getRetCode()); sret.setStderr(ret.getStderr()); sret.setStdout(ret.getStdout()); if (sret.getReturnCode() == 255 && privateKeyFile != null) { sret.setSshFailure(true); } else if (sret.getReturnCode() == 5 && privateKeyFile == null) { sret.setSshFailure(true); } return sret; } catch (Exception e) { throw new RuntimeException(e); } finally { if (tempPasswordFile != null) { tempPasswordFile.delete(); } } } public SshResult runScript(String script) { checkParams(); String ssh; File tempPasswordFile = null; try { if (privateKeyFile != null) { ssh = ln( "ssh -i {0} -o UserKnownHostsFile=/dev/null -o PasswordAuthentication=no -o StrictHostKeyChecking=no -p {1} -T {2}@{3} << 'EOF'", "s=`mktemp`", "cat << 'EOT' > $s", "{4}", "EOT", "bash $s", "ret=$?", "rm -f $s", "exit $ret", "EOF" ).format(privateKeyFile, port, username, hostname, script); } else { tempPasswordFile = File.createTempFile("zstack", "tmp"); FileUtils.writeStringToFile(tempPasswordFile, password); ssh = ln( "sshpass -f{0} ssh -o UserKnownHostsFile=/dev/null -o PubkeyAuthentication=no -o StrictHostKeyChecking=no -p {1} -T {2}@{3} << 'EOF'", "s=`mktemp`", "cat << 'EOT' > $s", "{4}", "EOT", "bash $s", "ret=$?", "rm -f $s", "exit $ret", "EOF" ).format(tempPasswordFile.getAbsolutePath(), port, username, hostname, script); } if (logger.isTraceEnabled()) { logger.trace(String.format("[ssh shell]: %s", ssh)); } ShellResult ret = ShellUtils.runAndReturn(ssh); SshResult sret = new SshResult(); sret.setCommandToExecute(script); sret.setReturnCode(ret.getRetCode()); sret.setStderr(ret.getStderr()); sret.setStdout(ret.getStdout()); if (sret.getReturnCode() == 255 && privateKeyFile != null) { sret.setSshFailure(true); } else if (sret.getReturnCode() == 5 && privateKeyFile == null) { sret.setSshFailure(true); } return sret; } catch (Exception e) { throw new RuntimeException(e); } finally { if (tempPasswordFile != null) { tempPasswordFile.delete(); } } } public SshResult runScriptWithToken(String scriptName, Map token) { String scriptPath = PathUtil.findFileOnClassPath(scriptName, true).getAbsolutePath(); if (token == null) { token = new HashMap(); } String contents = null; try { contents = FileUtils.readFileToString(new File(scriptPath)); } catch (IOException e) { throw new RuntimeException(e); } String script = s(contents).formatByMap(token); return runScript(script); } public String getHostname() { return hostname; } public void setHostname(String hostname) { this.hostname = hostname; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getPrivateKeyFile() { return privateKeyFile; } public void setPrivateKeyFile(String privateKeyFile) { this.privateKeyFile = privateKeyFile; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } }