Skip to content
This repository has been archived by the owner on Jul 11, 2022. It is now read-only.

Commit

Permalink
Bug 1226413 - Bundle rhq:handover can hang when management interface is
Browse files Browse the repository at this point in the history
using SSL and jboss-cli does not yet trust certs

Fixed potential OOM caused by EAP 6.4.x which is constantly filling stdout
when waiting for user to accept ssl cert.

Fixed cleaning up java process (executed dummy CLI command), which could
survive, it's parent because it got detached from it.

(cherry picked from commit e4c7c18)
Signed-off-by: Libor Zoubek <lzoubek@redhat.com>
  • Loading branch information
Libor Zoubek committed Jul 3, 2015
1 parent c58aedd commit f5cc61f
Showing 1 changed file with 52 additions and 21 deletions.
Expand Up @@ -26,6 +26,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
Expand All @@ -36,6 +37,7 @@
import org.rhq.core.system.OperatingSystemType;
import org.rhq.core.system.ProcessExecution;
import org.rhq.core.system.ProcessExecutionResults;
import org.rhq.core.system.ProcessInfo;
import org.rhq.core.system.SystemInfo;
import org.rhq.core.util.file.FileUtil;
import org.rhq.modules.plugins.jbossas7.helper.ServerPluginConfiguration;
Expand All @@ -62,6 +64,7 @@ public final class ServerControl {

private long waitTime;
private boolean killOnTimeout;
private boolean ignoreOutput;

private ServerControl(Configuration pluginConfiguration, AS7Mode serverMode, SystemInfo systemInfo) {
this.pluginConfiguration = pluginConfiguration;
Expand Down Expand Up @@ -100,6 +103,11 @@ public ServerControl killingOnTimeout(boolean kill) {
return this;
}

private ServerControl ignoreOutput() {
this.ignoreOutput = true;
return this;
}

/**
* @return lifecycle methods on the server.
*/
Expand Down Expand Up @@ -137,10 +145,11 @@ private ProcessExecutionResults execute(String prefix, File executable, String..
// When running on Windows 9x, standalone.bat and domain.bat need the cwd to be the AS bin dir in order to find
// standalone.bat.conf and domain.bat.conf respectively.
processExecution.setWorkingDirectory(startScriptFile.getParent());
processExecution.setCaptureOutput(true);
processExecution.setWaitForCompletion(MAX_PROCESS_WAIT_TIME);
processExecution.setKillOnTimeout(false);

processExecution.setCaptureOutput(!ignoreOutput);

if (waitTime > 0) {
processExecution.setWaitForCompletion(waitTime);
} else if (waitTime < 0) {
Expand Down Expand Up @@ -207,6 +216,7 @@ public final class Cli {
*/
private boolean checkCertificate = true;


Cli() {
// When running the CLI on Windows, make sure no "pause" message is shown after script execution
// Otherwise the CLI process will just keep running so we'll never get the exit code
Expand Down Expand Up @@ -235,38 +245,47 @@ public Cli disconnected(boolean disconnected) {
* CLI executions would hang and wait for input, null otherwise.
*/
private ProcessExecutionResults detectCertificateApprovalRequired() {
// uniquely identify our dummy process so we can find it later on
String rhqPid = UUID.randomUUID().toString();
ProcessExecutionResults result = ServerControl.onServer(pluginConfiguration, serverMode, systemInfo)
.killingOnTimeout(true)
.waitingFor(10 * 1000L)
.ignoreOutput()// avoid potential OOM https://bugzilla.redhat.com/show_bug.cgi?id=1238263
.cli()
.disconnected(false)
.dontCheckCertificate() // avoid stack overflow
.executeCliCommand(":whoami");
.executeCliCommand(":whoami", "-Drhq.as7.plugin.exec-id=" + rhqPid);

if (result.getExitCode() == null) { // process was killed because of timeout (killingOnTimeout(true))
// we're interested in first 7 lines only (CLI prints SSL certificate details)
String[] output = result.getCapturedOutput().split("\n", 7);
if (output.length > 0
&& output[0].startsWith("Unable to connect due to unrecognised server certificate")) {
int strip = Math.min(7, output.length);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < strip; i++) {
sb.append(output[i] + "\n");

// it would be better if we parsed process output and make sure it did not end up within 10 seconds
// because it's waiting for input. But the fact, that the :whoami command did not end up within 10 seconds
// is enough to know, that CLI *is* waiting for user to accept certificate

// there is an issue with killing EAP CLI process. we've enabled killingOnTimeout, but only
// shell wrapper script is affected and it's child java process survives.
// Find the java process and send SIGKILL
String piql = "process|basename|match=^java.*,arg|-Drhq.as7.plugin.exec-id|match=" + rhqPid;
List<ProcessInfo> processes = systemInfo.getProcesses(piql);
if (processes.size() > 0) {
ProcessInfo pi = processes.get(0);
try {
LOG.debug("Killing " + pi.getPid());
pi.kill("KILL");
} catch (Exception e) {
LOG.error("Unable to kill process", e);
}
return new SslCheckRequiredExecutionResults(result, sb.toString());
} else {
LOG.warn("We were unable to locate testing jboss-cli java process to clean it up, you may need to kill it manually");
}

return new SslCheckRequiredExecutionResults(result,
"Unable to connect due to unrecognised server certificate. Server's certificate needs to be manually accepted by user.");
}
return null;
}

/**
* Runs (a series of) CLI commands against the server.
* The commands are separated by either a newline or a comma (or a mix thereof).
*
* @param commands the commands to execute in order
* @return the execution results
*/
public ProcessExecutionResults executeCliCommand(String commands) {
private ProcessExecutionResults executeCliCommand(String commands, String additionalArg) {
File executable = new File("bin", serverMode.getCliScriptFileName());
String connect = disconnected ? null : "--connect";
boolean local = serverPluginConfig.isNativeLocalAuth();
Expand All @@ -285,12 +304,24 @@ public ProcessExecutionResults executeCliCommand(String commands) {
}

if (systemInfo.getOperatingSystemType() != OperatingSystemType.WINDOWS) {
return execute(null, executable, connect, commands, user, password, controller);
return execute(null, executable, connect, commands, user, password, controller, additionalArg);
}
WinCliHelper cliHelper = new WinCliHelper(executable, connect, commands, user, password, controller);
WinCliHelper cliHelper = new WinCliHelper(executable, connect, commands, user, password, controller,
additionalArg);
return cliHelper.execute();
}

/**
* Runs (a series of) CLI commands against the server.
* The commands are separated by either a newline or a comma (or a mix thereof).
*
* @param commands the commands to execute in order
* @return the execution results
*/
public ProcessExecutionResults executeCliCommand(String commands) {
return executeCliCommand(commands, null);
}

/**
* Runs the provided script against the server.
*
Expand Down

0 comments on commit f5cc61f

Please sign in to comment.