brooklyn-qa: add org.apache package prefix
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/bd44bb8f Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/bd44bb8f Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/bd44bb8f Branch: refs/heads/master Commit: bd44bb8f18799d603308d19e98348c949ffa00a1 Parents: 0d7c48c Author: Ciprian Ciubotariu <[email protected]> Authored: Tue Jul 14 18:33:30 2015 +0300 Committer: Ciprian Ciubotariu <[email protected]> Committed: Wed Jul 15 16:56:03 2015 +0300 ---------------------------------------------------------------------- .../qa/load/SimulatedJBoss7ServerImpl.java | 240 -------------- .../qa/load/SimulatedMySqlNodeImpl.java | 183 ----------- .../qa/load/SimulatedNginxControllerImpl.java | 196 ----------- .../brooklyn/qa/load/SimulatedTheeTierApp.java | 140 -------- .../java/brooklyn/qa/longevity/Monitor.java | 261 --------------- .../brooklyn/qa/longevity/MonitorListener.java | 35 -- .../brooklyn/qa/longevity/MonitorPrefs.java | 54 --- .../brooklyn/qa/longevity/MonitorUtils.java | 329 ------------------- .../brooklyn/qa/longevity/StatusRecorder.java | 130 -------- .../qa/load/SimulatedJBoss7ServerImpl.java | 240 ++++++++++++++ .../qa/load/SimulatedMySqlNodeImpl.java | 183 +++++++++++ .../qa/load/SimulatedNginxControllerImpl.java | 196 +++++++++++ .../brooklyn/qa/load/SimulatedTheeTierApp.java | 140 ++++++++ .../apache/brooklyn/qa/longevity/Monitor.java | 261 +++++++++++++++ .../brooklyn/qa/longevity/MonitorListener.java | 35 ++ .../brooklyn/qa/longevity/MonitorPrefs.java | 54 +++ .../brooklyn/qa/longevity/MonitorUtils.java | 329 +++++++++++++++++++ .../brooklyn/qa/longevity/StatusRecorder.java | 130 ++++++++ .../test/java/brooklyn/qa/load/LoadTest.java | 243 -------------- .../brooklyn/qa/longevity/MonitorUtilsTest.java | 165 ---------- .../webcluster/SinusoidalLoadGenerator.java | 90 ----- .../qa/longevity/webcluster/WebClusterApp.java | 101 ------ .../org/apache/brooklyn/qa/load/LoadTest.java | 244 ++++++++++++++ .../brooklyn/qa/longevity/MonitorUtilsTest.java | 166 ++++++++++ .../webcluster/SinusoidalLoadGenerator.java | 90 +++++ .../qa/longevity/webcluster/WebClusterApp.java | 101 ++++++ 26 files changed, 2169 insertions(+), 2167 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bd44bb8f/usage/qa/src/main/java/brooklyn/qa/load/SimulatedJBoss7ServerImpl.java ---------------------------------------------------------------------- diff --git a/usage/qa/src/main/java/brooklyn/qa/load/SimulatedJBoss7ServerImpl.java b/usage/qa/src/main/java/brooklyn/qa/load/SimulatedJBoss7ServerImpl.java deleted file mode 100644 index 64f7aa5..0000000 --- a/usage/qa/src/main/java/brooklyn/qa/load/SimulatedJBoss7ServerImpl.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.qa.load; - -import static java.lang.String.format; - -import java.util.concurrent.Callable; - -import brooklyn.config.ConfigKey; -import brooklyn.enricher.Enrichers; -import brooklyn.entity.basic.Attributes; -import brooklyn.entity.webapp.jboss.JBoss7ServerImpl; -import brooklyn.entity.webapp.jboss.JBoss7SshDriver; -import brooklyn.event.feed.function.FunctionFeed; -import brooklyn.event.feed.function.FunctionPollConfig; -import brooklyn.event.feed.http.HttpFeed; -import brooklyn.event.feed.http.HttpPollConfig; -import brooklyn.event.feed.http.HttpValueFunctions; -import brooklyn.location.access.BrooklynAccessUtils; -import brooklyn.location.basic.SshMachineLocation; -import brooklyn.util.collections.MutableMap; -import brooklyn.util.guava.Functionals; -import brooklyn.util.os.Os; - -import com.google.common.net.HostAndPort; - -/** - * For simulating various aspects of the JBoss 7 app-server entity. - * - * The use-case for this is that the desired configuration is not always available for testing. - * For example, there may be insufficient resources to run 100s of JBoss app-servers, or one - * may be experimenting with possible configurations such as use of an external monitoring tool - * that is not yet available. - * - * It is then possible to simulate aspects of the behaviour, for performance and load testing purposes. - * - * There is configuration for: - * <ul> - * <li>{@code simulateEntity} - * <ul> - * <li>if true, no underlying entity will be started. Instead a sleep 100000 job will be run and monitored. - * <li>if false, the underlying entity (i.e. a JBoss app-server) will be started as normal. - * </ul> - * <li>{@code simulateExternalMonitoring} - * <ul> - * <li>if true, disables the default monitoring mechanism. Instead, a function will periodically execute - * to set the entity's sensors (as though the values had been obtained from the external monitoring tool). - * <li>if false, then: - * <ul> - * <li>If {@code simulateEntity==true} it will execute comparable commands (e.g. execute a command of the same - * size over ssh or do a comparable number of http GET requests). - * <li>If {@code simulateEntity==false} then normal monitoring will be done. - * </ul> - * </ul> - * <li>{@code skipSshOnStart} - * <ul> - * <li>If true (and if {@code simulateEntity==true}), then no ssh commands will be executed at deploy-time. - * This is useful for speeding up load testing, to get to the desired number of entities. - * Should not be set to {@code true} if {@code simulateEntity==false}. - * <li>If false, the ssh commands will be executed (based on the value of {@code simulateEntity}. - * </ul> - * </ul> - */ -public class SimulatedJBoss7ServerImpl extends JBoss7ServerImpl { - - public static final ConfigKey<Boolean> SIMULATE_ENTITY = SimulatedTheeTierApp.SIMULATE_ENTITY; - public static final ConfigKey<Boolean> SIMULATE_EXTERNAL_MONITORING = SimulatedTheeTierApp.SIMULATE_EXTERNAL_MONITORING; - public static final ConfigKey<Boolean> SKIP_SSH_ON_START = SimulatedTheeTierApp.SKIP_SSH_ON_START; - - private HttpFeed httpFeed; - private FunctionFeed functionFeed; - - @Override - public Class<?> getDriverInterface() { - return SimulatedJBoss7SshDriver.class; - } - - @Override - protected void connectSensors() { - boolean simulateEntity = getConfig(SIMULATE_ENTITY); - boolean simulateExternalMonitoring = getConfig(SIMULATE_EXTERNAL_MONITORING); - - if (!simulateEntity && !simulateExternalMonitoring) { - super.connectSensors(); - return; - } - - HostAndPort hp = BrooklynAccessUtils.getBrooklynAccessibleAddress(this, - getAttribute(MANAGEMENT_HTTP_PORT) + getConfig(PORT_INCREMENT)); - - String managementUri = String.format("http://%s:%s/management/subsystem/web/connector/http/read-resource", - hp.getHostText(), hp.getPort()); - setAttribute(MANAGEMENT_URL, managementUri); - - if (simulateExternalMonitoring) { - // TODO What would set this normally, if not doing connectServiceUpIsRunning? - setAttribute(SERVICE_PROCESS_IS_RUNNING, true); - } else { - // if simulating entity, then simulate work of periodic HTTP request; TODO but not parsing JSON response - String uriToPoll = (simulateEntity) ? "http://localhost:8081" : managementUri; - - httpFeed = HttpFeed.builder() - .entity(this) - .period(200) - .baseUri(uriToPoll) - .credentials(getConfig(MANAGEMENT_USER), getConfig(MANAGEMENT_PASSWORD)) - .poll(new HttpPollConfig<Integer>(MANAGEMENT_STATUS) - .onSuccess(HttpValueFunctions.responseCode())) - .build(); - - // Polls over ssh for whether process is running - connectServiceUpIsRunning(); - } - - functionFeed = FunctionFeed.builder() - .entity(this) - .period(5000) - .poll(new FunctionPollConfig<Boolean,Boolean>(MANAGEMENT_URL_UP) - .callable(new Callable<Boolean>() { - private int counter = 0; - public Boolean call() { - setAttribute(REQUEST_COUNT, (counter++ % 100)); - setAttribute(ERROR_COUNT, (counter++ % 100)); - setAttribute(TOTAL_PROCESSING_TIME, (counter++ % 100)); - setAttribute(MAX_PROCESSING_TIME, (counter++ % 100)); - setAttribute(BYTES_RECEIVED, (long) (counter++ % 100)); - setAttribute(BYTES_SENT, (long) (counter++ % 100)); - return true; - }})) - .build(); - - addEnricher(Enrichers.builder().updatingMap(Attributes.SERVICE_NOT_UP_INDICATORS) - .from(MANAGEMENT_URL_UP) - .computing(Functionals.ifNotEquals(true).value("Management URL not reachable") ) - .build()); - } - - @Override - protected void disconnectSensors() { - super.disconnectSensors(); - if (httpFeed != null) httpFeed.stop(); - if (functionFeed != null) functionFeed.stop(); - } - - public static class SimulatedJBoss7SshDriver extends JBoss7SshDriver { - public SimulatedJBoss7SshDriver(SimulatedJBoss7ServerImpl entity, SshMachineLocation machine) { - super(entity, machine); - } - - @Override - public boolean isRunning() { - if (entity.getConfig(SKIP_SSH_ON_START)) { - return true; - } else { - return super.isRunning(); - } - } - - @Override - public void install() { - if (entity.getConfig(SKIP_SSH_ON_START)) { - // no-op - } else { - super.install(); - } - } - - @Override - public void customize() { - if (entity.getConfig(SKIP_SSH_ON_START)) { - // no-op - } else { - super.customize(); - } - } - - @Override - public void launch() { - if (!entity.getConfig(SIMULATE_ENTITY)) { - super.launch(); - return; - } - - // We wait for evidence of JBoss running because, using - // brooklyn.ssh.config.tool.class=brooklyn.util.internal.ssh.cli.SshCliTool, - // we saw the ssh session return before the JBoss process was fully running - // so the process failed to start. - String pidFile = Os.mergePathsUnix(getRunDir(), PID_FILENAME); - - if (entity.getConfig(SKIP_SSH_ON_START)) { - // minimal ssh, so that isRunning will subsequently work - newScript(MutableMap.of("usePidFile", pidFile), LAUNCHING) - .body.append( - format("nohup sleep 100000 > %s/console 2>&1 < /dev/null &", getRunDir())) - .execute(); - } else { - newScript(MutableMap.of(USE_PID_FILE, false), LAUNCHING) - .body.append( - "export LAUNCH_JBOSS_IN_BACKGROUND=true", - format("export JBOSS_HOME=%s", getExpandedInstallDir()), - format("export JBOSS_PIDFILE=%s/%s", getRunDir(), PID_FILENAME), - format("echo skipping exec of %s/bin/%s.sh ", getExpandedInstallDir(), SERVER_TYPE) + - format("--server-config %s ", CONFIG_FILE) + - format("-Djboss.server.base.dir=%s/%s ", getRunDir(), SERVER_TYPE) + - format("\"-Djboss.server.base.url=file://%s/%s\" ", getRunDir(), SERVER_TYPE) + - "-Djava.net.preferIPv4Stack=true " + - "-Djava.net.preferIPv6Addresses=false " + - format(" >> %s/console 2>&1 </dev/null &", getRunDir()), - format("nohup sleep 100000 > %s/console 2>&1 < /dev/null &", getRunDir()), - format("echo $! > "+pidFile), - format("echo starting > %s/console", getRunDir()), - "for i in {1..10}\n" + - "do\n" + - " grep -i 'starting' "+getRunDir()+"/console && exit\n" + - " sleep 1\n" + - "done\n" + - "echo \"Couldn't determine if process is running (console output does not contain 'starting'); continuing but may subsequently fail\"" - - ) - .execute(); - } - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bd44bb8f/usage/qa/src/main/java/brooklyn/qa/load/SimulatedMySqlNodeImpl.java ---------------------------------------------------------------------- diff --git a/usage/qa/src/main/java/brooklyn/qa/load/SimulatedMySqlNodeImpl.java b/usage/qa/src/main/java/brooklyn/qa/load/SimulatedMySqlNodeImpl.java deleted file mode 100644 index bad437a..0000000 --- a/usage/qa/src/main/java/brooklyn/qa/load/SimulatedMySqlNodeImpl.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.qa.load; - -import static java.lang.String.format; - -import java.util.concurrent.Callable; - -import brooklyn.config.ConfigKey; -import brooklyn.entity.basic.AbstractSoftwareProcessSshDriver; -import brooklyn.entity.database.mysql.MySqlNode; -import brooklyn.entity.database.mysql.MySqlNodeImpl; -import brooklyn.entity.database.mysql.MySqlSshDriver; -import brooklyn.entity.software.SshEffectorTasks; -import brooklyn.event.feed.function.FunctionFeed; -import brooklyn.event.feed.function.FunctionPollConfig; -import brooklyn.location.basic.SshMachineLocation; -import brooklyn.util.collections.MutableMap; -import brooklyn.util.task.DynamicTasks; -import brooklyn.util.task.system.ProcessTaskWrapper; -import brooklyn.util.time.CountdownTimer; -import brooklyn.util.time.Duration; - -/** - * @see SimulatedJBoss7ServerImpl for description of purpose and configuration options. - */ -public class SimulatedMySqlNodeImpl extends MySqlNodeImpl { - - public static final ConfigKey<Boolean> SIMULATE_ENTITY = SimulatedTheeTierApp.SIMULATE_ENTITY; - public static final ConfigKey<Boolean> SIMULATE_EXTERNAL_MONITORING = SimulatedTheeTierApp.SIMULATE_EXTERNAL_MONITORING; - public static final ConfigKey<Boolean> SKIP_SSH_ON_START = SimulatedTheeTierApp.SKIP_SSH_ON_START; - - private FunctionFeed feed; - - @Override - public Class<?> getDriverInterface() { - return SimulatedMySqlSshDriver.class; - } - - @Override - protected void connectSensors() { - boolean simulateExternalMonitoring = getConfig(SIMULATE_EXTERNAL_MONITORING); - if (simulateExternalMonitoring) { - setAttribute(DATASTORE_URL, String.format("mysql://%s:%s/", getAttribute(HOSTNAME), getAttribute(MYSQL_PORT))); - - feed = FunctionFeed.builder() - .entity(this) - .period(Duration.FIVE_SECONDS) - .poll(new FunctionPollConfig<Boolean, Boolean>(SERVICE_UP) - .callable(new Callable<Boolean>() { - private int counter = 0; - public Boolean call() { - setAttribute(QUERIES_PER_SECOND_FROM_MYSQL, (double)(counter++ % 100)); - return true; - }}) - .setOnFailureOrException(false)) - .build(); - } else { - super.connectSensors(); - } - } - - public static class SimulatedMySqlSshDriver extends MySqlSshDriver { - - private int counter = 0; - - public SimulatedMySqlSshDriver(SimulatedMySqlNodeImpl entity, SshMachineLocation machine) { - super(entity, machine); - } - - // simulate metrics, for if using ssh polling - @Override - public String getStatusCmd() { - if (entity.getConfig(SIMULATE_ENTITY)) { - return "echo Uptime: 2427 Threads: 1 Questions: 581 Slow queries: 0 Opens: 53 Flush tables: 1 Open tables: 35 Queries per second avg: "+(counter++ % 100); - } else { - return super.getStatusCmd(); - } - } - - @Override - public void install() { - if (entity.getConfig(SKIP_SSH_ON_START)) { - // no-op - } else { - super.install(); - } - } - - // Not applying creation-script etc, as that requires launching msyqld (so would not scale for single-machine testing) - // This is a copy of super.customize, but with the mysqladmin-exec disabled - @Override - public void customize() { - if (!entity.getConfig(SIMULATE_ENTITY)) { - super.customize(); - return; - } else if (entity.getConfig(SKIP_SSH_ON_START)) { - // no-op - } else { - copyDatabaseConfigScript(); - - newScript(CUSTOMIZING) - .updateTaskAndFailOnNonZeroResultCode() - .body.append( - "chmod 600 "+getConfigFile(), - getBaseDir()+"/scripts/mysql_install_db "+ - "--basedir="+getBaseDir()+" --datadir="+getDataDir()+" "+ - "--defaults-file="+getConfigFile()) - .execute(); - - // launch, then we will configure it - launch(); - - CountdownTimer timer = Duration.seconds(20).countdownTimer(); - boolean hasCreationScript = copyDatabaseCreationScript(); - timer.waitForExpiryUnchecked(); - - // DELIBERATELY SKIPPED FOR SCALABILITY TESTING ON SINGLE MACHINE - DynamicTasks.queue( - SshEffectorTasks.ssh( - "cd "+getRunDir(), - "echo skipping exec of "+getBaseDir()+"/bin/mysqladmin --defaults-file="+getConfigFile()+" --password= password "+getPassword() - ).summary("setting password")); - - if (hasCreationScript) - executeScriptFromInstalledFileAsync("creation-script.sql"); - - // not sure necessary to stop then subsequently launch, but seems safest - // (if skipping, use a flag in launch to indicate we've just launched it) - stop(); - } - } - - @Override - public void launch() { - if (!entity.getConfig(SIMULATE_ENTITY)) { - super.launch(); - return; - } - - entity.setAttribute(MySqlNode.PID_FILE, getRunDir() + "/" + AbstractSoftwareProcessSshDriver.PID_FILENAME); - - if (entity.getConfig(SKIP_SSH_ON_START)) { - // minimal ssh, so that isRunning will subsequently work - newScript(MutableMap.of("usePidFile", true), LAUNCHING) - .body.append( - format("nohup sleep 100000 > %s 2>&1 < /dev/null &", getLogFile())) - .execute(); - } else { - newScript(MutableMap.of("usePidFile", true), LAUNCHING) - .updateTaskAndFailOnNonZeroResultCode() - .body.append(format("echo skipping normal exec of nohup %s/bin/mysqld --defaults-file=%s --user=`whoami` > %s 2>&1 < /dev/null &", getBaseDir(), getConfigFile(), getLogFile())) - .body.append(format("nohup sleep 100000 > %s 2>&1 < /dev/null &", getLogFile())) - .execute(); - } - } - - @Override - public ProcessTaskWrapper<Integer> executeScriptFromInstalledFileAsync(String filenameAlreadyInstalledAtServer) { - return DynamicTasks.queue( - SshEffectorTasks.ssh( - "cd "+getRunDir(), - "echo skipping exec of "+getBaseDir()+"/bin/mysql --defaults-file="+getConfigFile()+" < "+filenameAlreadyInstalledAtServer) - .summary("executing datastore script "+filenameAlreadyInstalledAtServer)); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bd44bb8f/usage/qa/src/main/java/brooklyn/qa/load/SimulatedNginxControllerImpl.java ---------------------------------------------------------------------- diff --git a/usage/qa/src/main/java/brooklyn/qa/load/SimulatedNginxControllerImpl.java b/usage/qa/src/main/java/brooklyn/qa/load/SimulatedNginxControllerImpl.java deleted file mode 100644 index e5c40c2..0000000 --- a/usage/qa/src/main/java/brooklyn/qa/load/SimulatedNginxControllerImpl.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.qa.load; - -import static java.lang.String.format; - -import java.net.URI; -import java.util.Collection; -import java.util.concurrent.Callable; - -import brooklyn.config.ConfigKey; -import brooklyn.entity.Group; -import brooklyn.entity.proxy.nginx.NginxControllerImpl; -import brooklyn.entity.proxy.nginx.NginxSshDriver; -import brooklyn.entity.proxy.nginx.UrlMapping; -import brooklyn.event.SensorEvent; -import brooklyn.event.SensorEventListener; -import brooklyn.event.feed.ConfigToAttributes; -import brooklyn.event.feed.function.FunctionFeed; -import brooklyn.event.feed.function.FunctionPollConfig; -import brooklyn.event.feed.http.HttpFeed; -import brooklyn.event.feed.http.HttpPollConfig; -import brooklyn.location.basic.SshMachineLocation; -import brooklyn.policy.PolicySpec; -import brooklyn.util.collections.MutableMap; -import brooklyn.util.net.Networking; - -import com.google.common.base.Functions; - -/** - * @see SimulatedJBoss7ServerImpl for description of purpose and configuration options. - */ -public class SimulatedNginxControllerImpl extends NginxControllerImpl { - - public static final ConfigKey<Boolean> SIMULATE_ENTITY = SimulatedTheeTierApp.SIMULATE_ENTITY; - public static final ConfigKey<Boolean> SIMULATE_EXTERNAL_MONITORING = SimulatedTheeTierApp.SIMULATE_EXTERNAL_MONITORING; - public static final ConfigKey<Boolean> SKIP_SSH_ON_START = SimulatedTheeTierApp.SKIP_SSH_ON_START; - - private HttpFeed httpFeed; - private FunctionFeed functionFeed; - - @Override - public Class<?> getDriverInterface() { - return SimulatedNginxSshDriver.class; - } - - @Override - public void connectSensors() { - boolean simulateEntity = getConfig(SIMULATE_ENTITY); - boolean simulateExternalMonitoring = getConfig(SIMULATE_EXTERNAL_MONITORING); - - if (!simulateEntity && !simulateExternalMonitoring) { - super.connectSensors(); - return; - } - - // From AbstractController.connectSensors - if (getUrl()==null) { - setAttribute(MAIN_URI, URI.create(inferUrl())); - setAttribute(ROOT_URL, inferUrl()); - } - addServerPoolMemberTrackingPolicy(); - - // From NginxController.connectSensors - ConfigToAttributes.apply(this); - - if (!simulateExternalMonitoring) { - // if simulating entity, then simulate work of periodic HTTP request; TODO but not parsing JSON response - String uriToPoll = (simulateEntity) ? "http://localhost:8081" : getAttribute(MAIN_URI).toString(); - - httpFeed = HttpFeed.builder() - .entity(this) - .period(getConfig(HTTP_POLL_PERIOD)) - .baseUri(uriToPoll) - .poll(new HttpPollConfig<Boolean>(SERVICE_UP) - .onSuccess(Functions.constant(true)) - .onFailureOrException(Functions.constant(true))) - .build(); - } - - functionFeed = FunctionFeed.builder() - .entity(this) - .period(getConfig(HTTP_POLL_PERIOD)) - .poll(new FunctionPollConfig<Boolean,Boolean>(SERVICE_UP) - .callable(new Callable<Boolean>() { - public Boolean call() { - return true; - }})) - .build(); - - // Can guarantee that parent/managementContext has been set - Group urlMappings = getConfig(URL_MAPPINGS); - if (urlMappings != null) { - // Listen to the targets of each url-mapping changing - subscribeToMembers(urlMappings, UrlMapping.TARGET_ADDRESSES, new SensorEventListener<Collection<String>>() { - @Override public void onEvent(SensorEvent<Collection<String>> event) { - updateNeeded(); - } - }); - - // Listen to url-mappings being added and removed - urlMappingsMemberTrackerPolicy = addPolicy(PolicySpec.create(UrlMappingsMemberTrackerPolicy.class) - .configure("group", urlMappings)); - } - } - - @Override - protected void disconnectSensors() { - super.disconnectSensors(); - if (httpFeed != null) httpFeed.stop(); - if (functionFeed != null) functionFeed.stop(); - } - - public static class SimulatedNginxSshDriver extends NginxSshDriver { - public SimulatedNginxSshDriver(SimulatedNginxControllerImpl entity, SshMachineLocation machine) { - super(entity, machine); - } - - @Override - public void install() { - if (entity.getConfig(SKIP_SSH_ON_START)) { - // no-op - } else { - super.install(); - } - } - - @Override - public void customize() { - if (entity.getConfig(SKIP_SSH_ON_START)) { - // no-op - } else { - super.customize(); - } - } - - @Override - public void launch() { - if (!entity.getConfig(SIMULATE_ENTITY)) { - super.launch(); - return; - } - - Networking.checkPortsValid(MutableMap.of("httpPort", getPort())); - - if (entity.getConfig(SKIP_SSH_ON_START)) { - // minimal ssh, so that isRunning will subsequently work - newScript(MutableMap.of("usePidFile", getPidFile()), LAUNCHING) - .body.append( - format("mkdir -p %s/logs", getRunDir()), - format("nohup sleep 100000 > %s 2>&1 < /dev/null &", getLogFileLocation())) - .execute(); - } else { - newScript(MutableMap.of("usePidFile", false), LAUNCHING) - .body.append( - format("cd %s", getRunDir()), - "echo skipping exec of requireExecutable ./sbin/nginx", - sudoBashCIfPrivilegedPort(getPort(), format( - "echo skipping exec of nohup ./sbin/nginx -p %s/ -c conf/server.conf > %s 2>&1 &", getRunDir(), getLogFileLocation())), - format("nohup sleep 100000 > %s 2>&1 < /dev/null &", getLogFileLocation()), - format("echo $! > "+getPidFile()), - format("for i in {1..10}\n" + - "do\n" + - " test -f %1$s && ps -p `cat %1$s` && exit\n" + - " sleep 1\n" + - "done\n" + - "echo \"No explicit error launching nginx but couldn't find process by pid; continuing but may subsequently fail\"\n" + - "cat %2$s | tee /dev/stderr", - getPidFile(), getLogFileLocation())) - .execute(); - } - } - - // Use pid file, because just simulating the run of nginx - @Override - public void stop() { - newScript(MutableMap.of("usePidFile", getPidFile()), STOPPING).execute(); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bd44bb8f/usage/qa/src/main/java/brooklyn/qa/load/SimulatedTheeTierApp.java ---------------------------------------------------------------------- diff --git a/usage/qa/src/main/java/brooklyn/qa/load/SimulatedTheeTierApp.java b/usage/qa/src/main/java/brooklyn/qa/load/SimulatedTheeTierApp.java deleted file mode 100644 index 6f95209..0000000 --- a/usage/qa/src/main/java/brooklyn/qa/load/SimulatedTheeTierApp.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.qa.load; - -import static brooklyn.event.basic.DependentConfiguration.attributeWhenReady; -import static brooklyn.event.basic.DependentConfiguration.formatString; - -import java.util.Collection; -import java.util.List; - -import brooklyn.config.ConfigKey; -import brooklyn.enricher.Enrichers; -import brooklyn.enricher.HttpLatencyDetector; -import brooklyn.entity.basic.AbstractApplication; -import brooklyn.entity.basic.Attributes; -import brooklyn.entity.basic.ConfigKeys; -import brooklyn.entity.basic.Entities; -import brooklyn.entity.basic.StartableApplication; -import brooklyn.entity.database.mysql.MySqlNode; -import brooklyn.entity.group.DynamicCluster; -import brooklyn.entity.java.JavaEntityMethods; -import brooklyn.entity.proxy.nginx.NginxController; -import brooklyn.entity.proxying.EntitySpec; -import brooklyn.entity.trait.Startable; -import brooklyn.entity.webapp.ControlledDynamicWebAppCluster; -import brooklyn.entity.webapp.DynamicWebAppCluster; -import brooklyn.entity.webapp.JavaWebAppService; -import brooklyn.entity.webapp.WebAppService; -import brooklyn.entity.webapp.WebAppServiceConstants; -import brooklyn.entity.webapp.jboss.JBoss7Server; -import brooklyn.launcher.BrooklynLauncher; -import brooklyn.location.basic.PortRanges; -import brooklyn.policy.autoscaling.AutoScalerPolicy; -import brooklyn.util.CommandLineUtil; -import brooklyn.util.collections.MutableSet; - -import com.google.common.base.Function; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; - -/** - * A 3-tier app where all components are just "simulated" - they don't actually run - * real app-servers or databases, instead just executing a "sleep" command to simulate - * the running process. - * - * This is useful for load testing, where we want to test the performance of Brooklyn - * rather than the ability to host many running app-servers. - * - * The app is based on WebClusterDatabaseExampleApp - * - * @see SimulatedJBoss7ServerImpl for description of purpose and configuration options. - */ -public class SimulatedTheeTierApp extends AbstractApplication { - - public static final ConfigKey<Boolean> SIMULATE_ENTITY = ConfigKeys.newBooleanConfigKey("simulateEntity", "", true); - - public static final ConfigKey<Boolean> SIMULATE_EXTERNAL_MONITORING = ConfigKeys.newBooleanConfigKey("simulateExternalMonitoring", "", true); - - public static final ConfigKey<Boolean> SKIP_SSH_ON_START = ConfigKeys.newBooleanConfigKey("skipSshOnStart", "", false); - - public static final String WAR_PATH = "classpath://hello-world.war"; - public static final String DB_TABLE = "visitors"; - public static final String DB_USERNAME = "brooklyn"; - public static final String DB_PASSWORD = "br00k11n"; - public static final boolean USE_HTTPS = false; - - @Override - public void init() { - MySqlNode mysql = addChild( - EntitySpec.create(MySqlNode.class) - .impl(SimulatedMySqlNodeImpl.class)); - - ControlledDynamicWebAppCluster web = addChild( - EntitySpec.create(ControlledDynamicWebAppCluster.class) - .configure(ControlledDynamicWebAppCluster.MEMBER_SPEC, EntitySpec.create(JBoss7Server.class).impl(SimulatedJBoss7ServerImpl.class)) - .configure(ControlledDynamicWebAppCluster.CONTROLLER_SPEC, EntitySpec.create(NginxController.class).impl(SimulatedNginxControllerImpl.class)) - .configure(WebAppService.HTTP_PORT, PortRanges.fromString("8080+")) - .configure(JavaWebAppService.ROOT_WAR, WAR_PATH) - .configure(JavaEntityMethods.javaSysProp("brooklyn.example.db.url"), - formatString("jdbc:%s%s?user=%s\\&password=%s", - attributeWhenReady(mysql, MySqlNode.DATASTORE_URL), DB_TABLE, DB_USERNAME, DB_PASSWORD)) - .configure(DynamicCluster.INITIAL_SIZE, 2) - .configure(WebAppService.ENABLED_PROTOCOLS, ImmutableSet.of(USE_HTTPS ? "https" : "http")) ); - - web.getCluster().addPolicy(AutoScalerPolicy.builder(). - metric(DynamicWebAppCluster.REQUESTS_PER_SECOND_IN_WINDOW_PER_NODE). - metricRange(10, 100). - sizeRange(2, 5). - build()); - - addEnricher(Enrichers.builder() - .propagating(Attributes.MAIN_URI, WebAppServiceConstants.ROOT_URL, - DynamicWebAppCluster.REQUESTS_PER_SECOND_IN_WINDOW, - HttpLatencyDetector.REQUEST_LATENCY_IN_SECONDS_IN_WINDOW) - .from(web) - .build()); - - addEnricher(Enrichers.builder() - .aggregating(Startable.SERVICE_UP) - .publishing(Startable.SERVICE_UP) - .fromHardcodedProducers(ImmutableList.of(web, mysql)) - .computing(new Function<Collection<Boolean>, Boolean>() { - @Override public Boolean apply(Collection<Boolean> input) { - return input != null && input.size() == 2 && MutableSet.copyOf(input).equals(ImmutableSet.of(true)); - }}) - .build()); - } - - public static void main(String[] argv) { - List<String> args = Lists.newArrayList(argv); - String port = CommandLineUtil.getCommandLineOption(args, "--port", "8081+"); - String location = CommandLineUtil.getCommandLineOption(args, "--location", "localhost"); - - BrooklynLauncher launcher = BrooklynLauncher.newInstance() - .application(EntitySpec.create(StartableApplication.class, SimulatedTheeTierApp.class) - .displayName("Brooklyn WebApp Cluster with Database example")) - .webconsolePort(port) - .location(location) - .start(); - - Entities.dumpInfo(launcher.getApplications()); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bd44bb8f/usage/qa/src/main/java/brooklyn/qa/longevity/Monitor.java ---------------------------------------------------------------------- diff --git a/usage/qa/src/main/java/brooklyn/qa/longevity/Monitor.java b/usage/qa/src/main/java/brooklyn/qa/longevity/Monitor.java deleted file mode 100644 index 36e9f55..0000000 --- a/usage/qa/src/main/java/brooklyn/qa/longevity/Monitor.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.qa.longevity; - -import static brooklyn.qa.longevity.StatusRecorder.Factory.chain; -import static brooklyn.qa.longevity.StatusRecorder.Factory.noop; -import static brooklyn.qa.longevity.StatusRecorder.Factory.toFile; -import static brooklyn.qa.longevity.StatusRecorder.Factory.toLog; -import static java.util.concurrent.TimeUnit.SECONDS; - -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import joptsimple.OptionParser; -import joptsimple.OptionSet; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import brooklyn.util.collections.TimeWindowedList; -import brooklyn.util.collections.TimestampedValue; -import brooklyn.util.time.Duration; - -import com.google.common.base.Charsets; -import com.google.common.base.Throwables; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.common.collect.Range; -import com.google.common.io.Files; - -public class Monitor { - - private static final Logger LOG = LoggerFactory.getLogger(Monitor.class); - - private static final int checkPeriodMs = 1000; - - private static final OptionParser parser = new OptionParser() { - { - acceptsAll(ImmutableList.of("help", "?", "h"), "show help"); - accepts("webUrl", "Web-app url") - .withRequiredArg().ofType(URL.class); - accepts("brooklynPid", "Brooklyn pid") - .withRequiredArg().ofType(Integer.class); - accepts("logFile", "Brooklyn log file") - .withRequiredArg().ofType(File.class); - accepts("logGrep", "Grep in log file (defaults to 'SEVERE|ERROR|WARN|Exception|Error'") - .withRequiredArg().ofType(String.class); - accepts("logGrepExclusionsFile", "File of expressions to be ignored in log file") - .withRequiredArg().ofType(File.class); - accepts("webProcesses", "Name (for `ps ax | grep` of web-processes") - .withRequiredArg().ofType(String.class); - accepts("numWebProcesses", "Number of web-processes expected (e.g. 1 or 1-3)") - .withRequiredArg().ofType(String.class); - accepts("webProcessesCyclingPeriod", "The period (in seconds) for cycling through the range of numWebProcesses") - .withRequiredArg().ofType(Integer.class); - accepts("outFile", "File to write monitor status info") - .withRequiredArg().ofType(File.class); - accepts("abortOnError", "Exit the JVM on error, with exit code 1") - .withRequiredArg().ofType(Boolean.class); - } - }; - - public static void main(String[] argv) throws InterruptedException, IOException { - OptionSet options = parse(argv); - - if (options == null || options.has("help")) { - parser.printHelpOn(System.out); - System.exit(0); - } - - MonitorPrefs prefs = new MonitorPrefs(); - prefs.webUrl = options.hasArgument("webUrl") ? (URL) options.valueOf("webUrl") : null; - prefs.brooklynPid = options.hasArgument("brooklynPid") ? (Integer) options.valueOf("brooklynPid") : -1; - prefs.logFile = options.hasArgument("logFile") ? (File) options.valueOf("logFile") : null; - prefs.logGrep = options.hasArgument("logGrep") ? (String) options.valueOf("logGrep") : "SEVERE|ERROR|WARN|Exception|Error"; - prefs.logGrepExclusionsFile = options.hasArgument("logGrepExclusionsFile") ? (File) options.valueOf("logGrepExclusionsFile") : null; - prefs.webProcessesRegex = options.hasArgument("webProcesses") ? (String) options.valueOf("webProcesses") : null; - prefs.numWebProcesses = options.hasArgument("numWebProcesses") ? parseRange((String) options.valueOf("numWebProcesses")) : null; - prefs.webProcessesCyclingPeriod = options.hasArgument("webProcessesCyclingPeriod") ? (Integer) options.valueOf("webProcessesCyclingPeriod") : -1; - prefs.outFile = options.hasArgument("outFile") ? (File) options.valueOf("outFile") : null; - prefs.abortOnError = options.hasArgument("abortOnError") ? (Boolean) options.valueOf("abortOnError") : false; - Monitor main = new Monitor(prefs, MonitorListener.NOOP); - main.start(); - } - - private static Range<Integer> parseRange(String range) { - if (range.contains("-")) { - String[] parts = range.split("-"); - return Range.closed(Integer.parseInt(parts[0]), Integer.parseInt(parts[1])); - } else { - return Range.singleton(Integer.parseInt(range)); - } - } - - private static OptionSet parse(String...argv) { - try { - return parser.parse(argv); - } catch (Exception e) { - System.out.println("Error in parsing options: " + e.getMessage()); - return null; - } - } - - private final MonitorPrefs prefs; - private final StatusRecorder recorder; - private final MonitorListener listener; - - public Monitor(MonitorPrefs prefs, MonitorListener listener) { - this.prefs = prefs; - this.listener = listener; - this.recorder = chain(toLog(LOG), (prefs.outFile != null ? toFile(prefs.outFile) : noop())); - } - - private void start() throws IOException { - LOG.info("Monitoring: "+prefs); - ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); - - final AtomicReference<List<String>> previousLogLines = new AtomicReference<List<String>>(Collections.<String>emptyList()); - final TimeWindowedList<Integer> numWebProcessesHistory = new TimeWindowedList<Integer>( - ImmutableMap.of("timePeriod", Duration.seconds(prefs.webProcessesCyclingPeriod), "minExpiredVals", 1)); - final Set<String> logGrepExclusions = ImmutableSet.copyOf(Files.readLines(prefs.logGrepExclusionsFile, Charsets.UTF_8)); - - executor.scheduleAtFixedRate(new Runnable() { - @Override public void run() { - StatusRecorder.Record record = new StatusRecorder.Record(); - StringBuilder failureMsg = new StringBuilder(); - try { - if (prefs.brooklynPid > 0) { - boolean pidRunning = MonitorUtils.isPidRunning(prefs.brooklynPid, "java"); - MonitorUtils.MemoryUsage memoryUsage = MonitorUtils.getMemoryUsage(prefs.brooklynPid, ".*brooklyn.*", 1000); - record.put("pidRunning", pidRunning); - record.put("totalMemoryBytes", memoryUsage.getTotalMemoryBytes()); - record.put("totalMemoryInstances", memoryUsage.getTotalInstances()); - record.put("instanceCounts", memoryUsage.getInstanceCounts()); - - if (!pidRunning) { - failureMsg.append("pid "+prefs.brooklynPid+" is not running"+"\n"); - } - } - if (prefs.webUrl != null) { - boolean webUrlUp = MonitorUtils.isUrlUp(prefs.webUrl); - record.put("webUrlUp", webUrlUp); - - if (!webUrlUp) { - failureMsg.append("web URL "+prefs.webUrl+" is not available"+"\n"); - } - } - if (prefs.logFile != null) { - List<String> logLines = MonitorUtils.searchLog(prefs.logFile, prefs.logGrep, logGrepExclusions); - List<String> newLogLines = getAdditions(previousLogLines.get(), logLines); - previousLogLines.set(logLines); - record.put("logLines", newLogLines); - - if (newLogLines.size() > 0) { - failureMsg.append("Log contains warnings/errors: "+newLogLines+"\n"); - } - } - if (prefs.webProcessesRegex != null) { - List<Integer> pids = MonitorUtils.getRunningPids(prefs.webProcessesRegex, "--webProcesses"); - pids.remove((Object)MonitorUtils.findOwnPid()); - - record.put("webPids", pids); - record.put("numWebPids", pids.size()); - numWebProcessesHistory.add(pids.size()); - - if (prefs.numWebProcesses != null) { - boolean numWebPidsInRange = prefs.numWebProcesses.apply(pids.size()); - record.put("numWebPidsInRange", numWebPidsInRange); - - if (!numWebPidsInRange) { - failureMsg.append("num web processes out-of-range: pids="+pids+"; size="+pids.size()+"; expected="+prefs.numWebProcesses); - } - - if (prefs.webProcessesCyclingPeriod > 0) { - List<TimestampedValue<Integer>> values = numWebProcessesHistory.getValues(); - long valuesTimeRange = (values.get(values.size()-1).getTimestamp() - values.get(0).getTimestamp()); - if (values.size() > 0 && valuesTimeRange > SECONDS.toMillis(prefs.webProcessesCyclingPeriod)) { - int min = -1; - int max = -1; - for (TimestampedValue<Integer> val : values) { - min = (min < 0) ? val.getValue() : Math.min(val.getValue(), min); - max = Math.max(val.getValue(), max); - } - record.put("minWebSizeInPeriod", min); - record.put("maxWebSizeInPeriod", max); - - if (min > prefs.numWebProcesses.lowerEndpoint() || max < prefs.numWebProcesses.upperEndpoint()) { - failureMsg.append("num web processes not increasing/decreasing correctly: " + - "pids="+pids+"; size="+pids.size()+"; cyclePeriod="+prefs.webProcessesCyclingPeriod+ - "; expectedRange="+prefs.numWebProcesses+"; min="+min+"; max="+max+"; history="+values); - } - } else { - int numVals = values.size(); - long startTime = (numVals > 0) ? values.get(0).getTimestamp() : 0; - long endTime = (numVals > 0) ? values.get(values.size()-1).getTimestamp() : 0; - LOG.info("Insufficient vals in time-window to determine cycling behaviour over period ("+prefs.webProcessesCyclingPeriod+"secs): "+ - "numVals="+numVals+"; startTime="+startTime+"; endTime="+endTime+"; periodCovered="+(endTime-startTime)/1000); - } - } - } - } - - } catch (Throwable t) { - LOG.error("Error during periodic checks", t); - throw Throwables.propagate(t); - } - - try { - recorder.record(record); - listener.onRecord(record); - - if (failureMsg.length() > 0) { - listener.onFailure(record, failureMsg.toString()); - - if (prefs.abortOnError) { - LOG.error("Aborting on error: "+failureMsg); - System.exit(1); - } - } - - } catch (Throwable t) { - LOG.warn("Error recording monitor info ("+record+")", t); - throw Throwables.propagate(t); - } - } - }, 0, checkPeriodMs, TimeUnit.MILLISECONDS); - } - - // TODO What is the guava equivalent? Don't want Set.difference, because duplicates/ordered. - private static List<String> getAdditions(List<String> prev, List<String> next) { - List<String> result = Lists.newArrayList(next); - result.removeAll(prev); - return result; - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bd44bb8f/usage/qa/src/main/java/brooklyn/qa/longevity/MonitorListener.java ---------------------------------------------------------------------- diff --git a/usage/qa/src/main/java/brooklyn/qa/longevity/MonitorListener.java b/usage/qa/src/main/java/brooklyn/qa/longevity/MonitorListener.java deleted file mode 100644 index b0a0678..0000000 --- a/usage/qa/src/main/java/brooklyn/qa/longevity/MonitorListener.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.qa.longevity; - -import brooklyn.qa.longevity.StatusRecorder.Record; - -public interface MonitorListener { - - public static final MonitorListener NOOP = new MonitorListener() { - @Override public void onRecord(Record record) { - } - @Override public void onFailure(Record record, String msg) { - } - }; - - public void onRecord(Record record); - - public void onFailure(Record record, String msg); -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bd44bb8f/usage/qa/src/main/java/brooklyn/qa/longevity/MonitorPrefs.java ---------------------------------------------------------------------- diff --git a/usage/qa/src/main/java/brooklyn/qa/longevity/MonitorPrefs.java b/usage/qa/src/main/java/brooklyn/qa/longevity/MonitorPrefs.java deleted file mode 100644 index 3883e93..0000000 --- a/usage/qa/src/main/java/brooklyn/qa/longevity/MonitorPrefs.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.qa.longevity; - -import java.io.File; -import java.net.URL; - -import com.google.common.base.Objects; -import com.google.common.collect.Range; - -public class MonitorPrefs { - - public URL webUrl; - public int brooklynPid; - public File logFile; - public String logGrep; - public File logGrepExclusionsFile; - public String webProcessesRegex; - public Range<Integer> numWebProcesses; - public int webProcessesCyclingPeriod; - public File outFile; - public boolean abortOnError; - - @Override - public String toString() { - return Objects.toStringHelper(this) - .add("webUrl", webUrl) - .add("brooklynPid", brooklynPid) - .add("logFile", logFile) - .add("logGrep", logGrep) - .add("logGrepExclusionsFile", logGrepExclusionsFile) - .add("outFile", outFile) - .add("webProcessesRegex", webProcessesRegex) - .add("numWebProcesses", numWebProcesses) - .add("webProcessesCyclingPeriod", webProcessesCyclingPeriod) - .toString(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bd44bb8f/usage/qa/src/main/java/brooklyn/qa/longevity/MonitorUtils.java ---------------------------------------------------------------------- diff --git a/usage/qa/src/main/java/brooklyn/qa/longevity/MonitorUtils.java b/usage/qa/src/main/java/brooklyn/qa/longevity/MonitorUtils.java deleted file mode 100644 index 290a555..0000000 --- a/usage/qa/src/main/java/brooklyn/qa/longevity/MonitorUtils.java +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.qa.longevity; - -import static com.google.common.base.Strings.isNullOrEmpty; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Pattern; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import brooklyn.util.http.HttpTool; -import brooklyn.util.http.HttpToolResponse; -import brooklyn.util.stream.StreamGobbler; - -import com.google.common.base.Objects; -import com.google.common.base.Throwables; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; -import com.google.common.io.ByteStreams; - -public class MonitorUtils { - - private static final Logger LOG = LoggerFactory.getLogger(MonitorUtils.class); - - private static volatile int ownPid = -1; - - /** - * Confirm can read from URL. - * - * @param url - */ - public static boolean isUrlUp(URL url) { - try { - HttpToolResponse result = HttpTool.httpGet( - HttpTool.httpClientBuilder().trustAll().build(), - URI.create(url.toString()), - ImmutableMap.<String,String>of()); - int statuscode = result.getResponseCode(); - - if (statuscode != 200) { - LOG.info("Error reading URL {}: {}, {}", new Object[]{url, statuscode, result.getReasonPhrase()}); - return false; - } else { - return true; - } - } catch (Exception e) { - LOG.info("Error reading URL {}: {}", url, e); - return false; - } - } - - public static boolean isPidRunning(int pid) { - return isPidRunning(pid, null); - } - - /** - * Confirm the given pid is running, and that the the process matches the given regex. - * - * @param pid - * @param regex - */ - public static boolean isPidRunning(int pid, String regex) { - Process process = exec("ps -p " + pid); - String out = waitFor(process); - if (process.exitValue() > 0) { - String err = toString(process.getErrorStream()); - LOG.info(String.format("pid %s not running: %s", pid, err)); - return false; - } - - if (regex != null) { - String regex2 = "^\\s*" + pid + ".*" + regex; - boolean found = false; - for (String line : out.split("\n")) { - if (hasAtLeastOneMatch(line, regex2)) { - found = true; - break; - } - } - - if (!found) { - String txt = toString(process.getInputStream()); - LOG.info("process did not match regular expression: "+txt); - return false; - } - } - - return true; - } - - private static boolean hasAtLeastOneMatch(String line, String regex) { - return Pattern.matches(".*"+regex+".*", line); - } - - private static String toString(InputStream in){ - try { - byte[] bytes = ByteStreams.toByteArray(in); - return new String(bytes); - } catch (IOException e) { - throw Throwables.propagate(e); - } - - } - - public static List<Integer> getRunningPids(String regex) { - return getRunningPids(regex, null); - } - - /** - * Confirm the given pid is running, and that the the process matches the given regex. - * - * @param regex - * @param excludingRegex - */ - public static List<Integer> getRunningPids(String regex, String excludingRegex) { - Process process = exec("ps ax"); - String out = waitFor(process); - - List<Integer> result = new LinkedList<Integer>(); - for (String line : out.split("\n")) { - if (excludingRegex != null && hasAtLeastOneMatch(line, excludingRegex)) { - continue; - } - if (hasAtLeastOneMatch(line, regex)) { - String[] linesplit = line.trim().split("\\s+"); - result.add(Integer.parseInt(linesplit[0])); - } - } - return result; - } - - public static MemoryUsage getMemoryUsage(int pid){ - return getMemoryUsage(pid, null,0); - } - - /** - * @param pid - */ - public static MemoryUsage getMemoryUsage(int pid, String clazzRegexOfInterest, int minInstancesOfInterest) { - Process process = exec(String.format("jmap -histo %s", pid)); - String out = waitFor(process); - - Map<String, Integer> instanceCounts = Maps.newLinkedHashMap(); - long totalInstances=0; - long totalMemoryBytes=0; - - for (String line : out.split("\n")) { - if (clazzRegexOfInterest!=null && hasAtLeastOneMatch(line, clazzRegexOfInterest)) { - // Format is: - // num #instances #bytes class name - // 1: 43506 8047096 example.MyClazz - - String[] parts = line.trim().split("\\s+"); - String clazz = parts[3]; - int instanceCount = Integer.parseInt(parts[1]); - if (instanceCount >= minInstancesOfInterest) { - instanceCounts.put(clazz, instanceCount); - } - } - if (hasAtLeastOneMatch(line, "^Total.*")) { - String[] parts = line.split("\\s+"); - totalInstances = Long.parseLong(parts[1]); - totalMemoryBytes = Long.parseLong(parts[2]); - } - } - - return new MemoryUsage(totalInstances, totalMemoryBytes, instanceCounts); - } - - public static class MemoryUsage { - final long totalInstances; - final long totalMemoryBytes; - final Map<String, Integer> instanceCounts; - - MemoryUsage(long totalInstances, long totalMemoryBytes, Map<String, Integer> instanceCounts) { - this.totalInstances = totalInstances; - this.totalMemoryBytes = totalMemoryBytes; - this.instanceCounts = instanceCounts; - } - - public String toString() { - return Objects.toStringHelper(this) - .add("totalInstances", totalInstances) - .add("totalMemoryBytes", totalMemoryBytes) - .add("instanceCounts", instanceCounts) - .toString(); - } - - public long getTotalInstances() { - return totalInstances; - } - - public long getTotalMemoryBytes() { - return totalMemoryBytes; - } - - public Map<String, Integer> getInstanceCounts() { - return instanceCounts; - } - } - - public static List<String> searchLog(File file, String grepOfInterest) { - return searchLog(file, grepOfInterest, new LinkedHashSet<String>()); - } - - /** - * Find lines in the given file that match given given regex. - * - * @param file - * @param grepOfInterest - */ - public static List<String> searchLog(File file, String grepOfInterest, Set<String> grepExclusions) { - Process process = exec(String.format("grep -E %s %s", grepOfInterest, file.getAbsoluteFile())); - String out = waitFor(process); - - // TODO Annoying that String.split() returns size 1 when empty string; lookup javadoc when back online... - if (out.length() == 0) return Collections.<String>emptyList(); - - List<String> result = new ArrayList<String>(); - for (String line : out.trim().split("\n")) { - boolean excluded = false; - for (String exclusion : grepExclusions) { - if (!isNullOrEmpty(exclusion) && hasAtLeastOneMatch(line, exclusion)) { - excluded = true; - } - } - if (!excluded) { - result.add(line); - } - } - return result; - } - - public static Process exec(String cmd) { - LOG.info("executing cmd: " + cmd); - - try { - return Runtime.getRuntime().exec(cmd); - } catch (IOException e) { - throw Throwables.propagate(e); - } - } - - public static class ProcessHasStderr extends IllegalStateException { - private static final long serialVersionUID = -937871002993888405L; - - byte[] stderrBytes; - public ProcessHasStderr(byte[] stderrBytes) { - this("Process printed to stderr: " + new String(stderrBytes), stderrBytes); - } - public ProcessHasStderr(String message, byte[] stderrBytes) { - super(message); - this.stderrBytes = stderrBytes; - } - } - - /** - * Waits for the given process to complete, consuming its stdout and returning it as a string. - * If there is any output on stderr an exception will be thrown. - */ - public static String waitFor(Process process) { - ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); - @SuppressWarnings("resource") //Closeable doesn't seem appropriate for StreamGobbler since it isn't expected to be called every time - StreamGobbler gobblerOut = new StreamGobbler(process.getInputStream(), bytesOut, null); - gobblerOut.start(); - - ByteArrayOutputStream bytesErr = new ByteArrayOutputStream(); - @SuppressWarnings("resource") - StreamGobbler gobblerErr = new StreamGobbler(process.getErrorStream(), bytesErr, null); - gobblerErr.start(); - - try { - process.waitFor(); - gobblerOut.blockUntilFinished(); - gobblerErr.blockUntilFinished(); - - if (bytesErr.size() > 0) { - throw new ProcessHasStderr(bytesErr.toByteArray()); - } - - return new String(bytesOut.toByteArray()); - } catch (Exception e) { - throw Throwables.propagate(e); - } finally { - if (gobblerOut.isAlive()) gobblerOut.interrupt(); - if (gobblerErr.isAlive()) gobblerErr.interrupt(); - } - } - - public static int findOwnPid() throws IOException { - if (ownPid >= 0) return ownPid; - - String[] cmd = new String[]{"bash", "-c", "echo $PPID"}; - Process process = Runtime.getRuntime().exec(cmd); - String out = MonitorUtils.waitFor(process); - ownPid = Integer.parseInt(out.trim()); - return ownPid; - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bd44bb8f/usage/qa/src/main/java/brooklyn/qa/longevity/StatusRecorder.java ---------------------------------------------------------------------- diff --git a/usage/qa/src/main/java/brooklyn/qa/longevity/StatusRecorder.java b/usage/qa/src/main/java/brooklyn/qa/longevity/StatusRecorder.java deleted file mode 100644 index 5664a2d..0000000 --- a/usage/qa/src/main/java/brooklyn/qa/longevity/StatusRecorder.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.qa.longevity; - -import java.io.File; -import java.io.IOException; -import java.util.Map; - -import org.slf4j.Logger; - -import com.google.common.base.Charsets; -import com.google.common.collect.Maps; -import com.google.common.io.Files; - -public interface StatusRecorder { - - public void record(Record record) throws IOException; - - public static class Factory { - public static final StatusRecorder NOOP = new StatusRecorder() { - @Override public void record(Record record) {} - }; - - public static StatusRecorder noop() { - return NOOP; - } - public static StatusRecorder toFile(File outFile) { - return new FileBasedStatusRecorder(outFile); - } - public static StatusRecorder toSysout() { - return new SysoutBasedStatusRecorder(); - } - public static StatusRecorder toLog(Logger log) { - return new LogBasedStatusRecorder(log); - } - public static StatusRecorder chain(StatusRecorder...recorders) { - return new ChainingStatusRecorder(recorders); - } - } - - public static class Record { - private final Map<String,Object> fields = Maps.newLinkedHashMap(); - - public void putAll(Map<String,?> entries) { - fields.putAll(entries); - } - - public void putAll(String keyPrefix, Map<String,?> entries) { - for (Map.Entry<String,?> entry : entries.entrySet()) { - fields.put(keyPrefix+entry.getKey(), entry.getValue()); - } - } - - public void put(String key, Object val) { - fields.put(key, val); - } - - @Override - public String toString() { - return fields.toString(); - } - } - - public static class FileBasedStatusRecorder implements StatusRecorder { - private final File outFile; - - public FileBasedStatusRecorder(File outFile) { - this.outFile = outFile; - } - - @Override - public void record(Record record) throws IOException { - Files.append(record.fields.toString()+"\n", outFile, Charsets.UTF_8); - } - } - - public static class SysoutBasedStatusRecorder implements StatusRecorder { - public SysoutBasedStatusRecorder() { - } - - @Override - public void record(Record record) { - System.out.println(record.fields); - } - } - - public static class LogBasedStatusRecorder implements StatusRecorder { - private final Logger log; - - public LogBasedStatusRecorder(Logger log) { - this.log = log; - } - - @Override - public void record(Record record) { - log.info("{}", record.fields); - } - } - - public static class ChainingStatusRecorder implements StatusRecorder { - private final StatusRecorder[] recorders; - - public ChainingStatusRecorder(StatusRecorder... recorders) { - this.recorders = recorders; - } - - @Override - public void record(Record record) throws IOException { - for (StatusRecorder recorder : recorders) { - recorder.record(record); - } - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bd44bb8f/usage/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedJBoss7ServerImpl.java ---------------------------------------------------------------------- diff --git a/usage/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedJBoss7ServerImpl.java b/usage/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedJBoss7ServerImpl.java new file mode 100644 index 0000000..762c17b --- /dev/null +++ b/usage/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedJBoss7ServerImpl.java @@ -0,0 +1,240 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.brooklyn.qa.load; + +import static java.lang.String.format; + +import java.util.concurrent.Callable; + +import brooklyn.config.ConfigKey; +import brooklyn.enricher.Enrichers; +import brooklyn.entity.basic.Attributes; +import brooklyn.entity.webapp.jboss.JBoss7ServerImpl; +import brooklyn.entity.webapp.jboss.JBoss7SshDriver; +import brooklyn.event.feed.function.FunctionFeed; +import brooklyn.event.feed.function.FunctionPollConfig; +import brooklyn.event.feed.http.HttpFeed; +import brooklyn.event.feed.http.HttpPollConfig; +import brooklyn.event.feed.http.HttpValueFunctions; +import brooklyn.location.access.BrooklynAccessUtils; +import brooklyn.location.basic.SshMachineLocation; +import brooklyn.util.collections.MutableMap; +import brooklyn.util.guava.Functionals; +import brooklyn.util.os.Os; + +import com.google.common.net.HostAndPort; + +/** + * For simulating various aspects of the JBoss 7 app-server entity. + * + * The use-case for this is that the desired configuration is not always available for testing. + * For example, there may be insufficient resources to run 100s of JBoss app-servers, or one + * may be experimenting with possible configurations such as use of an external monitoring tool + * that is not yet available. + * + * It is then possible to simulate aspects of the behaviour, for performance and load testing purposes. + * + * There is configuration for: + * <ul> + * <li>{@code simulateEntity} + * <ul> + * <li>if true, no underlying entity will be started. Instead a sleep 100000 job will be run and monitored. + * <li>if false, the underlying entity (i.e. a JBoss app-server) will be started as normal. + * </ul> + * <li>{@code simulateExternalMonitoring} + * <ul> + * <li>if true, disables the default monitoring mechanism. Instead, a function will periodically execute + * to set the entity's sensors (as though the values had been obtained from the external monitoring tool). + * <li>if false, then: + * <ul> + * <li>If {@code simulateEntity==true} it will execute comparable commands (e.g. execute a command of the same + * size over ssh or do a comparable number of http GET requests). + * <li>If {@code simulateEntity==false} then normal monitoring will be done. + * </ul> + * </ul> + * <li>{@code skipSshOnStart} + * <ul> + * <li>If true (and if {@code simulateEntity==true}), then no ssh commands will be executed at deploy-time. + * This is useful for speeding up load testing, to get to the desired number of entities. + * Should not be set to {@code true} if {@code simulateEntity==false}. + * <li>If false, the ssh commands will be executed (based on the value of {@code simulateEntity}. + * </ul> + * </ul> + */ +public class SimulatedJBoss7ServerImpl extends JBoss7ServerImpl { + + public static final ConfigKey<Boolean> SIMULATE_ENTITY = SimulatedTheeTierApp.SIMULATE_ENTITY; + public static final ConfigKey<Boolean> SIMULATE_EXTERNAL_MONITORING = SimulatedTheeTierApp.SIMULATE_EXTERNAL_MONITORING; + public static final ConfigKey<Boolean> SKIP_SSH_ON_START = SimulatedTheeTierApp.SKIP_SSH_ON_START; + + private HttpFeed httpFeed; + private FunctionFeed functionFeed; + + @Override + public Class<?> getDriverInterface() { + return SimulatedJBoss7SshDriver.class; + } + + @Override + protected void connectSensors() { + boolean simulateEntity = getConfig(SIMULATE_ENTITY); + boolean simulateExternalMonitoring = getConfig(SIMULATE_EXTERNAL_MONITORING); + + if (!simulateEntity && !simulateExternalMonitoring) { + super.connectSensors(); + return; + } + + HostAndPort hp = BrooklynAccessUtils.getBrooklynAccessibleAddress(this, + getAttribute(MANAGEMENT_HTTP_PORT) + getConfig(PORT_INCREMENT)); + + String managementUri = String.format("http://%s:%s/management/subsystem/web/connector/http/read-resource", + hp.getHostText(), hp.getPort()); + setAttribute(MANAGEMENT_URL, managementUri); + + if (simulateExternalMonitoring) { + // TODO What would set this normally, if not doing connectServiceUpIsRunning? + setAttribute(SERVICE_PROCESS_IS_RUNNING, true); + } else { + // if simulating entity, then simulate work of periodic HTTP request; TODO but not parsing JSON response + String uriToPoll = (simulateEntity) ? "http://localhost:8081" : managementUri; + + httpFeed = HttpFeed.builder() + .entity(this) + .period(200) + .baseUri(uriToPoll) + .credentials(getConfig(MANAGEMENT_USER), getConfig(MANAGEMENT_PASSWORD)) + .poll(new HttpPollConfig<Integer>(MANAGEMENT_STATUS) + .onSuccess(HttpValueFunctions.responseCode())) + .build(); + + // Polls over ssh for whether process is running + connectServiceUpIsRunning(); + } + + functionFeed = FunctionFeed.builder() + .entity(this) + .period(5000) + .poll(new FunctionPollConfig<Boolean,Boolean>(MANAGEMENT_URL_UP) + .callable(new Callable<Boolean>() { + private int counter = 0; + public Boolean call() { + setAttribute(REQUEST_COUNT, (counter++ % 100)); + setAttribute(ERROR_COUNT, (counter++ % 100)); + setAttribute(TOTAL_PROCESSING_TIME, (counter++ % 100)); + setAttribute(MAX_PROCESSING_TIME, (counter++ % 100)); + setAttribute(BYTES_RECEIVED, (long) (counter++ % 100)); + setAttribute(BYTES_SENT, (long) (counter++ % 100)); + return true; + }})) + .build(); + + addEnricher(Enrichers.builder().updatingMap(Attributes.SERVICE_NOT_UP_INDICATORS) + .from(MANAGEMENT_URL_UP) + .computing(Functionals.ifNotEquals(true).value("Management URL not reachable") ) + .build()); + } + + @Override + protected void disconnectSensors() { + super.disconnectSensors(); + if (httpFeed != null) httpFeed.stop(); + if (functionFeed != null) functionFeed.stop(); + } + + public static class SimulatedJBoss7SshDriver extends JBoss7SshDriver { + public SimulatedJBoss7SshDriver(SimulatedJBoss7ServerImpl entity, SshMachineLocation machine) { + super(entity, machine); + } + + @Override + public boolean isRunning() { + if (entity.getConfig(SKIP_SSH_ON_START)) { + return true; + } else { + return super.isRunning(); + } + } + + @Override + public void install() { + if (entity.getConfig(SKIP_SSH_ON_START)) { + // no-op + } else { + super.install(); + } + } + + @Override + public void customize() { + if (entity.getConfig(SKIP_SSH_ON_START)) { + // no-op + } else { + super.customize(); + } + } + + @Override + public void launch() { + if (!entity.getConfig(SIMULATE_ENTITY)) { + super.launch(); + return; + } + + // We wait for evidence of JBoss running because, using + // brooklyn.ssh.config.tool.class=brooklyn.util.internal.ssh.cli.SshCliTool, + // we saw the ssh session return before the JBoss process was fully running + // so the process failed to start. + String pidFile = Os.mergePathsUnix(getRunDir(), PID_FILENAME); + + if (entity.getConfig(SKIP_SSH_ON_START)) { + // minimal ssh, so that isRunning will subsequently work + newScript(MutableMap.of("usePidFile", pidFile), LAUNCHING) + .body.append( + format("nohup sleep 100000 > %s/console 2>&1 < /dev/null &", getRunDir())) + .execute(); + } else { + newScript(MutableMap.of(USE_PID_FILE, false), LAUNCHING) + .body.append( + "export LAUNCH_JBOSS_IN_BACKGROUND=true", + format("export JBOSS_HOME=%s", getExpandedInstallDir()), + format("export JBOSS_PIDFILE=%s/%s", getRunDir(), PID_FILENAME), + format("echo skipping exec of %s/bin/%s.sh ", getExpandedInstallDir(), SERVER_TYPE) + + format("--server-config %s ", CONFIG_FILE) + + format("-Djboss.server.base.dir=%s/%s ", getRunDir(), SERVER_TYPE) + + format("\"-Djboss.server.base.url=file://%s/%s\" ", getRunDir(), SERVER_TYPE) + + "-Djava.net.preferIPv4Stack=true " + + "-Djava.net.preferIPv6Addresses=false " + + format(" >> %s/console 2>&1 </dev/null &", getRunDir()), + format("nohup sleep 100000 > %s/console 2>&1 < /dev/null &", getRunDir()), + format("echo $! > "+pidFile), + format("echo starting > %s/console", getRunDir()), + "for i in {1..10}\n" + + "do\n" + + " grep -i 'starting' "+getRunDir()+"/console && exit\n" + + " sleep 1\n" + + "done\n" + + "echo \"Couldn't determine if process is running (console output does not contain 'starting'); continuing but may subsequently fail\"" + + ) + .execute(); + } + } + } +}
