modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java
| 1057 ++++------
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerPluginConfigurationProperties.java
| 2
modules/plugins/jboss-as-5/src/main/resources/META-INF/rhq-plugin.xml
| 12
3 files changed, 526 insertions(+), 545 deletions(-)
New commits:
commit 2b2bb3e381517867fc6526c406b9a187ed47c9fe
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Wed Mar 30 16:39:07 2011 -0400
BZ-689992: adding customizing for max start/stop WAIT_MAX times.
diff --git
a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java
b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java
index 5f7ae4f..1761b6c 100644
---
a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java
+++
b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java
@@ -34,7 +34,9 @@ import org.mc4j.ems.connection.EmsConnection;
import org.mc4j.ems.connection.bean.EmsBean;
import org.mc4j.ems.connection.bean.operation.EmsOperation;
import org.mc4j.ems.connection.bean.parameter.EmsParameter;
+
import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
import org.rhq.core.pluginapi.operation.OperationResult;
@@ -51,108 +53,105 @@ import org.rhq.core.system.SystemInfo;
* @author Jay Shaughnessy
*/
public class ApplicationServerOperationsDelegate {
- /**
- * max amount of time to wait for server to show as unavailable after
- * executing stop - in milliseconds
- */
- private static final long STOP_WAIT_MAX = 1000L * 150; // 2.5 minutes
-
- /**
- * amount of time to wait between availability checks when performing a stop
- * - in milliseconds
- */
- private static final long STOP_WAIT_INTERVAL = 1000L * 5; // 5 seconds
-
- /**
- * amount of time to wait for stop to complete after the loop that checks
- * for DOWN availability terminates - in milliseconds
- */
- private static final long STOP_WAIT_FINAL = 1000L * 30; // 30 seconds
-
- /** max amount of time to wait for start to complete - in milliseconds */
- private static final long START_WAIT_MAX = 1000L * 300; // 5 minutes
-
- /**
- * amount of time to wait between availability checks when performing a
- * start - in milliseconds
- */
- private static final long START_WAIT_INTERVAL = 1000L * 5; // 5 seconds
-
- private final Log log = LogFactory
- .getLog(ApplicationServerOperationsDelegate.class);
-
- private static final String SEPARATOR = "\n-----------------------\n";
-
- static final String DEFAULT_START_SCRIPT = "bin" + File.separator +
"run."
- + ((File.separatorChar == '/') ? "sh" : "bat");
- static final String DEFAULT_SHUTDOWN_SCRIPT = "bin" + File.separator
- + "shutdown." + ((File.separatorChar == '/') ? "sh" :
"bat");
-
- /**
- * Server component against which the operations are being performed.
- */
- private ApplicationServerComponent serverComponent;
-
- private File configPath;
-
- // Constructors --------------------------------------------
-
- public ApplicationServerOperationsDelegate(
- ApplicationServerComponent serverComponent) {
- this.serverComponent = serverComponent;
- }
-
- // Public --------------------------------------------
-
- /**
- * Performs the specified operation. The result of the operation will be
- * indicated in the return. If there is an error, an
- * <code>RuntimeException</code> will be thrown.
- *
- * @param operation
- * the operation to perform
- * @param parameters
- * parameters to the operation call
- *
- * @return if successful, the result object will contain a success message
- *
- * @throws RuntimeException
- * if any errors occur while trying to perform the operation
- */
- public OperationResult invoke(
- ApplicationServerSupportedOperations operation,
- Configuration parameters) throws InterruptedException {
- OperationResult result = null;
-
- switch (operation) {
- case START: {
- result = start();
- break;
- }
- case SHUTDOWN: {
- result = shutDown();
- break;
- }
- case RESTART: {
- result = restart();
- break;
- }
- }
-
- return result;
- }
-
- // Private --------------------------------------------
-
- /**
- * Starts the underlying AS server.
- *
- * @return success message if no errors are encountered
- * @throws InterruptedException
- * if the plugin container stops this operation while its
- * executing
- */
- private OperationResult start() throws InterruptedException {
+ /**
+ * max amount of time to wait for server to show as unavailable after
+ * executing stop - in milliseconds
+ */
+ private static long STOP_WAIT_MAX = 1000L * 150; // 2.5 minutes
+
+ /**
+ * amount of time to wait between availability checks when performing a stop
+ * - in milliseconds
+ */
+ private static final long STOP_WAIT_INTERVAL = 1000L * 5; // 5 seconds
+
+ /**
+ * amount of time to wait for stop to complete after the loop that checks
+ * for DOWN availability terminates - in milliseconds
+ */
+ private static final long STOP_WAIT_FINAL = 1000L * 30; // 30 seconds
+
+ /** max amount of time to wait for start to complete - in milliseconds */
+ private static long START_WAIT_MAX = 1000L * 300; // 5 minutes
+
+ /**
+ * amount of time to wait between availability checks when performing a
+ * start - in milliseconds
+ */
+ private static final long START_WAIT_INTERVAL = 1000L * 5; // 5 seconds
+
+ private final Log log =
LogFactory.getLog(ApplicationServerOperationsDelegate.class);
+
+ private static final String SEPARATOR = "\n-----------------------\n";
+
+ static final String DEFAULT_START_SCRIPT = "bin" + File.separator +
"run."
+ + ((File.separatorChar == '/') ? "sh" : "bat");
+ static final String DEFAULT_SHUTDOWN_SCRIPT = "bin" + File.separator +
"shutdown."
+ + ((File.separatorChar == '/') ? "sh" : "bat");
+
+ /**
+ * Server component against which the operations are being performed.
+ */
+ private ApplicationServerComponent serverComponent;
+
+ private File configPath;
+
+ // Constructors --------------------------------------------
+
+ public ApplicationServerOperationsDelegate(ApplicationServerComponent
serverComponent) {
+ this.serverComponent = serverComponent;
+ }
+
+ // Public --------------------------------------------
+
+ /**
+ * Performs the specified operation. The result of the operation will be
+ * indicated in the return. If there is an error, an
+ * <code>RuntimeException</code> will be thrown.
+ *
+ * @param operation
+ * the operation to perform
+ * @param parameters
+ * parameters to the operation call
+ *
+ * @return if successful, the result object will contain a success message
+ *
+ * @throws RuntimeException
+ * if any errors occur while trying to perform the operation
+ */
+ public OperationResult invoke(ApplicationServerSupportedOperations operation,
Configuration parameters)
+ throws InterruptedException {
+ OperationResult result = null;
+
+ switch (operation) {
+ case START: {
+ result = start();
+ break;
+ }
+ case SHUTDOWN: {
+ result = shutDown();
+ break;
+ }
+ case RESTART: {
+ result = restart();
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ // Private --------------------------------------------
+
+ /**
+ * Starts the underlying AS server.
+ *
+ * @return success message if no errors are encountered
+ * @throws InterruptedException
+ * if the plugin container stops this operation while its
+ * executing
+ */
+ private OperationResult start() throws InterruptedException {
AvailabilityType avail = this.serverComponent.getAvailability();
if (avail == AvailabilityType.UP) {
OperationResult result = new OperationResult();
@@ -161,25 +160,20 @@ public class ApplicationServerOperationsDelegate {
}
Configuration pluginConfig =
serverComponent.getResourceContext().getPluginConfiguration();
File startScriptFile = getStartScriptPath();
- validateScriptFile(
- startScriptFile,
- ApplicationServerPluginConfigurationProperties.START_SCRIPT_CONFIG_PROP);
+ validateScriptFile(startScriptFile,
ApplicationServerPluginConfigurationProperties.START_SCRIPT_CONFIG_PROP);
// The optional command prefix (e.g. sudo or nohup).
- String prefix = pluginConfig
- .getSimple(
- ApplicationServerPluginConfigurationProperties.SCRIPT_PREFIX_CONFIG_PROP)
- .getStringValue();
- String configName = getConfigurationSet();
- String bindAddress = pluginConfig.getSimpleValue(
- ApplicationServerPluginConfigurationProperties.BIND_ADDRESS, null);
+ String prefix = pluginConfig
+
.getSimple(ApplicationServerPluginConfigurationProperties.SCRIPT_PREFIX_CONFIG_PROP).getStringValue();
+ String configName = getConfigurationSet();
+ String bindAddress =
pluginConfig.getSimpleValue(ApplicationServerPluginConfigurationProperties.BIND_ADDRESS,
+ null);
- ProcessExecution processExecution;
- if (prefix == null || prefix.replaceAll("\\s",
"").equals("")) {
- // Prefix is either null or contains ONLY whitespace characters.
+ ProcessExecution processExecution;
+ if (prefix == null || prefix.replaceAll("\\s",
"").equals("")) {
+ // Prefix is either null or contains ONLY whitespace characters.
- processExecution = ProcessExecutionUtility
- .createProcessExecution(startScriptFile);
+ processExecution =
ProcessExecutionUtility.createProcessExecution(startScriptFile);
processExecution.getArguments().add("-c");
processExecution.getArguments().add(configName);
@@ -188,111 +182,103 @@ public class ApplicationServerOperationsDelegate {
processExecution.getArguments().add("-b");
processExecution.getArguments().add(bindAddress);
}
- } else {
- // The process execution should be tied to the process represented
- // as the prefix. If there are any other
- // tokens in the prefix, consider them arguments to the prefix
- // process.
- StringTokenizer prefixTokenizer = new StringTokenizer(prefix);
- String processName = prefixTokenizer.nextToken();
- File prefixProcess = new File(processName);
-
- processExecution = ProcessExecutionUtility
- .createProcessExecution(prefixProcess);
-
- while (prefixTokenizer.hasMoreTokens()) {
- String prefixArgument = prefixTokenizer.nextToken();
- processExecution.getArguments().add(prefixArgument);
- }
-
- // Add the AS start script and its options as a single argument to the prefix
command.
- String startScriptArgument = startScriptFile.getAbsolutePath();
- startScriptArgument += " -c " + configName;
- if (bindAddress != null) {
- startScriptArgument += " -b " + bindAddress;
- }
- processExecution.getArguments().add(startScriptArgument);
- }
-
- initProcessExecution(processExecution, startScriptFile);
-
- long start = System.currentTimeMillis();
- if (log.isDebugEnabled()) {
- log.debug("About to execute the following process: [" + processExecution +
"]");
- }
- SystemInfo systemInfo = serverComponent.getResourceContext().getSystemInformation();
- ProcessExecutionResults results = systemInfo
- .executeProcess(processExecution);
- logExecutionResults(results);
-
- if (results.getError() == null) {
- avail = waitForServerToStart(start);
- } else {
- log.error(
- "Error from process execution while starting the AS instance. Exit code
["
- + results.getExitCode() + "]", results.getError());
- avail = this.serverComponent.getAvailability();
- }
-
- // If, after the loop, the Server is still down, consider the start to be a failure.
- OperationResult result;
+ } else {
+ // The process execution should be tied to the process represented
+ // as the prefix. If there are any other
+ // tokens in the prefix, consider them arguments to the prefix
+ // process.
+ StringTokenizer prefixTokenizer = new StringTokenizer(prefix);
+ String processName = prefixTokenizer.nextToken();
+ File prefixProcess = new File(processName);
+
+ processExecution =
ProcessExecutionUtility.createProcessExecution(prefixProcess);
+
+ while (prefixTokenizer.hasMoreTokens()) {
+ String prefixArgument = prefixTokenizer.nextToken();
+ processExecution.getArguments().add(prefixArgument);
+ }
+
+ // Add the AS start script and its options as a single argument to the prefix
command.
+ String startScriptArgument = startScriptFile.getAbsolutePath();
+ startScriptArgument += " -c " + configName;
+ if (bindAddress != null) {
+ startScriptArgument += " -b " + bindAddress;
+ }
+ processExecution.getArguments().add(startScriptArgument);
+ }
+
+ initProcessExecution(processExecution, startScriptFile);
+
+ long start = System.currentTimeMillis();
+ if (log.isDebugEnabled()) {
+ log.debug("About to execute the following process: [" +
processExecution + "]");
+ }
+ SystemInfo systemInfo =
serverComponent.getResourceContext().getSystemInformation();
+ ProcessExecutionResults results = systemInfo.executeProcess(processExecution);
+ logExecutionResults(results);
+
+ if (results.getError() == null) {
+ avail = waitForServerToStart(start);
+ } else {
+ log.error("Error from process execution while starting the AS instance.
Exit code ["
+ + results.getExitCode() + "]", results.getError());
+ avail = this.serverComponent.getAvailability();
+ }
+
+ // If, after the loop, the Server is still down, consider the start to be a
failure.
+ OperationResult result;
if (avail == AvailabilityType.DOWN) {
- result = new OperationResult();
+ result = new OperationResult();
result.setErrorMessage("The server failed to start: " +
results.getCapturedOutput());
- } else {
- result = new OperationResult("The server has been started.");
- }
+ } else {
+ result = new OperationResult("The server has been started.");
+ }
return result;
- }
-
- private String getConfigurationSet() {
- Configuration pluginConfig =
serverComponent.getResourceContext().getPluginConfiguration();
- configPath = resolvePathRelativeToHomeDir(getRequiredPropertyValue(
- pluginConfig,
- ApplicationServerPluginConfigurationProperties.SERVER_HOME_DIR));
-
- if (!configPath.exists()) {
- throw new InvalidPluginConfigurationException(
- "Configuration path '" + configPath + "' does not
exist.");
- }
- return pluginConfig.getSimpleValue(
- ApplicationServerPluginConfigurationProperties.SERVER_NAME,
- configPath.getName());
- }
-
- private void initProcessExecution(ProcessExecution processExecution,
- File scriptFile) {
- // NOTE: For both run.bat and shutdown.bat, the current working dir must
- // be set to the script's parent dir
- // (e.g. ${JBOSS_HOME}/bin) for the script to work.
- processExecution.setWorkingDirectory(scriptFile.getParent());
-
- // Both scripts require the JAVA_HOME env var to be set.
- File javaHomeDir = getJavaHomePath();
- if (javaHomeDir == null) {
- throw new IllegalStateException(
- "The '"
- + ApplicationServerPluginConfigurationProperties.JAVA_HOME
- + "' connection property must be set in order to start the application
server or to stop it via script.");
- }
-
- validateJavaHomePathProperty();
- processExecution.getEnvironmentVariables().put("JAVA_HOME",
- javaHomeDir.getPath());
-
- processExecution.setCaptureOutput(true);
- processExecution.setWaitForCompletion(1000L); // 1 second // TODO:
- // Should we wait longer than one second?
- processExecution.setKillOnTimeout(false);
- }
-
- /**
- * Shuts down the server by dispatching to shutdown via script or JMX. Waits
- * until the server is down.
- *
- * @return The result of the shutdown operation - is successful
- */
- private OperationResult shutDown() {
+ }
+
+ private String getConfigurationSet() {
+ Configuration pluginConfig =
serverComponent.getResourceContext().getPluginConfiguration();
+ configPath = resolvePathRelativeToHomeDir(getRequiredPropertyValue(pluginConfig,
+ ApplicationServerPluginConfigurationProperties.SERVER_HOME_DIR));
+
+ if (!configPath.exists()) {
+ throw new InvalidPluginConfigurationException("Configuration path
'" + configPath + "' does not exist.");
+ }
+ return
pluginConfig.getSimpleValue(ApplicationServerPluginConfigurationProperties.SERVER_NAME,
configPath
+ .getName());
+ }
+
+ private void initProcessExecution(ProcessExecution processExecution, File scriptFile)
{
+ // NOTE: For both run.bat and shutdown.bat, the current working dir must
+ // be set to the script's parent dir
+ // (e.g. ${JBOSS_HOME}/bin) for the script to work.
+ processExecution.setWorkingDirectory(scriptFile.getParent());
+
+ // Both scripts require the JAVA_HOME env var to be set.
+ File javaHomeDir = getJavaHomePath();
+ if (javaHomeDir == null) {
+ throw new IllegalStateException(
+ "The '"
+ + ApplicationServerPluginConfigurationProperties.JAVA_HOME
+ + "' connection property must be set in order to start the
application server or to stop it via script.");
+ }
+
+ validateJavaHomePathProperty();
+ processExecution.getEnvironmentVariables().put("JAVA_HOME",
javaHomeDir.getPath());
+
+ processExecution.setCaptureOutput(true);
+ processExecution.setWaitForCompletion(1000L); // 1 second // TODO:
+ // Should we wait longer than one second?
+ processExecution.setKillOnTimeout(false);
+ }
+
+ /**
+ * Shuts down the server by dispatching to shutdown via script or JMX. Waits
+ * until the server is down.
+ *
+ * @return The result of the shutdown operation - is successful
+ */
+ private OperationResult shutDown() {
AvailabilityType avail = this.serverComponent.getAvailability();
if (avail == AvailabilityType.DOWN) {
OperationResult result = new OperationResult();
@@ -301,339 +287,320 @@ public class ApplicationServerOperationsDelegate {
}
Configuration pluginConfig =
serverComponent.getResourceContext().getPluginConfiguration();
- ApplicationServerShutdownMethod shutdownMethod = Enum
- .valueOf(
- ApplicationServerShutdownMethod.class,
- pluginConfig
- .getSimple(
- ApplicationServerPluginConfigurationProperties.SHUTDOWN_METHOD_CONFIG_PROP)
- .getStringValue());
- String resultMessage = ApplicationServerShutdownMethod.JMX
- .equals(shutdownMethod) ? shutdownViaJmx()
- : shutdownViaScript();
+ ApplicationServerShutdownMethod shutdownMethod =
Enum.valueOf(ApplicationServerShutdownMethod.class,
+
pluginConfig.getSimple(ApplicationServerPluginConfigurationProperties.SHUTDOWN_METHOD_CONFIG_PROP)
+ .getStringValue());
+ String resultMessage = ApplicationServerShutdownMethod.JMX.equals(shutdownMethod)
? shutdownViaJmx()
+ : shutdownViaScript();
avail = waitForServerToShutdown();
- OperationResult result;
+ OperationResult result;
if (avail == AvailabilityType.UP) {
- result = new OperationResult();
+ result = new OperationResult();
result.setErrorMessage("The server failed to shut down.");
- } else {
- return new OperationResult(resultMessage);
- }
+ } else {
+ return new OperationResult(resultMessage);
+ }
return result;
- }
-
- /**
- * Shuts down the AS server using a shutdown script.
- *
- * @return success message if no errors are encountered
- */
- private String shutdownViaScript() {
- File shutdownScriptFile = getShutdownScriptPath();
- validateScriptFile(
- shutdownScriptFile,
- ApplicationServerPluginConfigurationProperties.SHUTDOWN_SCRIPT_CONFIG_PROP);
- Configuration pluginConfig =
serverComponent.getResourceContext().getPluginConfiguration();
- String prefix = pluginConfig
- .getSimple(
- ApplicationServerPluginConfigurationProperties.SCRIPT_PREFIX_CONFIG_PROP)
- .getStringValue();
- ProcessExecution processExecution = ProcessExecutionUtility
- .createProcessExecution(prefix, shutdownScriptFile);
-
- initProcessExecution(processExecution, shutdownScriptFile);
-
- String server = pluginConfig.getSimple(
- ApplicationServerPluginConfigurationProperties.NAMING_URL)
- .getStringValue();
- if (server != null) {
- processExecution.getArguments().add("--server=" + server);
- }
-
- String user = pluginConfig.getSimple(
- ApplicationServerComponent.PRINCIPAL_CONFIG_PROP)
- .getStringValue();
- if (user != null) {
- processExecution.getArguments().add("--user=" + user);
- }
-
- String password = pluginConfig.getSimple(
- ApplicationServerComponent.CREDENTIALS_CONFIG_PROP)
- .getStringValue();
- if (password != null) {
- processExecution.getArguments().add("--password=" + password);
- }
-
- processExecution.getArguments().add("--shutdown");
-
- /*
- * This tells shutdown.bat not to call the Windows PAUSE command, which
- * would cause the script to hang indefinitely waiting for input.
- * noinspection ConstantConditions
- */
- processExecution.getEnvironmentVariables().put("NOPAUSE", "1");
-
- if (log.isDebugEnabled()) {
- log.debug("About to execute the following process: ["
- + processExecution + "]");
- }
- SystemInfo systemInfo = serverComponent.getResourceContext().getSystemInformation();
- ProcessExecutionResults results = systemInfo
- .executeProcess(processExecution);
- logExecutionResults(results);
-
- if (results.getError() != null) {
- throw new RuntimeException(
- "Error executing shutdown script while stopping AS instance. Exit code ["
- + results.getExitCode() + "]", results.getError());
- }
-
- return "The server has been shut down.";
- }
-
- private void logExecutionResults(ProcessExecutionResults results) {
- // Always log the output at info level. On Unix we could switch
- // depending on a exitCode being !=0, but ...
- log.info("Exit code from process execution: " + results.getExitCode());
- log.info("Output from process execution: " + SEPARATOR
- + results.getCapturedOutput() + SEPARATOR);
- }
-
- /**
- * Shuts down the AS server via a JMX call.
- *
- * @return success message if no errors are encountered
- */
- private String shutdownViaJmx() {
- Configuration pluginConfig =
serverComponent.getResourceContext().getPluginConfiguration();
- String mbeanName = pluginConfig
- .getSimple(
- ApplicationServerPluginConfigurationProperties.SHUTDOWN_MBEAN_CONFIG_PROP)
- .getStringValue();
- String operationName = pluginConfig
- .getSimple(
- ApplicationServerPluginConfigurationProperties.SHUTDOWN_MBEAN_OPERATION_CONFIG_PROP)
- .getStringValue();
-
- EmsConnection connection = this.serverComponent.getEmsConnection();
- if (connection == null) {
- throw new RuntimeException("Can not connect to the server");
- }
- EmsBean bean = connection.getBean(mbeanName);
- EmsOperation operation = bean.getOperation(operationName);
- /*
- * Now see if we got the 'real' method (the one with no param) or the
- * overloaded one. This is a workaround for a bug in EMS that prevents
- * finding operations with same name and different signature.
- *
http://sourceforge
- * .net/tracker/index.php?func=detail&aid=2007692&group_id
- * =60228&atid=493495
- *
- * In addition, as we offer the user to specify any MBean and any
- * method, we'd need a clever way for the user to specify parameters
- * anyway.
- */
- List<EmsParameter> params = operation.getParameters();
- int count = params.size();
- if (count == 0)
- operation.invoke(new Object[0]);
- else { // overloaded operation
- operation.invoke(new Object[] { 0 }); // return code of 0
- }
-
- return "The server has been shut down.";
- }
-
- private void validateScriptFile(File scriptFile, String scriptPropertyName) {
- if (!scriptFile.exists()) {
- throw new RuntimeException("Script (" + scriptFile
- + ") specified via '" + scriptPropertyName
- + "' connection property does not exist.");
- }
-
- if (scriptFile.isDirectory()) {
- throw new RuntimeException("Script (" + scriptFile
- + ") specified via '" + scriptPropertyName
- + "' connection property is a directory, not a file.");
- }
- }
-
- /**
- * Restart the server by first trying a shutdown and then a start. This is
- * fail fast.
- *
- * @return A success message on success
- */
- private OperationResult restart() {
- try {
- shutDown();
- } catch (Exception e) {
- throw new RuntimeException("Shutdown may have failed: " + e);
- }
-
- try {
- start();
- } catch (Exception e) {
- throw new RuntimeException("Start following shutdown may have failed: " +
e);
- }
-
- return new OperationResult("Server has been restarted.");
-
- }
-
- private AvailabilityType waitForServerToStart(long start)
- throws InterruptedException {
- AvailabilityType avail;
- while (((avail = this.serverComponent.getAvailability()) == AvailabilityType.DOWN)
- && (System.currentTimeMillis() < (start + START_WAIT_MAX))) {
- try {
- Thread.sleep(START_WAIT_INTERVAL);
- } catch (InterruptedException e) {
- // ignore
- }
- }
- return avail;
- }
-
- private AvailabilityType waitForServerToShutdown() {
- long start = System.currentTimeMillis();
+ }
+
+ /**
+ * Shuts down the AS server using a shutdown script.
+ *
+ * @return success message if no errors are encountered
+ */
+ private String shutdownViaScript() {
+ File shutdownScriptFile = getShutdownScriptPath();
+ validateScriptFile(shutdownScriptFile,
+ ApplicationServerPluginConfigurationProperties.SHUTDOWN_SCRIPT_CONFIG_PROP);
+ Configuration pluginConfig =
serverComponent.getResourceContext().getPluginConfiguration();
+ String prefix = pluginConfig
+
.getSimple(ApplicationServerPluginConfigurationProperties.SCRIPT_PREFIX_CONFIG_PROP).getStringValue();
+ ProcessExecution processExecution =
ProcessExecutionUtility.createProcessExecution(prefix, shutdownScriptFile);
+
+ initProcessExecution(processExecution, shutdownScriptFile);
+
+ String server =
pluginConfig.getSimple(ApplicationServerPluginConfigurationProperties.NAMING_URL)
+ .getStringValue();
+ if (server != null) {
+ processExecution.getArguments().add("--server=" + server);
+ }
+
+ String user =
pluginConfig.getSimple(ApplicationServerComponent.PRINCIPAL_CONFIG_PROP).getStringValue();
+ if (user != null) {
+ processExecution.getArguments().add("--user=" + user);
+ }
+
+ String password =
pluginConfig.getSimple(ApplicationServerComponent.CREDENTIALS_CONFIG_PROP).getStringValue();
+ if (password != null) {
+ processExecution.getArguments().add("--password=" + password);
+ }
+
+ processExecution.getArguments().add("--shutdown");
+
+ /*
+ * This tells shutdown.bat not to call the Windows PAUSE command, which
+ * would cause the script to hang indefinitely waiting for input.
+ * noinspection ConstantConditions
+ */
+ processExecution.getEnvironmentVariables().put("NOPAUSE",
"1");
+
+ if (log.isDebugEnabled()) {
+ log.debug("About to execute the following process: [" +
processExecution + "]");
+ }
+ SystemInfo systemInfo =
serverComponent.getResourceContext().getSystemInformation();
+ ProcessExecutionResults results = systemInfo.executeProcess(processExecution);
+ logExecutionResults(results);
+
+ if (results.getError() != null) {
+ throw new RuntimeException("Error executing shutdown script while
stopping AS instance. Exit code ["
+ + results.getExitCode() + "]", results.getError());
+ }
+
+ return "The server has been shut down.";
+ }
+
+ private void logExecutionResults(ProcessExecutionResults results) {
+ // Always log the output at info level. On Unix we could switch
+ // depending on a exitCode being !=0, but ...
+ log.info("Exit code from process execution: " +
results.getExitCode());
+ log.info("Output from process execution: " + SEPARATOR +
results.getCapturedOutput() + SEPARATOR);
+ }
+
+ /**
+ * Shuts down the AS server via a JMX call.
+ *
+ * @return success message if no errors are encountered
+ */
+ private String shutdownViaJmx() {
+ Configuration pluginConfig =
serverComponent.getResourceContext().getPluginConfiguration();
+ String mbeanName = pluginConfig.getSimple(
+
ApplicationServerPluginConfigurationProperties.SHUTDOWN_MBEAN_CONFIG_PROP).getStringValue();
+ String operationName = pluginConfig.getSimple(
+
ApplicationServerPluginConfigurationProperties.SHUTDOWN_MBEAN_OPERATION_CONFIG_PROP).getStringValue();
+
+ EmsConnection connection = this.serverComponent.getEmsConnection();
+ if (connection == null) {
+ throw new RuntimeException("Can not connect to the server");
+ }
+ EmsBean bean = connection.getBean(mbeanName);
+ EmsOperation operation = bean.getOperation(operationName);
+ /*
+ * Now see if we got the 'real' method (the one with no param) or the
+ * overloaded one. This is a workaround for a bug in EMS that prevents
+ * finding operations with same name and different signature.
+ *
http://sourceforge
+ * .net/tracker/index.php?func=detail&aid=2007692&group_id
+ * =60228&atid=493495
+ *
+ * In addition, as we offer the user to specify any MBean and any
+ * method, we'd need a clever way for the user to specify parameters
+ * anyway.
+ */
+ List<EmsParameter> params = operation.getParameters();
+ int count = params.size();
+ if (count == 0)
+ operation.invoke(new Object[0]);
+ else { // overloaded operation
+ operation.invoke(new Object[] { 0 }); // return code of 0
+ }
+
+ return "The server has been shut down.";
+ }
+
+ private void validateScriptFile(File scriptFile, String scriptPropertyName) {
+ if (!scriptFile.exists()) {
+ throw new RuntimeException("Script (" + scriptFile + ")
specified via '" + scriptPropertyName
+ + "' connection property does not exist.");
+ }
+
+ if (scriptFile.isDirectory()) {
+ throw new RuntimeException("Script (" + scriptFile + ")
specified via '" + scriptPropertyName
+ + "' connection property is a directory, not a file.");
+ }
+ }
+
+ /**
+ * Restart the server by first trying a shutdown and then a start. This is
+ * fail fast.
+ *
+ * @return A success message on success
+ */
+ private OperationResult restart() {
+ try {
+ shutDown();
+ } catch (Exception e) {
+ throw new RuntimeException("Shutdown may have failed: " + e);
+ }
+
+ try {
+ start();
+ } catch (Exception e) {
+ throw new RuntimeException("Start following shutdown may have failed:
" + e);
+ }
+
+ return new OperationResult("Server has been restarted.");
+
+ }
+
+ private AvailabilityType waitForServerToStart(long start) throws InterruptedException
{
AvailabilityType avail;
+ //detect whether startWaitMax property has been set.
+ Configuration pluginConfig =
serverComponent.getResourceContext().getPluginConfiguration();
+ PropertySimple property = pluginConfig
+
.getSimple(ApplicationServerPluginConfigurationProperties.START_WAIT_MAX_PROP);
+ //if set and valid, update startWaitMax value
+ if ((property != null) && (property.getIntegerValue() != null)) {
+ int newValue = property.getIntegerValue();
+ if (newValue >= 1) {
+ START_WAIT_MAX = 1000L * 60 * newValue;
+ }
+ }
+ while (((avail = this.serverComponent.getAvailability()) ==
AvailabilityType.DOWN)
+ && (System.currentTimeMillis() < (start + START_WAIT_MAX))) {
+ try {
+ Thread.sleep(START_WAIT_INTERVAL);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+ return avail;
+ }
+
+ private AvailabilityType waitForServerToShutdown() {
+ long start = System.currentTimeMillis();
+ AvailabilityType avail;
+ //detect whether stopWaitMax property has been set.
+ Configuration pluginConfig =
serverComponent.getResourceContext().getPluginConfiguration();
+ PropertySimple property = pluginConfig
+
.getSimple(ApplicationServerPluginConfigurationProperties.STOP_WAIT_MAX_PROP);
+ //if set and valid update stopWaitMax value
+ if ((property != null) && (property.getIntegerValue() != null)) {
+ int newValue = property.getIntegerValue();
+ if (newValue >= 1) {
+ STOP_WAIT_MAX = 1000L * 60 * newValue;
+ }
+ }
+
while (((avail = this.serverComponent.getAvailability()) == AvailabilityType.UP)
- && (System.currentTimeMillis() < (start + STOP_WAIT_MAX))) {
- try {
- Thread.sleep(STOP_WAIT_INTERVAL);
- } catch (InterruptedException e) {
- // ignore
- }
- }
-
- // After the server becomes unavailable, wait a little longer to hopefully
- // ensure shutdown is complete.
- try {
- Thread.sleep(STOP_WAIT_FINAL);
- } catch (InterruptedException e) {
- // ignore
- }
- return avail;
- }
-
- /**
- * Return the absolute path of this JBoss server's start script (e.g.
- * "C:\opt\jboss-5.1.0.GA\bin\run.sh").
- *
- * @return the absolute path of this JBoss server's start script (e.g.
- * "C:\opt\jboss-5.1.0.GA\bin\run.sh")
- */
- @NotNull
- public File getStartScriptPath() {
- Configuration pluginConfig = serverComponent.getResourceContext()
- .getPluginConfiguration();
- String startScript = pluginConfig
- .getSimpleValue(
- ApplicationServerPluginConfigurationProperties.START_SCRIPT_CONFIG_PROP,
- DEFAULT_START_SCRIPT);
- File startScriptFile = resolvePathRelativeToHomeDir(startScript);
- return startScriptFile;
- }
-
- @NotNull
- private File resolvePathRelativeToHomeDir(@NotNull String path) {
- return resolvePathRelativeToHomeDir(serverComponent
- .getResourceContext().getPluginConfiguration(), path);
- }
-
- @NotNull
- private File resolvePathRelativeToHomeDir(Configuration pluginConfig,
- @NotNull String path) {
- File configDir = new File(path);
- if (!configDir.isAbsolute()) {
- String jbossHomeDir = getRequiredPropertyValue(pluginConfig,
- ApplicationServerPluginConfigurationProperties.HOME_DIR);
- configDir = new File(jbossHomeDir, path);
- }
-
- return configDir;
- }
-
- @NotNull
- private String getRequiredPropertyValue(@NotNull Configuration config,
- @NotNull String propName) {
- String propValue = config.getSimpleValue(propName, null);
- if (propValue == null) {
- // Something's not right - neither autodiscovery, nor the config
- // edit GUI, should ever allow this.
- throw new IllegalStateException("Required property '" + propName
- + "' is not set.");
- }
-
- return propValue;
- }
-
- /**
- * Return the absolute path of this JBoss server's shutdown script (e.g.
- * "C:\opt\jboss-5.1.0.GA\bin\shutdown.sh").
- *
- * @return the absolute path of this JBoss server's shutdown script (e.g.
- * "C:\opt\jboss-5.1.0.GA\bin\shutdown.sh")
- */
- @NotNull
- public File getShutdownScriptPath() {
- Configuration pluginConfig = serverComponent.getResourceContext()
- .getPluginConfiguration();
- String shutdownScript = pluginConfig
- .getSimpleValue(
- ApplicationServerPluginConfigurationProperties.SHUTDOWN_SCRIPT_CONFIG_PROP,
- DEFAULT_SHUTDOWN_SCRIPT);
- File shutdownScriptFile = resolvePathRelativeToHomeDir(shutdownScript);
- return shutdownScriptFile;
- }
-
- /**
- * Return the absolute path of this JBoss server's JAVA_HOME directory (e.g.
"C:\opt\jdk1.5.0_14"), as defined by
+ && (System.currentTimeMillis() < (start + STOP_WAIT_MAX))) {
+ try {
+ Thread.sleep(STOP_WAIT_INTERVAL);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+
+ // After the server becomes unavailable, wait a little longer to hopefully
+ // ensure shutdown is complete.
+ try {
+ Thread.sleep(STOP_WAIT_FINAL);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ return avail;
+ }
+
+ /**
+ * Return the absolute path of this JBoss server's start script (e.g.
+ * "C:\opt\jboss-5.1.0.GA\bin\run.sh").
+ *
+ * @return the absolute path of this JBoss server's start script (e.g.
+ * "C:\opt\jboss-5.1.0.GA\bin\run.sh")
+ */
+ @NotNull
+ public File getStartScriptPath() {
+ Configuration pluginConfig =
serverComponent.getResourceContext().getPluginConfiguration();
+ String startScript = pluginConfig.getSimpleValue(
+ ApplicationServerPluginConfigurationProperties.START_SCRIPT_CONFIG_PROP,
DEFAULT_START_SCRIPT);
+ File startScriptFile = resolvePathRelativeToHomeDir(startScript);
+ return startScriptFile;
+ }
+
+ @NotNull
+ private File resolvePathRelativeToHomeDir(@NotNull String path) {
+ return
resolvePathRelativeToHomeDir(serverComponent.getResourceContext().getPluginConfiguration(),
path);
+ }
+
+ @NotNull
+ private File resolvePathRelativeToHomeDir(Configuration pluginConfig, @NotNull String
path) {
+ File configDir = new File(path);
+ if (!configDir.isAbsolute()) {
+ String jbossHomeDir = getRequiredPropertyValue(pluginConfig,
+ ApplicationServerPluginConfigurationProperties.HOME_DIR);
+ configDir = new File(jbossHomeDir, path);
+ }
+
+ return configDir;
+ }
+
+ @NotNull
+ private String getRequiredPropertyValue(@NotNull Configuration config, @NotNull
String propName) {
+ String propValue = config.getSimpleValue(propName, null);
+ if (propValue == null) {
+ // Something's not right - neither autodiscovery, nor the config
+ // edit GUI, should ever allow this.
+ throw new IllegalStateException("Required property '" +
propName + "' is not set.");
+ }
+
+ return propValue;
+ }
+
+ /**
+ * Return the absolute path of this JBoss server's shutdown script (e.g.
+ * "C:\opt\jboss-5.1.0.GA\bin\shutdown.sh").
+ *
+ * @return the absolute path of this JBoss server's shutdown script (e.g.
+ * "C:\opt\jboss-5.1.0.GA\bin\shutdown.sh")
+ */
+ @NotNull
+ public File getShutdownScriptPath() {
+ Configuration pluginConfig =
serverComponent.getResourceContext().getPluginConfiguration();
+ String shutdownScript = pluginConfig.getSimpleValue(
+ ApplicationServerPluginConfigurationProperties.SHUTDOWN_SCRIPT_CONFIG_PROP,
DEFAULT_SHUTDOWN_SCRIPT);
+ File shutdownScriptFile = resolvePathRelativeToHomeDir(shutdownScript);
+ return shutdownScriptFile;
+ }
+
+ /**
+ * Return the absolute path of this JBoss server's JAVA_HOME directory (e.g.
"C:\opt\jdk1.5.0_14"), as defined by
* the 'javaHome' plugin config prop, or null if that prop is not set.
- *
- * @return the absolute path of this JBoss server's JAVA_HOME directory, as defined
by
+ *
+ * @return the absolute path of this JBoss server's JAVA_HOME directory, as
defined by
* the 'javaHome' plugin config prop, or null if that prop is not
set
- */
- @Nullable
- public File getJavaHomePath() {
- Configuration pluginConfig =
serverComponent.getResourceContext().getPluginConfiguration();
- String javaHomePath =
pluginConfig.getSimpleValue(ApplicationServerPluginConfigurationProperties.JAVA_HOME,
- null);
- File javaHome = (javaHomePath != null) ? new File(javaHomePath) : null;
- return javaHome;
- }
-
- void validateJavaHomePathProperty() {
- Configuration pluginConfig =
serverComponent.getResourceContext().getPluginConfiguration();
- String javaHome = pluginConfig.getSimple(
- ApplicationServerPluginConfigurationProperties.JAVA_HOME)
- .getStringValue();
- if (javaHome != null) {
- File javaHomeDir = new File(javaHome);
- if (!javaHomeDir.isAbsolute()) {
- throw new InvalidPluginConfigurationException(
- ApplicationServerPluginConfigurationProperties.JAVA_HOME
- + " connection property ('"
- + javaHomeDir
- + "') is not an absolute path. Note, on Windows, absolute paths must
start with the drive letter (e.g. C:).");
- }
-
- if (!javaHomeDir.exists()) {
- throw new InvalidPluginConfigurationException(
- ApplicationServerPluginConfigurationProperties.JAVA_HOME
- + " connection property ('"
- + javaHomeDir
- + "') does not exist.");
- }
-
- if (!javaHomeDir.isDirectory()) {
- throw new InvalidPluginConfigurationException(
- ApplicationServerPluginConfigurationProperties.JAVA_HOME
- + " connection property ('"
- + javaHomeDir
- + "') is not a directory.");
- }
- }
- }
+ */
+ @Nullable
+ public File getJavaHomePath() {
+ Configuration pluginConfig =
serverComponent.getResourceContext().getPluginConfiguration();
+ String javaHomePath =
pluginConfig.getSimpleValue(ApplicationServerPluginConfigurationProperties.JAVA_HOME,
+ null);
+ File javaHome = (javaHomePath != null) ? new File(javaHomePath) : null;
+ return javaHome;
+ }
+
+ void validateJavaHomePathProperty() {
+ Configuration pluginConfig =
serverComponent.getResourceContext().getPluginConfiguration();
+ String javaHome =
pluginConfig.getSimple(ApplicationServerPluginConfigurationProperties.JAVA_HOME)
+ .getStringValue();
+ if (javaHome != null) {
+ File javaHomeDir = new File(javaHome);
+ if (!javaHomeDir.isAbsolute()) {
+ throw new InvalidPluginConfigurationException(
+ ApplicationServerPluginConfigurationProperties.JAVA_HOME
+ + " connection property ('"
+ + javaHomeDir
+ + "') is not an absolute path. Note, on Windows,
absolute paths must start with the drive letter (e.g. C:).");
+ }
+
+ if (!javaHomeDir.exists()) {
+ throw new
InvalidPluginConfigurationException(ApplicationServerPluginConfigurationProperties.JAVA_HOME
+ + " connection property ('" + javaHomeDir +
"') does not exist.");
+ }
+
+ if (!javaHomeDir.isDirectory()) {
+ throw new
InvalidPluginConfigurationException(ApplicationServerPluginConfigurationProperties.JAVA_HOME
+ + " connection property ('" + javaHomeDir +
"') is not a directory.");
+ }
+ }
+ }
}
diff --git
a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerPluginConfigurationProperties.java
b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerPluginConfigurationProperties.java
index c87a82f..e0aa0a4 100644
---
a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerPluginConfigurationProperties.java
+++
b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerPluginConfigurationProperties.java
@@ -35,6 +35,8 @@ public class ApplicationServerPluginConfigurationProperties {
public static final String JAVA_HOME = "javaHome";
public static final String BIND_ADDRESS = "bindAddress";
public static final String START_SCRIPT_CONFIG_PROP = "startScript";
+ public static final String START_WAIT_MAX_PROP = "startWaitMax";
+ public static final String STOP_WAIT_MAX_PROP = "stopWaitMax";
public static final String SHUTDOWN_SCRIPT_CONFIG_PROP = "shutdownScript";
public static final String SHUTDOWN_MBEAN_CONFIG_PROP =
"shutdownMBeanName";
public static final String SHUTDOWN_MBEAN_OPERATION_CONFIG_PROP =
"shutdownMBeanOperation";
diff --git a/modules/plugins/jboss-as-5/src/main/resources/META-INF/rhq-plugin.xml
b/modules/plugins/jboss-as-5/src/main/resources/META-INF/rhq-plugin.xml
index f6c14a1..523d9c4 100644
--- a/modules/plugins/jboss-as-5/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-5/src/main/resources/META-INF/rhq-plugin.xml
@@ -1009,6 +1009,18 @@
this property must be set in order for the
Start operation to work,
or for the Shutdown operation to work when
the shutdown method is set
to 'shutdown script'."/>
+ <c:simple-property name="startWaitMax"
required="false"
+ description="The time, in minutes,(e.g. 1 or 8)
that must elapse before the server is considered to have failed to start up. The default
is 5 minutes.">
+ <c:constraint>
+ <c:integer-constraint minimum="1"/>
+ </c:constraint>
+ </c:simple-property>
+ <c:simple-property name="stopWaitMax"
required="false"
+ description="The time, in minutes,(e.g. 1 or 8)
that must elapse before the server is considered to have failed to stop. The default is
2.5 minutes.">
+ <c:constraint>
+ <c:integer-constraint minimum="1"/>
+ </c:constraint>
+ </c:simple-property>
</c:group>
<c:group name="advanced" displayName="Advanced"
hiddenByDefault="true">