You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2015/07/16 01:09:47 UTC
[03/12] incubator-brooklyn git commit: brooklyn-qa: add org.apache
package prefix
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 <ch...@gmx.net>
Authored: Tue Jul 14 18:33:30 2015 +0300
Committer: Ciprian Ciubotariu <ch...@gmx.net>
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();
+ }
+ }
+ }
+}