modules/core/native-system/src/main/java/org/rhq/core/system/ProcessExecution.java | 6 modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ProcessExecutionUtility.java | 93 +++++----- modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ServerStartScriptDiscoveryUtility.java | 64 ++++++ modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/StartScriptConfiguration.java | 37 ++- modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/AS7Mode.java | 17 - modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java | 14 + modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java | 74 ++++--- modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HostControllerComponent.java | 10 - modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java | 18 + modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml | 22 +- modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java | 6 11 files changed, 242 insertions(+), 119 deletions(-)
New commits: commit 48b46c0c42e23c1c31064a722dc45704351e6d76 Merge: 736bfc7 e566c0a Author: John Sanda jsanda@redhat.com Date: Sat Apr 28 19:56:27 2012 -0400
Merge branch 'master' into rc/jon3.1.0.GA
commit e566c0a1657455ce59d012f3b673823e2ccca7d4 Author: John Sanda jsanda@redhat.com Date: Sat Apr 28 19:55:36 2012 -0400
fixing typo from previous commit
diff --git a/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml b/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml index 6673fa0..9e1a5a9 100644 --- a/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml +++ b/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml @@ -1,4 +1,4 @@ -t?xml version="1.0"?> +<?xml version="1.0"?>
<!-- $Id: rhq-container.build.xml 9321 2008-02-11 05:03:45Z jmazzitelli $ -->
commit d4aba30b70926318e8ffb8418d002b9a78057b74 Author: John Sanda jsanda@redhat.com Date: Sat Apr 28 18:22:12 2012 -0400
updating path to rtfilter artifact with new group id
diff --git a/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml b/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml index 50e891d..6673fa0 100644 --- a/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml +++ b/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml @@ -1,4 +1,4 @@ -<?xml version="1.0"?> +t?xml version="1.0"?>
<!-- $Id: rhq-container.build.xml 9321 2008-02-11 05:03:45Z jmazzitelli $ -->
@@ -351,7 +351,7 @@ dest="${jboss.deploy.dir}/rhq-agent.sar" />
<echo>Deploying RT filter jar ...</echo> - <copy file="${settings.localRepository}/org/rhq/rhq-rtfilter/${rhq.version}/rhq-rtfilter-${rhq.version}.jar" + <copy file="${settings.localRepository}/org/rhq/helpers/rhq-rtfilter/${rhq.version}/rhq-rtfilter-${rhq.version}.jar" todir="${jboss.home}/server/default/lib" verbose="true" />
<!-- Delete docs dir and README files... -->
commit 4afaad5199bfd476bba5ca98b802cd07712bf104 Author: Ian Springer ian.springer@redhat.com Date: Sat Apr 28 16:33:04 2012 -0400
[BZ 816633] add support for specifying a start script prefix in the plugin configs for AS7 servers (https://bugzilla.redhat.com/show_bug.cgi?id=816633)
diff --git a/modules/core/native-system/src/main/java/org/rhq/core/system/ProcessExecution.java b/modules/core/native-system/src/main/java/org/rhq/core/system/ProcessExecution.java index 1510213..9e4acf2 100644 --- a/modules/core/native-system/src/main/java/org/rhq/core/system/ProcessExecution.java +++ b/modules/core/native-system/src/main/java/org/rhq/core/system/ProcessExecution.java @@ -32,15 +32,18 @@ import org.jetbrains.annotations.Nullable;
/** * Provides information on what process to execute and how to execute it. + * <p/> + * Agent plugin developers should also see the ProcessExecutionUtility class in the plugin-api module, which provides + * handy methods for creating <code>ProcessExecution</code>s. * * @author John Mazzitelli * @author Ian Springer * @author Jay Shaughnessy * * @see org.rhq.core.system.JavaSystemInfo#executeProcess(ProcessExecution) - * @see org.rhq.core.pluginapi.util.ProcessExecutionUtility */ public class ProcessExecution { + private String executable; private List<String> arguments; private Map<String, String> environmentVariables; @@ -251,4 +254,5 @@ public class ProcessExecution {
return buf.toString(); } + } \ No newline at end of file diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ProcessExecutionUtility.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ProcessExecutionUtility.java index 157901d..74c0cd0 100644 --- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ProcessExecutionUtility.java +++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ProcessExecutionUtility.java @@ -1,6 +1,6 @@ /* * RHQ Management Platform - * Copyright (C) 2005-2008 Red Hat, Inc. + * Copyright (C) 2005-2012 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -24,14 +24,12 @@ package org.rhq.core.pluginapi.util;
import java.io.File; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; -import java.util.StringTokenizer; import java.util.List;
-/** - * @author Ian Springer - */ import org.rhq.core.system.ProcessExecution;
/** @@ -41,6 +39,8 @@ import org.rhq.core.system.ProcessExecution; */ public class ProcessExecutionUtility {
+ private static final boolean OS_IS_WINDOWS = (File.separatorChar == '\'); + private ProcessExecutionUtility() { }
@@ -68,8 +68,10 @@ public class ProcessExecutionUtility { * ProcessExecution will have a non-null arguments list, an environment map that is a copy of the current process's * environment, and a working directory set to its executable's parent directory. * - * @param prefix a command prefix applied prior to <code>file</code> execution. Typically a <code>sudo</code> - * command. Ignored if null. + * @param prefix a prefix command line that should be prepended to the executable's command line + * (e.g. "/usr/bin/nohup /usr/bin/sudo -u jboss -g jboss"). any files on the + * command line should be absolute paths. if null, no prefix command line will be + * prepended * @param file an executable or a batch file * * @return a process execution @@ -77,53 +79,47 @@ public class ProcessExecutionUtility { public static ProcessExecution createProcessExecution(String prefix, File file) { ProcessExecution processExecution;
- if (isWindows() && isBatchFile(file)) { - String comSpec = System.getenv("COMSPEC"); - if (comSpec == null) { - throw new RuntimeException("COMSPEC environment variable is not defined."); - // TODO: Try to find cmd.exe by checking the various usual locations. - } - - if (!new File(comSpec).exists()) { - throw new RuntimeException("COMSPEC environment variable specifies a non-existent path: " + comSpec); - } - - processExecution = new ProcessExecution(comSpec); - if (null == prefix) { - processExecution.setArguments(new String[] { "/C", file.getPath(), }); - } else { - processExecution.setArguments(new String[] { "/C", prefix, file.getPath(), }); - } + List<String> prefixArgs; + if (prefix != null) { + // TODO (ips, 04/27/10): Ideally, the prefix should be a String[], not a String. + prefixArgs = Arrays.asList(prefix.split("[ \t]+")); } else { - if (null == prefix) { - processExecution = new ProcessExecution(file.getPath()); - processExecution.setArguments(new ArrayList<String>()); + prefixArgs = Collections.emptyList(); + } + String executable; + List<String> args = new ArrayList<String>(); + if (OS_IS_WINDOWS && isBatchFile(file)) { + // Windows batch files cannot be executed directly - they must be passed as arguments to cmd.exe, e.g. + // "C:\Windows\System32\cmd.exe /c C:\opt\jboss-as\bin\run.bat". + executable = getCmdExeFile().getPath(); + args.add("/c"); + args.addAll(prefixArgs); + args.add(file.getPath()); + } else { + // UNIX + if (prefixArgs.isEmpty()) { + executable = file.getPath(); } else { - List<String> arguments = new ArrayList<String>(); - - StringTokenizer prefixTokenizer = new StringTokenizer(prefix); - String processName = prefixTokenizer.nextToken(); - - while (prefixTokenizer.hasMoreTokens()) { - String prefixArgument = prefixTokenizer.nextToken(); - arguments.add(prefixArgument); + executable = prefixArgs.get(0); + if (prefixArgs.size() > 1) { + args.addAll(prefixArgs.subList(1, prefixArgs.size())); } - - arguments.add(file.getPath()); - - processExecution = new ProcessExecution(processName); - processExecution.setArguments(arguments); + args.add(file.getPath()); } }
+ processExecution = new ProcessExecution(executable); + processExecution.setArguments(args); + // Start out with a copy of our own environment, since Windows needs // certain system environment variables to find DLLs, etc., and even // on UNIX, many scripts will require certain environment variables // (PATH, JAVA_HOME, etc.). + // TODO (ips, 04/27/12): We probably should not just do this by default. Map<String, String> envVars = new LinkedHashMap<String, String>(System.getenv()); processExecution.setEnvironmentVariables(envVars);
- // Many scripts (e.g. JBossAS scripts) assume their working directory is their parent directory. + // Many scripts (e.g. JBossAS scripts) assume their working directory is the directory containing the script. processExecution.setWorkingDirectory(file.getParent());
return processExecution; @@ -133,8 +129,19 @@ public class ProcessExecutionUtility { return file.getName().matches(".*\.((bat)|(cmd))$(?i)"); }
- private static boolean isWindows() { - return File.separatorChar == '\'; + private static File getCmdExeFile() { + String cmdExe = System.getenv("COMSPEC"); + if (cmdExe == null) { + throw new RuntimeException("COMSPEC environment variable is not defined."); + // TODO: Try to find cmd.exe by checking the various usual locations. + } + + File cmdExeFile = new File(cmdExe); + if (!cmdExeFile.exists()) { + throw new RuntimeException("COMSPEC environment variable specifies a non-existent path: " + cmdExe); + } + + return cmdExeFile; }
} \ No newline at end of file diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ServerStartScriptDiscoveryUtility.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ServerStartScriptDiscoveryUtility.java index 576ae41..df8ac21 100644 --- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ServerStartScriptDiscoveryUtility.java +++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ServerStartScriptDiscoveryUtility.java @@ -38,8 +38,9 @@ import org.jetbrains.annotations.Nullable; import org.rhq.core.system.ProcessInfo;
/** - * A set of utility methods for initializing the three plugin configuration properties used by a plugin for starting the - * managed server - "startScript", "startScriptEnv", and "startScriptArgs". See also {@link StartScriptConfiguration}. + * A set of utility methods that server discovery components can use to discover the values required to later restart + * the server process via a start script. The values can then be stored in or retrieved from the server's plugin + * configuration using the {@link StartScriptConfiguration} plugin configuration wrapper. * * @author Ian Springer */ @@ -55,6 +56,8 @@ public class ServerStartScriptDiscoveryUtility { // Generic OS-level env vars that should be in every process's environment. private static final Set<String> CORE_ENV_VAR_NAME_INCLUDES = new HashSet<String>(Arrays.asList("PATH", "LD_LIBRARY_PATH")); + private static final String NOHUP_PATH = "/usr/bin/nohup"; + private static final String SUDO_PATH = "/usr/bin/sudo";
static { if (OS_IS_WINDOWS) { @@ -109,6 +112,63 @@ public class ServerStartScriptDiscoveryUtility { }
/** + * Return the command line prefix that should be used when restarting the specified server process. + * + * @param serverProcess a server (e.g. JBoss AS) process + * @param thisProcess this java process + * + * @return the command line prefix that should be used when restarting the specified server process + */ + @Nullable + public static String getStartScriptPrefix(ProcessInfo serverProcess, ProcessInfo thisProcess) { + String prefix = null; + if (!OS_IS_WINDOWS) { + StringBuilder buffer = new StringBuilder(); + File nohup = new File(NOHUP_PATH); + if (nohup.canExecute()) { + buffer.append(nohup.getPath()); + } + File sudo = new File(SUDO_PATH); + if (sudo.canExecute() && (serverProcess.getCredentials() != null) && + (thisProcess.getCredentials() != null)) { + long processUid = serverProcess.getCredentials().getUid(); + long processGid = serverProcess.getCredentials().getGid(); + long agentProcessUid = thisProcess.getCredentials().getUid(); + long agentProcessGid = thisProcess.getCredentials().getGid(); + boolean sudoNeededForUser = (processUid != agentProcessUid); + boolean sudoNeededForGroup = (processGid != agentProcessGid); + if (sudoNeededForUser || sudoNeededForGroup) { + if (buffer.length() > 0) { + buffer.append(' '); + } + buffer.append(sudo.getPath()); + if (sudoNeededForUser) { + buffer.append(" -u "); + if (serverProcess.getCredentialsName() != null) { + buffer.append(serverProcess.getCredentialsName().getUser()); + } else { + buffer.append(serverProcess.getCredentials().getUid()); + } + } + if (sudoNeededForUser) { + buffer.append(" -g "); + if (serverProcess.getCredentialsName() != null) { + buffer.append(serverProcess.getCredentialsName().getGroup()); + } else { + buffer.append(serverProcess.getCredentials().getGid()); + } + } + } + } + if (buffer.length() > 0) { + prefix = buffer.toString(); + } + } + + return prefix; + } + + /** * Returns the list of arguments that should be passed to the start script for the specified server (e.g. JBoss AS) * process in order to start a functionally equivalent server instance. * diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/StartScriptConfiguration.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/StartScriptConfiguration.java index bd5f6fe..fd633dc 100644 --- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/StartScriptConfiguration.java +++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/StartScriptConfiguration.java @@ -41,57 +41,70 @@ import org.rhq.core.pluginapi.configuration.MapPropertySimpleWrapper; */ public class StartScriptConfiguration {
- public static final String START_SCRIPT_CONFIG_PROP = "startScript"; - public static final String START_SCRIPT_ENV_CONFIG_PROP = "startScriptEnv"; - public static final String START_SCRIPT_ARGS_CONFIG_PROP = "startScriptArgs"; + public static final String START_SCRIPT_PROP = "startScript"; + public static final String START_SCRIPT_PREFIX_PROP = "startScriptPrefix"; + public static final String START_SCRIPT_ENV_PROP = "startScriptEnv"; + public static final String START_SCRIPT_ARGS_PROP = "startScriptArgs";
private Configuration pluginConfig;
public StartScriptConfiguration(Configuration pluginConfig) { + if (pluginConfig == null) { + throw new IllegalArgumentException("'pluginConfig' parameter is null."); + } this.pluginConfig = pluginConfig; }
@Nullable public File getStartScript() { - String startScript = this.pluginConfig.getSimpleValue(START_SCRIPT_CONFIG_PROP); + String startScript = this.pluginConfig.getSimpleValue(START_SCRIPT_PROP); return (startScript != null) ? new File(startScript) : null; }
public void setStartScript(File startScript) { - PropertySimple prop = this.pluginConfig.getSimple(START_SCRIPT_CONFIG_PROP); + PropertySimple prop = this.pluginConfig.getSimple(START_SCRIPT_PROP); if (prop == null) { - prop = new PropertySimple(START_SCRIPT_CONFIG_PROP, null); + prop = new PropertySimple(START_SCRIPT_PROP, null); } prop.setValue(startScript); }
+ @Nullable + public String getStartScriptPrefix() { + return this.pluginConfig.getSimpleValue(START_SCRIPT_PREFIX_PROP); + } + + public void setStartScriptPrefix(String startScriptPrefix) { + this.pluginConfig.setSimpleValue(START_SCRIPT_PREFIX_PROP, startScriptPrefix); + } + @NotNull public Map<String, String> getStartScriptEnv() { - PropertySimple prop = this.pluginConfig.getSimple(START_SCRIPT_ENV_CONFIG_PROP); + PropertySimple prop = this.pluginConfig.getSimple(START_SCRIPT_ENV_PROP); Map<String, String> map = (prop != null) ? new MapPropertySimpleWrapper(prop).getValue() : new HashMap<String, String>(); return map; }
public void setStartScriptEnv(Map<String, String> startScriptEnv) { - PropertySimple prop = this.pluginConfig.getSimple(START_SCRIPT_ENV_CONFIG_PROP); + PropertySimple prop = this.pluginConfig.getSimple(START_SCRIPT_ENV_PROP); if (prop == null) { - prop = new PropertySimple(START_SCRIPT_ENV_CONFIG_PROP, null); + prop = new PropertySimple(START_SCRIPT_ENV_PROP, null); } new MapPropertySimpleWrapper(prop).setValue(startScriptEnv); }
@NotNull public List<String> getStartScriptArgs() { - PropertySimple prop = this.pluginConfig.getSimple(START_SCRIPT_ARGS_CONFIG_PROP); + PropertySimple prop = this.pluginConfig.getSimple(START_SCRIPT_ARGS_PROP); List<String> list = (prop != null) ? new ArgsPropertySimpleWrapper(prop).getValue() : new ArrayList<String>(); return list; }
public void setStartScriptArgs(List<String> startScriptArgs) { - PropertySimple prop = this.pluginConfig.getSimple(START_SCRIPT_ARGS_CONFIG_PROP); + PropertySimple prop = this.pluginConfig.getSimple(START_SCRIPT_ARGS_PROP); if (prop == null) { - prop = new PropertySimple(START_SCRIPT_ARGS_CONFIG_PROP, null); + prop = new PropertySimple(START_SCRIPT_ARGS_PROP, null); } new ArgsPropertySimpleWrapper(prop).setValue(startScriptArgs); } diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/AS7Mode.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/AS7Mode.java index 1d8841a..81d7ee3 100644 --- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/AS7Mode.java +++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/AS7Mode.java @@ -20,25 +20,26 @@ package org.rhq.modules.plugins.jbossas7;
/** * Various definitions for the operation modes of AS7 (HOST is strictly not a mode, but fits here nicely) + * * @author Heiko W. Rupp */ public enum AS7Mode {
- STANDALONE("standalone.xml", "standalone", "--server-config", "bin/standalone.sh","config"), - DOMAIN("domain.xml", "domain", "--domain-config", "bin/domain.sh","domainConfig"), - HOST("host.xml", "domain", "--host-config", "bin/domain.sh","hostConfig"); + STANDALONE("standalone.xml", "standalone", "--server-config", "standalone", "config"), + DOMAIN("domain.xml", "domain", "--domain-config", "domain", "domainConfig"), + HOST("host.xml", "domain", "--host-config", "domain", "hostConfig");
private String defaultXmlFile; private String defaultBaseDir; private String configArg; - private String startScript; + private String startScriptBaseName; private String configPropertyName;
- private AS7Mode(String defaultXmlFile, String defaultBaseDir, String configArg, String startScript, String configPropertyName) { + private AS7Mode(String defaultXmlFile, String defaultBaseDir, String configArg, String startScriptBaseName, String configPropertyName) { this.defaultXmlFile = defaultXmlFile; this.defaultBaseDir = defaultBaseDir; this.configArg = configArg; - this.startScript = startScript; + this.startScriptBaseName = startScriptBaseName; this.configPropertyName = configPropertyName; }
@@ -54,8 +55,8 @@ public enum AS7Mode { return configArg; }
- public String getStartScript() { - return startScript; + public String getStartScriptBaseName() { + return startScriptBaseName; }
public String getConfigPropertyName() { diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java index 7285cec..5428016 100644 --- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java +++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java @@ -76,6 +76,8 @@ public abstract class BaseProcessDiscovery implements ResourceDiscoveryComponent private static final String RHQADMIN = "rhqadmin"; private static final String RHQADMIN_ENCRYPTED = "35c160c1f841a889d4cda53f0bfc94b6";
+ private static final boolean OS_IS_WINDOWS = (File.separatorChar == '\'); + // The list of environment vars that the AS7 start script will use if they are set. private static final Set<String> START_SCRIPT_ENV_VAR_NAMES = new LinkedHashSet<String>(); static { @@ -100,7 +102,7 @@ public abstract class BaseProcessDiscovery implements ResourceDiscoveryComponent ));
// If OS is Windows, add env vars that are only used by the batch files. - if (File.separatorChar == '\') { + if (OS_IS_WINDOWS) { START_SCRIPT_ENV_VAR_NAMES.add("ECHO"); START_SCRIPT_ENV_VAR_NAMES.add("NOPAUSE"); } @@ -188,7 +190,8 @@ public abstract class BaseProcessDiscovery implements ResourceDiscoveryComponent serverPluginConfig.setProductType(productType); pluginConfig.setSimpleValue("hostXmlFileName", getHostXmlFileName(commandLine));
- setStartScriptPluginConfigProps(process, commandLine, pluginConfig); + ProcessInfo agentProcess = discoveryContext.getSystemInformation().getThisProcess(); + setStartScriptPluginConfigProps(process, commandLine, pluginConfig, agentProcess); setUserAndPasswordPluginConfigProps(serverPluginConfig, hostConfig, baseDir);
String key = baseDir.getPath(); @@ -238,14 +241,14 @@ public abstract class BaseProcessDiscovery implements ResourceDiscoveryComponent }
private void setStartScriptPluginConfigProps(ProcessInfo process, AS7CommandLine commandLine, - Configuration pluginConfig) { + Configuration pluginConfig, ProcessInfo agentProcess) { StartScriptConfiguration startScriptConfig = new StartScriptConfiguration(pluginConfig); ProcessInfo parentProcess = getPotentialStartScriptProcess(process);
File startScript = ServerStartScriptDiscoveryUtility.getStartScript(parentProcess); if (startScript == null) { // The parent process is not a script - fallback to the default value (e.g. "bin/standalone.sh"). - startScript = new File(getMode().getStartScript()); + startScript = new File(getMode().getStartScriptBaseName()); } if (!startScript.exists()) { if (!startScript.isAbsolute()) { @@ -259,6 +262,9 @@ public abstract class BaseProcessDiscovery implements ResourceDiscoveryComponent } startScriptConfig.setStartScript(startScript);
+ String startScriptPrefix = ServerStartScriptDiscoveryUtility.getStartScriptPrefix(process, agentProcess); + startScriptConfig.setStartScriptPrefix(startScriptPrefix); + Map<String, String> startScriptEnv = ServerStartScriptDiscoveryUtility.getStartScriptEnv(process, parentProcess, START_SCRIPT_ENV_VAR_NAMES); startScriptConfig.setStartScriptEnv(startScriptEnv); diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java index 98dda57..7b70b94 100644 --- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java +++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java @@ -65,9 +65,11 @@ import org.rhq.modules.plugins.jbossas7.json.Result; * * @author Heiko W. Rupp */ -public class BaseServerComponent<T extends ResourceComponent<?>> extends BaseComponent<T> implements MeasurementFacet { +public abstract class BaseServerComponent<T extends ResourceComponent<?>> extends BaseComponent<T> implements MeasurementFacet {
private static final String SEPARATOR = "\n-----------------------\n"; + private static final boolean OS_IS_WINDOWS = (File.separatorChar == '\'); + private static final String SCRIPT_EXTENSION = (OS_IS_WINDOWS) ? "bat" : "sh";
final Log log = LogFactory.getLog(BaseServerComponent.class);
@@ -108,17 +110,18 @@ public class BaseServerComponent<T extends ResourceComponent<?>> extends BaseCom this.connection = connection; }
+ protected abstract AS7Mode getMode(); + /** - * Restart the server by first executing a 'shutdown' operation via its API, and then calling - * the {@link #startServer(AS7Mode)} method to start it again. + * Restart the server by first executing a 'shutdown' operation via the management API and then calling + * the {@link #startServer} method to start it again. * * @param parameters Parameters to pass to the (recursive) invocation of #invokeOperation - * @param mode Mode of the server to start (domain or standalone) * @return State of execution * @throws Exception If anything goes wrong */ - protected OperationResult restartServer(Configuration parameters, AS7Mode mode) throws Exception { - List<String> errors = validateStartScriptPluginConfigProps(mode); + protected OperationResult restartServer(Configuration parameters) throws Exception { + List<String> errors = validateStartScriptPluginConfigProps(); if (!errors.isEmpty()) { OperationResult result = new OperationResult(); setErrorMessage(result, errors); @@ -134,7 +137,7 @@ public class BaseServerComponent<T extends ResourceComponent<?>> extends BaseCom
// context.getAvailabilityContext().requestAvailabilityCheck();
- return startServer(mode); + return startServer(); }
protected boolean waitUntilDown(OperationResult tmp) throws InterruptedException { @@ -159,22 +162,23 @@ public class BaseServerComponent<T extends ResourceComponent<?>> extends BaseCom }
/** - * Start the server by calling the start script listed in the plugin configuration. If a different - * config is given, this is passed via --server-config - * @return State of Execution. - * @param mode Mode of the server to start (domain or standalone) + * Start the server by calling the start script defined in the plugin configuration. + * + * @return the result of the operation */ - protected OperationResult startServer(AS7Mode mode) { + protected OperationResult startServer() { OperationResult operationResult = new OperationResult();
- List<String> errors = validateStartScriptPluginConfigProps(mode); + List<String> errors = validateStartScriptPluginConfigProps(); if (!errors.isEmpty()) { setErrorMessage(operationResult, errors); return operationResult; }
- File startScriptFile = getStartScriptFile(mode); - ProcessExecution processExecution = ProcessExecutionUtility.createProcessExecution(startScriptFile); + String startScriptPrefix = startScriptConfig.getStartScriptPrefix(); + File startScriptFile = getStartScriptFile(); + ProcessExecution processExecution = ProcessExecutionUtility.createProcessExecution(startScriptPrefix, + startScriptFile);
List<String> arguments = processExecution.getArguments(); if (arguments == null) { @@ -239,10 +243,10 @@ public class BaseServerComponent<T extends ResourceComponent<?>> extends BaseCom operationResult.setErrorMessage(buffer.toString()); }
- private List<String> validateStartScriptPluginConfigProps(AS7Mode mode) { + private List<String> validateStartScriptPluginConfigProps() { List<String> errors = new ArrayList<String>();
- File startScriptFile = getStartScriptFile(mode); + File startScriptFile = getStartScriptFile();
if (!startScriptFile.exists()) { errors.add("Start script '" + startScriptFile + "' does not exist."); @@ -269,14 +273,18 @@ public class BaseServerComponent<T extends ResourceComponent<?>> extends BaseCom return errors; }
- private File getStartScriptFile(AS7Mode mode) { + private File getStartScriptFile() { File startScriptFile = startScriptConfig.getStartScript(); - if (startScriptFile == null) { - startScriptFile = new File(mode.getStartScript()); - } - if (!startScriptFile.isAbsolute()) { - File homeDir = serverPluginConfig.getHomeDir(); - startScriptFile = new File(homeDir, startScriptFile.getPath()); + File homeDir = serverPluginConfig.getHomeDir(); + if (startScriptFile != null) { + if (!startScriptFile.isAbsolute()) { + startScriptFile = new File(homeDir, startScriptFile.getPath()); + } + } else { + // Use the default start script. + String startScriptFileName = getMode().getStartScriptBaseName() + "." + SCRIPT_EXTENSION; + File binDir = new File(homeDir, "bin"); + startScriptFile = new File(binDir, startScriptFileName); } return startScriptFile; } @@ -359,7 +367,7 @@ public class BaseServerComponent<T extends ResourceComponent<?>> extends BaseCom return operationResult; }
- protected OperationResult installManagementUser(Configuration parameters, Configuration pluginConfig, AS7Mode mode) { + protected OperationResult installManagementUser(Configuration parameters, Configuration pluginConfig) { String user = parameters.getSimpleValue("user", ""); String password = parameters.getSimpleValue("password", "");
@@ -389,15 +397,15 @@ public class BaseServerComponent<T extends ResourceComponent<?>> extends BaseCom }
String configFileName; - switch (mode) { + switch (getMode()) { case STANDALONE: - configFileName = pluginConfig.getSimpleValue("config", null); + configFileName = pluginConfig.getSimpleValue("config"); break; - case HOST: - configFileName = pluginConfig.getSimpleValue("hostConfig", null); + case DOMAIN: + configFileName = pluginConfig.getSimpleValue("hostConfig"); break; default: - throw new IllegalArgumentException("Unsupported mode: " + mode); + throw new IllegalArgumentException("Unsupported mode: " + getMode()); }
File configFile = new File(configDir, configFileName); @@ -409,7 +417,11 @@ public class BaseServerComponent<T extends ResourceComponent<?>> extends BaseCom }
String realm = pluginConfig.getSimpleValue("realm", "ManagementRealm"); - File propertiesFile = hostConfig.getSecurityPropertyFile(baseDir, mode, realm); + File propertiesFile = hostConfig.getSecurityPropertyFile(baseDir, getMode(), realm); + if (!propertiesFile.canWrite()) { + result.setErrorMessage("Management users properties file [" + propertiesFile + "] is not writable."); + return result; + }
String encryptedPassword; try { diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HostControllerComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HostControllerComponent.java index d68ab07..2dcde85 100644 --- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HostControllerComponent.java +++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HostControllerComponent.java @@ -70,6 +70,10 @@ public class HostControllerComponent<T extends ResourceComponent<?>> extends Bas return AvailabilityType.UP; }
+ @Override + protected AS7Mode getMode() { + return AS7Mode.DOMAIN; + }
public Configuration getHCConfig() { return pluginConfiguration; @@ -81,9 +85,9 @@ public class HostControllerComponent<T extends ResourceComponent<?>> extends Bas
OperationResult operationResult; if (name.equals("start")) { - operationResult = startServer(AS7Mode.DOMAIN); + operationResult = startServer(); } else if (name.equals("restart")) { - operationResult = restartServer(parameters, AS7Mode.DOMAIN); + operationResult = restartServer(parameters); } else if (name.equals("shutdown")) { // This is a bit trickier, as it needs to be executed on the level on /host=xx String domainHost = pluginConfiguration.getSimpleValue("domainHost", ""); @@ -99,7 +103,7 @@ public class HostControllerComponent<T extends ResourceComponent<?>> extends Bas waitUntilDown(operationResult);
} else if (name.equals("installRhqUser")) { - operationResult = installManagementUser(parameters, pluginConfiguration, AS7Mode.HOST); + operationResult = installManagementUser(parameters, pluginConfiguration); } else {
// Defer other stuff to the base component for now diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java index b297046..7495399 100644 --- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java +++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java @@ -61,15 +61,19 @@ public class StandaloneASComponent extends BaseServerComponent implements Operat }
@Override + protected AS7Mode getMode() { + return AS7Mode.STANDALONE; + } + + @Override public OperationResult invokeOperation(String name, Configuration parameters) throws Exception { - if (name.equals("start")) { - return startServer(AS7Mode.STANDALONE); + return startServer(); } else if (name.equals("restart")) { - return restartServer(parameters, AS7Mode.STANDALONE); + return restartServer(parameters); } else if (name.equals("installRhqUser")) { - return installManagementUser(parameters, pluginConfiguration, AS7Mode.STANDALONE); + return installManagementUser(parameters, pluginConfiguration); }
// reload, shutdown go to the remote server @@ -90,8 +94,8 @@ public class StandaloneASComponent extends BaseServerComponent implements Operat }
private void waitUntilReloaded(OperationResult operationResult) { - boolean reloaded=false; - int count=0; + boolean reloaded = false; + int count = 0; while (!reloaded) { try { Thread.sleep(2000); // Wait 2s @@ -102,7 +106,7 @@ public class StandaloneASComponent extends BaseServerComponent implements Operat Operation op = new ReadAttribute(new Address(),"release-version"); Result res = getASConnection().execute(op); if (res.isSuccess() && !res.isReloadRequired()) { // - reloaded=true; + reloaded = true; } else if (count > 20) { operationResult.setErrorMessage("Was not able to reload the server"); return; diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml index 1ccd2cd..9547479 100644 --- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml +++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml @@ -3,15 +3,27 @@ <!DOCTYPE plugin [
<!ENTITY startScriptPluginConfigGroup ' - <c:group name="startScript"> - <c:simple-property name="startScript" type="file" description="Path to the script that the Start and Restart operations should use to start the server. If the path is not absolute, it is resolved relative to the server home directory." displayName="Start Script Path" required="false" /> - <c:simple-property name="startScriptEnv" type="longString" description="The variables that the Start and Restart operations will add to the environment of the server start script. Each name=value pair should be on a new line." displayName="Start Script Environment Variables" required="false" /> - <c:simple-property name="startScriptArgs" type="longString" description="The arguments that the Start and Restart operations will pass to the server start script. Each argument should be on a new line." displayName="Start Script Arguments" required="false" /> + <c:group name="operations"> + <c:simple-property name="startScript" type="file" + description="Path to the script that the Start and Restart operations should use to start the server. If the path is not absolute, it is resolved relative to the server home directory." displayName="Start Script Path" required="false" /> + <c:simple-property name="startScriptPrefix" type="string" required="false" + description="A prefix command line that should be prepended to the start script command line + by the Start and Restart operations; the prefix command must be an absolute path + (e.g. "/usr/bin/sudo"). This property is most commonly used to run the + AS7 process as a different user than the RHQ Agent (e.g. "sudo -u jboss -g + jboss" could be used to run AS7 as user "jboss" and group + "jboss". It is also possible to chain prefix commands (e.g. + "nohup sudo -u jboss" could be used to make AS7 ignore HUP signals and + run as user "jboss")." /> + <c:simple-property name="startScriptEnv" type="longString" + description="The variables that the Start and Restart operations will add to the environment of the server start script. Each name=value pair should be on a new line." displayName="Start Script Environment Variables" required="false" /> + <c:simple-property name="startScriptArgs" type="longString" + description="The arguments that the Start and Restart operations will pass to the server start script. Each argument should be on a new line." displayName="Start Script Arguments" required="false" /> </c:group> '>
<!ENTITY logSources ' - <c:group name="event" displayName="Events"> + <c:group name="events"> <c:list-property name="logEventSources"> <c:map-property name="logEventSource"> <c:simple-property name="logFilePath" type="file" summary="true" diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java index a58561c..8ddb308 100644 --- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java +++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java @@ -38,7 +38,7 @@ import org.rhq.core.pluginapi.inventory.CreateResourceReport; import org.rhq.core.pluginapi.inventory.ResourceContext; import org.rhq.modules.plugins.jbossas7.ASConnection; import org.rhq.modules.plugins.jbossas7.BaseComponent; -import org.rhq.modules.plugins.jbossas7.BaseServerComponent; +import org.rhq.modules.plugins.jbossas7.StandaloneASComponent; import org.rhq.modules.plugins.jbossas7.json.Address; import org.rhq.modules.plugins.jbossas7.json.CompositeOperation; import org.rhq.modules.plugins.jbossas7.json.Operation; @@ -343,7 +343,7 @@ public class UploadAndDeployTest extends AbstractIntegrationTest { rt.setName("Deployment"); Resource resource = new Resource("deployment="+TEST_WAR_FILE_NAME, TEST_WAR_FILE_NAME, rt); // TODO resource key? resource.setUuid(UUID.randomUUID().toString()); - BaseServerComponent parentComponent = new BaseServerComponent(); + StandaloneASComponent parentComponent = new StandaloneASComponent(); parentComponent.setConnection(getASConnection()); ResourceContext context = new ResourceContext(resource,parentComponent,null,null,null,null,null,null,null,null,null,null,null); bc.start(context); @@ -377,7 +377,7 @@ public class UploadAndDeployTest extends AbstractIntegrationTest { rt.setName("Deployment"); Resource resource = new Resource("server-group=main-server-group",TEST_WAR_FILE_NAME,rt); resource.setUuid(UUID.randomUUID().toString()); - BaseServerComponent parentComponent = new BaseServerComponent(); + StandaloneASComponent parentComponent = new StandaloneASComponent(); parentComponent.setConnection(getASConnection()); ResourceContext context = new ResourceContext(resource,parentComponent,null,null,null,null,null,null,null,null,null,null,null); bc.start(context);