/*
* ProActive Parallel Suite(TM):
* The Open Source library for parallel and distributed
* Workflows & Scheduling, Orchestration, Cloud Automation
* and Big Data Analysis on Enterprise Grids & Clouds.
*
* Copyright (c) 2007 - 2017 ActiveEon
* Contact: contact@activeeon.com
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation: version 3 of
* the License.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* If needed, contact us to obtain a release under GPL Version 2 or 3
* or a different license than the AGPL.
*/
package org.ow2.proactive.resourcemanager.nodesource.infrastructure;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import org.apache.log4j.Logger;
import org.objectweb.proactive.core.config.CentralPAPropertyRepository;
import org.objectweb.proactive.core.ssh.SSHClient;
import org.objectweb.proactive.utils.OperatingSystem;
import org.ow2.proactive.resourcemanager.core.properties.PAResourceManagerProperties;
/**
* A class where static utility methods are welcome
*/
public class Utils {
private static final Logger logger = Logger.getLogger(Utils.class);
/**
* Execute a specific command on a remote host through SSH
*
* @param host the remote host on which to execute the command
* @param cmd the command to execute on the remote host
* @param sshOptions the options that will be passed to the ssh command
* @return the Process in which the SSH command is running;
* NOT the actual process on the remote host, although it can be used
* to read the remote process' output.
* @throws IOException SSH command execution failed
*/
public static Process runSSHCommand(InetAddress host, String cmd, String sshOptions) throws IOException {
// build the SSH command using ProActive's SSH client:
// will recover keys/identities if they exist
String sshCmd = null;
StringBuilder sb = new StringBuilder();
//building path to java executable
String javaHome = System.getProperty("java.home");
if (javaHome.contains(" ")) {
switch (OperatingSystem.getOperatingSystem()) {
case unix:
javaHome = javaHome.replace(" ", "\\ ");
break;
case windows:
sb.append("\"");
break;
}
}
sb.append(javaHome);
sb.append(File.separator);
sb.append("bin");
sb.append(File.separator);
sb.append("java");
if (javaHome.contains(" ")) {
switch (OperatingSystem.getOperatingSystem()) {
case windows:
sb.append("\"");
break;
}
}
//building classpath
sb.append(" -cp ");
final String rmHome = PAResourceManagerProperties.RM_HOME.getValueAsString().trim();
sb.append("\"");
sb.append(rmHome);
sb.append(File.separator);
sb.append("dist");
sb.append(File.separator);
sb.append("lib");
sb.append(File.separator);
sb.append("*");
sb.append("\"");
sb.append(" ");
//mandatory property
//exe's name
sb.append(SSHClient.class.getName());
//SSH options supplied by user from cli|gui
sb.append(" ");
sb.append(sshOptions);
sb.append(" ");
//target machine
sb.append(host.getHostName());
//the command
sb.append(" \"");
sb.append(cmd);
sb.append("\"");
sshCmd = sb.toString();
logger.info("Executing SSH command: '" + sshCmd + "'");
Process p = null;
// start the SSH command in a new process and not a thread:
// easier killing, prevents the client from polluting stdout
switch (OperatingSystem.getOperatingSystem()) {
case unix:
p = Runtime.getRuntime().exec(new String[] { CentralPAPropertyRepository.PA_GCMD_UNIX_SHELL.getValue(),
"-c", sshCmd });
break;
case windows:
p = Runtime.getRuntime().exec(sshCmd);
break;
}
return p;
}
/**
* Extracts process errput and returns it
* @param p the remote process frow which one errput will be extracted.
* @return the remote process' errput
*/
static String extractProcessErrput(Process p) {
BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
StringBuilder sb = new StringBuilder();
String line = null;
try {
String lf = System.lineSeparator();
while (br.ready()) {
if ((line = br.readLine()) != null) {
sb.append(line);
sb.append(lf);
}
}
} catch (IOException e) {
sb.append("Cannot extract process errput");
} finally {
try {
br.close();
} catch (IOException e) {
logger.debug("Cannot close process error stream", e);
}
}
return sb.toString();
}
/**
* Extracts process output and returns it
* @param p the remote process frow which one output will be extracted.
* @return the remote process' output
*/
static String extractProcessOutput(Process p) {
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
try {
String lf = System.lineSeparator();
while (br.ready()) {
if ((line = br.readLine()) != null) {
sb.append(line);
sb.append(lf);
}
}
} catch (IOException e) {
sb.append("Cannot extract process output");
} finally {
try {
br.close();
} catch (IOException e) {
logger.debug("Cannot close process output stream", e);
}
}
return sb.toString();
}
/**
* Consumes everything written by a stream.
*/
public static void consumeProcessStream(InputStream stream) {
BufferedReader br = new BufferedReader(new InputStreamReader(stream));
try {
while (br.readLine() != null) {
br.readLine();
}
} catch (IOException e) {
} finally {
try {
br.close();
} catch (IOException e) {
}
}
}
}