/******************************************************************************
* Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
* 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 com.vmware.bdd.ssh;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.PublicKey;
import java.util.concurrent.TimeUnit;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.connection.channel.direct.Session;
import net.schmizz.sshj.transport.verification.HostKeyVerifier;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
/**
* Created By xiaoliangl on 1/4/15.
*/
@Component
public class SshExecService {
private static final Logger LOGGER = Logger.getLogger(SshExecService.class);
private SSHClient sshClient;
public void exec(String host, int port, String userName, String[] cmds, int timeoutInSecond) {
sshClient = new SSHClient();
try {
sshClient.addHostKeyVerifier(new HostKeyVerifier() {
@Override
public boolean verify(String hostname, int port, PublicKey key) {
return true;
}
});
sshClient.connect(host, port);
sshClient.authPublickey(userName);
for (String cmd : cmds) {
exec(sshClient, cmd, timeoutInSecond);
}
} catch (IOException e) {
throw new SshExecException("failed connect via ssh", e);
} finally {
try {
sshClient.close();
} catch (IOException e) {
//do nothing
}
}
}
private String readFromStream(InputStream in) throws IOException {
StringBuffer result = new StringBuffer();
BufferedInputStream inputStream = new BufferedInputStream(in);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
while(bufferedReader.ready()) {
result.append(bufferedReader.readLine());
}
return result.toString();
}
protected void exec(SSHClient client, String cmd, int timeoutInSecond) throws IOException {
LOGGER.debug("exec remote cmd via ssh: " + cmd);
Session session = null;
try {
session = client.startSession();
session.allocateDefaultPTY();
Session.Command command = session.exec(cmd);
LOGGER.debug(IOUtils.readFully(command.getInputStream()).toString());
command.join(timeoutInSecond, TimeUnit.SECONDS);
int exitStatus = command.getExitStatus();
LOGGER.debug("cmd exit status: " + exitStatus);
if(exitStatus != 0) {
StringBuilder output = new StringBuilder();
output.append(readFromStream(command.getErrorStream()));
output.append(readFromStream(command.getInputStream()));
//@TODO improve error handling
throw new SshExecException("exec failed with exit code: " + exitStatus + output.toString(), null);
}
LOGGER.info("cmd exec successfully!");
} catch (IOException e) {
throw new SshExecException("failed exec", e);
} finally {
if (session != null) {
try {
session.close();
} catch (IOException e) {
//do nothing
}
}
}
}
}