This closes #72
Fix test to work on any combination of OS & eol type.
diff --git a/.mvn/jvm.config b/.mvn/jvm.config
new file mode 100644
index 0000000..af5fbd1
--- /dev/null
+++ b/.mvn/jvm.config
@@ -0,0 +1 @@
+-Xmx1024m -Xms512m -XX:MaxPermSize=256m
diff --git a/LICENSE b/LICENSE
index ccac2ba..ba06157 100644
--- a/LICENSE
+++ b/LICENSE
@@ -235,10 +235,15 @@
Used under the following license: SIL OFL 1.1 (http://scripts.sil.org/OFL)
Copyright (c) Dave Gandy (2016)
-This project includes the software: github.com/codegangsta/cli
- Available at: https://github.com/codegangsta/cli
+This project includes the software: github.com/NodePrime/jsonpath/cli/jsonpath
+ Available at: github.com/NodePrime/jsonpath/
Used under the following license: The MIT License (http://opensource.org/licenses/MIT)
- Copyright (C) 2013 Jeremy Saenz
+ Copyright (c) 2015 NodePrime Inc.
+
+This project includes the software: github.com/urfave/cli
+ Available at: https://github.com/urfave/cli
+ Used under the following license: The MIT License (http://opensource.org/licenses/MIT)
+ Copyright (c) 2016 Jeremy Saenz & Contributors
This project includes the software: golang.org/x/crypto/ssh
Available at: https://godoc.org/golang.org/x/crypto/ssh
@@ -273,6 +278,14 @@
Used under the following license: The MIT License (http://opensource.org/licenses/MIT)
Copyright (c) "Cowboy" Ben Alman (2010)"
+This project includes the software: jQuery hashchange event
+ Available at: http://benalman.com/projects/jquery-hashchange-plugin/
+ Developed by: "Cowboy" Ben Alman (http://benalman.com/)
+ Inclusive of: jquery.ba-bbq*.js
+ Version used: 1.2
+ Used under the following license: The MIT License (http://opensource.org/licenses/MIT)
+ Copyright (c) "Cowboy" Ben Alman (2010)"
+
This project includes the software: DataTables Table plug-in for jQuery
Available at: http://www.datatables.net/
Developed by: SpryMedia Ltd (http://sprymedia.co.uk/)
@@ -283,7 +296,7 @@
This project includes the software: jquery.easy-autocomplete.js
Available at: https://github.com/pawelczak/EasyAutocomplete
- Version used: 1.3.1
+ Version used: 1.3.3
Used under the following license: The MIT License (http://opensource.org/licenses/MIT)
Copyright (c) Łukasz Pawełczak (2015)
diff --git a/examples/global-web-fabric/pom.xml b/examples/global-web-fabric/pom.xml
index c91290d..e44d249 100644
--- a/examples/global-web-fabric/pom.xml
+++ b/examples/global-web-fabric/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.brooklyn.example</groupId>
<artifactId>brooklyn-examples-parent</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/examples/global-web-fabric/src/main/resources/catalog.bom b/examples/global-web-fabric/src/main/resources/catalog.bom
index 4197271..4818153 100644
--- a/examples/global-web-fabric/src/main/resources/catalog.bom
+++ b/examples/global-web-fabric/src/main/resources/catalog.bom
@@ -16,7 +16,7 @@
# under the License.
brooklyn.catalog:
- version: "0.10.0-SNAPSHOT" # BROOKLYN_VERSION
+ version: "0.11.0-SNAPSHOT" # BROOKLYN_VERSION
itemType: template
items:
- id: org.apache.brooklyn.demo.GlobalWebFabricExample
diff --git a/examples/pom.xml b/examples/pom.xml
index 110258b..3b14be3 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -32,7 +32,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/examples/simple-messaging-pubsub/pom.xml b/examples/simple-messaging-pubsub/pom.xml
index 13dc86d..af81ec1 100644
--- a/examples/simple-messaging-pubsub/pom.xml
+++ b/examples/simple-messaging-pubsub/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.brooklyn.example</groupId>
<artifactId>brooklyn-examples-parent</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/examples/simple-nosql-cluster/pom.xml b/examples/simple-nosql-cluster/pom.xml
index 7065cab..a3b3085 100644
--- a/examples/simple-nosql-cluster/pom.xml
+++ b/examples/simple-nosql-cluster/pom.xml
@@ -30,7 +30,7 @@
<parent>
<groupId>org.apache.brooklyn.example</groupId>
<artifactId>brooklyn-examples-parent</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/examples/simple-nosql-cluster/src/main/resources/catalog.bom b/examples/simple-nosql-cluster/src/main/resources/catalog.bom
index f61f9cf..daacaaf 100644
--- a/examples/simple-nosql-cluster/src/main/resources/catalog.bom
+++ b/examples/simple-nosql-cluster/src/main/resources/catalog.bom
@@ -16,7 +16,7 @@
# under the License.
brooklyn.catalog:
- version: "0.10.0-SNAPSHOT" # BROOKLYN_VERSION
+ version: "0.11.0-SNAPSHOT" # BROOKLYN_VERSION
itemType: template
items:
- id: org.apache.brooklyn.demo.RiakClusterExample
diff --git a/examples/simple-web-cluster/pom.xml b/examples/simple-web-cluster/pom.xml
index 6e25fd0..f51df0b 100644
--- a/examples/simple-web-cluster/pom.xml
+++ b/examples/simple-web-cluster/pom.xml
@@ -28,7 +28,7 @@
<parent>
<groupId>org.apache.brooklyn.example</groupId>
<artifactId>brooklyn-examples-parent</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/examples/simple-web-cluster/src/main/resources/catalog.bom b/examples/simple-web-cluster/src/main/resources/catalog.bom
index 901c185..ebe3fa1 100644
--- a/examples/simple-web-cluster/src/main/resources/catalog.bom
+++ b/examples/simple-web-cluster/src/main/resources/catalog.bom
@@ -16,7 +16,7 @@
# under the License.
brooklyn.catalog:
- version: "0.10.0-SNAPSHOT" # BROOKLYN_VERSION
+ version: "0.11.0-SNAPSHOT" # BROOKLYN_VERSION
itemType: template
items:
- id: org.apache.brooklyn.demo.NodeJsTodoApplication
diff --git a/examples/webapps/hello-world-sql/pom.xml b/examples/webapps/hello-world-sql/pom.xml
index 969a1be..c55d0c7 100644
--- a/examples/webapps/hello-world-sql/pom.xml
+++ b/examples/webapps/hello-world-sql/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.brooklyn.example</groupId>
<artifactId>brooklyn-examples-webapps-parent</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/examples/webapps/hello-world-webapp/pom.xml b/examples/webapps/hello-world-webapp/pom.xml
index ac2fe36..98ddce1 100644
--- a/examples/webapps/hello-world-webapp/pom.xml
+++ b/examples/webapps/hello-world-webapp/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.brooklyn.example</groupId>
<artifactId>brooklyn-examples-webapps-parent</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/examples/webapps/hello-world-webapp/src/main/webapp/styles/main.css b/examples/webapps/hello-world-webapp/src/main/webapp/styles/main.css
index 27606d3..b47cd5b 100644
--- a/examples/webapps/hello-world-webapp/src/main/webapp/styles/main.css
+++ b/examples/webapps/hello-world-webapp/src/main/webapp/styles/main.css
@@ -24,7 +24,7 @@
margin: 0;
}
#main{
- background: url('../images/BrooklynBridge3Large.png')fixed;
+ background: url('../images/BrooklynBridge3Large.png');
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
diff --git a/examples/webapps/pom.xml b/examples/webapps/pom.xml
index dc67e86..92d4b01 100644
--- a/examples/webapps/pom.xml
+++ b/examples/webapps/pom.xml
@@ -29,7 +29,7 @@
<parent>
<groupId>org.apache.brooklyn.example</groupId>
<artifactId>brooklyn-examples-parent</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/karaf/catalog/pom.xml b/karaf/catalog/pom.xml
index 2748c47..fe9a1d2 100644
--- a/karaf/catalog/pom.xml
+++ b/karaf/catalog/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library-karaf</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/karaf/catalog/src/main/resources/library-catalog-classes.bom b/karaf/catalog/src/main/resources/library-catalog-classes.bom
index eb46825..525a7d5 100644
--- a/karaf/catalog/src/main/resources/library-catalog-classes.bom
+++ b/karaf/catalog/src/main/resources/library-catalog-classes.bom
@@ -16,7 +16,7 @@
# under the License.
#
brooklyn.catalog:
- version: "0.10.0-SNAPSHOT" # BROOKLYN_VERSION
+ version: "0.11.0-SNAPSHOT" # BROOKLYN_VERSION
include: classpath://catalog-classes.bom
items:
diff --git a/karaf/features/pom.xml b/karaf/features/pom.xml
index c4627bd..390e546 100644
--- a/karaf/features/pom.xml
+++ b/karaf/features/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library-karaf</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
</parent>
<artifactId>brooklyn-library-features</artifactId>
@@ -38,7 +38,7 @@
<plugin>
<groupId>org.apache.karaf.tooling</groupId>
<artifactId>karaf-maven-plugin</artifactId>
- <version>4.0.1</version>
+ <version>${karaf.plugin.version}</version>
<extensions>true</extensions>
</plugin>
</plugins>
diff --git a/karaf/pom.xml b/karaf/pom.xml
index e158869..95ee864 100644
--- a/karaf/pom.xml
+++ b/karaf/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/pom.xml b/pom.xml
index 473feaa..de1452d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,12 +24,11 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-parent</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../brooklyn-server/parent/</relativePath>
</parent>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<packaging>pom</packaging>
<name>Brooklyn Library Root</name>
@@ -45,9 +44,9 @@
</developers>
<scm>
- <connection>scm:git:https://git-wip-us.apache.org/repos/asf/incubator-brooklyn.git</connection>
- <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/incubator-brooklyn.git</developerConnection>
- <url>https://git-wip-us.apache.org/repos/asf?p=incubator-brooklyn.git</url>
+ <connection>scm:git:https://git-wip-us.apache.org/repos/asf/brooklyn-library.git</connection>
+ <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/brooklyn-library.git</developerConnection>
+ <url>https://git-wip-us.apache.org/repos/asf?p=brooklyn-library.git</url>
<tag>HEAD</tag>
</scm>
@@ -57,7 +56,7 @@
</issueManagement>
<ciManagement>
<system>Jenkins</system>
- <url>https://builds.apache.org/job/incubator-brooklyn-master-build/</url>
+ <url>https://builds.apache.org/view/Brooklyn/job/brooklyn-library-master/</url>
</ciManagement>
<mailingLists>
<mailingList>
diff --git a/qa/pom.xml b/qa/pom.xml
index 5a7e255..cbef5e6 100644
--- a/qa/pom.xml
+++ b/qa/pom.xml
@@ -29,7 +29,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedExternalMonitor.java b/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedExternalMonitor.java
new file mode 100644
index 0000000..3424842
--- /dev/null
+++ b/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedExternalMonitor.java
@@ -0,0 +1,57 @@
+/*
+ * 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 org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess;
+import org.apache.brooklyn.util.time.Duration;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.reflect.TypeToken;
+
+@ImplementedBy(SimulatedExternalMonitorImpl.class)
+public interface SimulatedExternalMonitor extends Entity, Startable {
+
+ @SuppressWarnings("serial")
+ ConfigKey<Predicate<? super Entity>> ENTITY_FILTER = ConfigKeys.newConfigKey(
+ new TypeToken<Predicate<? super Entity>>() {},
+ "entityFilter",
+ "Entities to set the sensors on",
+ Predicates.instanceOf(VanillaSoftwareProcess.class));
+
+ ConfigKey<Integer> NUM_SENSORS = ConfigKeys.newIntegerConfigKey(
+ "numSensors",
+ "Number of attribute sensors to set on each entity",
+ 1);
+
+ ConfigKey<Duration> POLL_PERIOD = ConfigKeys.newConfigKey(
+ Duration.class,
+ "pollPeriod",
+ "Period for polling to get the sensors (delay between polls)",
+ Duration.ONE_SECOND);
+
+ AttributeSensor<Boolean> SERVICE_UP = Attributes.SERVICE_UP;
+}
diff --git a/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedExternalMonitorImpl.java b/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedExternalMonitorImpl.java
new file mode 100644
index 0000000..a80c5a5
--- /dev/null
+++ b/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedExternalMonitorImpl.java
@@ -0,0 +1,101 @@
+/*
+ * 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 java.util.Collection;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.core.entity.AbstractEntity;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.util.time.Duration;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+public class SimulatedExternalMonitorImpl extends AbstractEntity implements SimulatedExternalMonitor {
+
+ private ScheduledExecutorService executor;
+ private Future<?> future;
+
+ @Override
+ public void rebind() {
+ super.rebind();
+ if (Boolean.TRUE.equals(sensors().get(SERVICE_UP))) {
+ startPolling();
+ }
+ }
+
+ @Override
+ public void start(Collection<? extends Location> locations) {
+ if (Boolean.TRUE.equals(sensors().get(SERVICE_UP))) {
+ // already up; no-op
+ }
+ sensors().set(SERVICE_UP, true);
+ startPolling();
+ }
+
+ @Override
+ public void stop() {
+ sensors().set(SERVICE_UP, false);
+ stopPolling();
+ }
+
+ @Override
+ public void restart() {
+ stop();
+ start(ImmutableList.<Location>of());
+ }
+
+ protected void startPolling() {
+ Duration pollPeriod = config().get(POLL_PERIOD);
+ executor = Executors.newScheduledThreadPool(1);
+ executor.scheduleWithFixedDelay(new Runnable() {
+ public void run() {
+ simulatePoll();
+ }},
+ 0, pollPeriod.toMilliseconds(), TimeUnit.MILLISECONDS);
+ }
+
+ protected void stopPolling() {
+ if (executor != null) {
+ executor.shutdownNow();
+ executor = null;
+ }
+ }
+
+ protected void simulatePoll() {
+ String val = "val-" + System.currentTimeMillis();
+ Predicate<? super Entity> filter = config().get(ENTITY_FILTER);
+ Integer numSensors = config().get(NUM_SENSORS);
+ Iterable<Entity> entities = Iterables.filter(getManagementContext().getEntityManager().getEntities(), filter);
+ for (Entity entity : entities) {
+ for (int i = 0; i < numSensors; i++) {
+ AttributeSensor<String> sensor = Sensors.newStringSensor("externalSensor"+i);
+ entity.sensors().set(sensor, val);
+ }
+ }
+ }
+}
diff --git a/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedTheeTierApp.java b/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedTheeTierApp.java
index 0e41beb..b0178e5 100644
--- a/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedTheeTierApp.java
+++ b/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedTheeTierApp.java
@@ -33,6 +33,7 @@
import org.apache.brooklyn.core.entity.StartableApplication;
import org.apache.brooklyn.core.entity.trait.Startable;
import org.apache.brooklyn.core.location.PortRanges;
+import org.apache.brooklyn.core.sensor.DependentConfiguration;
import org.apache.brooklyn.enricher.stock.Enrichers;
import org.apache.brooklyn.entity.database.mysql.MySqlNode;
import org.apache.brooklyn.entity.group.DynamicCluster;
@@ -95,7 +96,8 @@
.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))
+ DependentConfiguration.builder().attributeWhenReady(mysql, MySqlNode.DATASTORE_URL).build(),
+ DB_TABLE, DB_USERNAME, DB_PASSWORD))
.configure(DynamicCluster.INITIAL_SIZE, 2)
.configure(WebAppService.ENABLED_PROTOCOLS, ImmutableSet.of(USE_HTTPS ? "https" : "http")) );
diff --git a/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedVanillaSoftwareProcessImpl.java b/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedVanillaSoftwareProcessImpl.java
new file mode 100644
index 0000000..e5aea80
--- /dev/null
+++ b/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedVanillaSoftwareProcessImpl.java
@@ -0,0 +1,220 @@
+/*
+ * 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 java.net.URI;
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
+import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic.ServiceNotUpLogic;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess;
+import org.apache.brooklyn.entity.software.base.VanillaSoftwareProcessImpl;
+import org.apache.brooklyn.entity.software.base.VanillaSoftwareProcessSshDriver;
+import org.apache.brooklyn.feed.function.FunctionFeed;
+import org.apache.brooklyn.feed.function.FunctionPollConfig;
+import org.apache.brooklyn.feed.http.HttpFeed;
+import org.apache.brooklyn.feed.http.HttpPollConfig;
+import org.apache.brooklyn.feed.http.HttpValueFunctions;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.util.time.Duration;
+
+/**
+ * For simulating various aspects of the {@link VanillaSoftwareProcess} entity.
+ *
+ * It is assumed that the ssh commands for install, launch, etc will be written with testability in mind.
+ * For example, they might just be {@code echo} statements, because there is insufficient resources to
+ * run 100s of processes.
+ *
+ * It is thus possible to simulate aspects of the behaviour, for performance and load testing purposes.
+ *
+ * There is configuration for:
+ * <ul>
+ * <li>{@code skipSshOnStart}
+ * <ul>
+ * <li>If 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.
+ * <li>If false, the ssh commands will be executed.
+ * </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>
+ * </ul>
+ */
+public class SimulatedVanillaSoftwareProcessImpl extends VanillaSoftwareProcessImpl {
+
+ public static final ConfigKey<Boolean> EXEC_SSH_ON_START = ConfigKeys.newBooleanConfigKey(
+ "execSshOnStart",
+ "If true, will execute the ssh commands on install/launch; if false, will skip them",
+ true);
+
+ public static final ConfigKey<URI> HTTP_FEED_URI = ConfigKeys.newConfigKey(
+ URI.class,
+ "httpFeed.uri",
+ "If non-null, the URI to poll periodically using a HttpFeed", null);
+
+ public static final ConfigKey<Duration> HTTP_FEED_POLL_PERIOD = ConfigKeys.newConfigKey(
+ Duration.class,
+ "httpFeed.pollPeriod",
+ "The poll priod for the HttpFeed (if 'httpFeed.uri' was non-null)",
+ Duration.ONE_SECOND);
+
+ public static final ConfigKey<Duration> FUNCTION_FEED_POLL_PERIOD = ConfigKeys.newConfigKey(
+ Duration.class,
+ "functionFeed.pollPeriod",
+ "The poll priod for a function that increments 'counter' periodically (if null, then no-op)",
+ Duration.ONE_SECOND);
+
+ // see SERVICE_PROCESS_IS_RUNNING_POLL_PERIOD
+ // Inspired by EmptySoftwareProcess.USE_SSH_MONITORING
+ public static final ConfigKey<Boolean> USE_SSH_MONITORING = ConfigKeys.newConfigKey(
+ "sshMonitoring.enabled",
+ "Whether to poll periodically over ssh, using the driver.isRunning check",
+ Boolean.TRUE);
+
+ private static final AttributeSensor<String> HTTP_STRING_ATTRIBUTE = Sensors.newStringSensor("httpStringAttribute");
+
+ private static final AttributeSensor<Integer> HTTP_INT_ATTRIBUTE = Sensors.newIntegerSensor("httpIntAttribute");
+
+ private static final AttributeSensor<Long> FUNCTION_COUNTER = Sensors.newLongSensor("functionCounter");
+
+ private FunctionFeed functionFeed;
+ private HttpFeed httpFeed;
+
+ @Override
+ public void init() {
+ super.init();
+ if (Boolean.FALSE.equals(config().get(EXEC_SSH_ON_START))) {
+ config().set(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, true);
+ }
+ }
+
+ @Override
+ public Class<?> getDriverInterface() {
+ return SimulatedVanillaSoftwareProcessSshDriver.class;
+ }
+
+ @Override
+ protected void connectServiceUpIsRunning() {
+ boolean useSshMonitoring = Boolean.TRUE.equals(config().get(USE_SSH_MONITORING));
+ if (useSshMonitoring) {
+ super.connectServiceUpIsRunning();
+ }
+ }
+
+ @Override
+ protected void initEnrichers() {
+ super.initEnrichers();
+ }
+
+ @Override
+ protected void connectSensors() {
+ super.connectSensors();
+
+ boolean useSshMonitoring = Boolean.TRUE.equals(config().get(USE_SSH_MONITORING));
+ Duration functionFeedPeriod = config().get(FUNCTION_FEED_POLL_PERIOD);
+ URI httpFeedUri = config().get(HTTP_FEED_URI);
+
+ if (!useSshMonitoring) {
+ ServiceNotUpLogic.clearNotUpIndicator(this, SERVICE_PROCESS_IS_RUNNING);
+ }
+
+ if (functionFeedPeriod != null) {
+ functionFeed = feeds().add(FunctionFeed.builder()
+ .entity(this)
+ .period(functionFeedPeriod)
+ .poll(FunctionPollConfig.forSensor(FUNCTION_COUNTER)
+ .callable(new Callable<Long>() {
+ @Override public Long call() throws Exception {
+ Long oldVal = sensors().get(FUNCTION_COUNTER);
+ return (oldVal == null) ? 1 : oldVal + 1;
+ }
+ }))
+ .build());
+ }
+
+ if (httpFeedUri != null) {
+ httpFeed = feeds().add(HttpFeed.builder()
+ .entity(this)
+ .period(config().get(HTTP_FEED_POLL_PERIOD))
+ .baseUri(httpFeedUri)
+ .poll(new HttpPollConfig<Integer>(HTTP_INT_ATTRIBUTE)
+ .onSuccess(HttpValueFunctions.responseCode()))
+ .poll(new HttpPollConfig<String>(HTTP_STRING_ATTRIBUTE)
+ .onSuccess(HttpValueFunctions.stringContentsFunction()))
+ .build());
+ }
+ }
+
+ @Override
+ protected void disconnectSensors() {
+ super.disconnectSensors();
+ if (functionFeed != null) functionFeed.stop();
+ if (httpFeed != null) httpFeed.stop();
+ }
+
+ public static class SimulatedVanillaSoftwareProcessSshDriver extends VanillaSoftwareProcessSshDriver {
+ public SimulatedVanillaSoftwareProcessSshDriver(SimulatedVanillaSoftwareProcessImpl entity, SshMachineLocation machine) {
+ super(entity, machine);
+ }
+
+ @Override
+ public void install() {
+ if (Boolean.TRUE.equals(entity.getConfig(EXEC_SSH_ON_START))) {
+ super.install();
+ } else {
+ // no-op
+ }
+ }
+
+ @Override
+ public void customize() {
+ if (Boolean.TRUE.equals(entity.getConfig(EXEC_SSH_ON_START))) {
+ super.customize();
+ } else {
+ // no-op
+ }
+ }
+
+ @Override
+ public void launch() {
+ if (Boolean.TRUE.equals(entity.getConfig(EXEC_SSH_ON_START))) {
+ super.launch();
+ } else {
+ // no-op
+ }
+ }
+ }
+}
diff --git a/qa/src/test/java/org/apache/brooklyn/qa/load/AbstractLoadTest.java b/qa/src/test/java/org/apache/brooklyn/qa/load/AbstractLoadTest.java
new file mode 100644
index 0000000..c07f329
--- /dev/null
+++ b/qa/src/test/java/org/apache/brooklyn/qa/load/AbstractLoadTest.java
@@ -0,0 +1,378 @@
+/*
+ * 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 org.testng.Assert.assertEquals;
+
+import java.io.File;
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.ha.HighAvailabilityMode;
+import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.core.entity.StartableApplication;
+import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.core.location.PortRanges;
+import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
+import org.apache.brooklyn.core.mgmt.persist.PersistMode;
+import org.apache.brooklyn.core.test.HttpService;
+import org.apache.brooklyn.entity.group.DynamicCluster;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.policy.autoscaling.AutoScalerPolicy;
+import org.apache.brooklyn.test.performance.PerformanceTestUtils;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.os.Os;
+import org.apache.brooklyn.util.time.Duration;
+import org.apache.brooklyn.util.time.Time;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Predicate;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+/**
+ * Customers ask about the scalability of Brooklyn. These load tests investigate how many
+ * concurrent apps can be deployed and managed by a single Brooklyn management node.
+ *
+ * The apps are "simulated" in that they don't create the underlying resources
+ * (we are not checking if the test machine can run 100s of app-servers simultaneously!)
+ *
+ * See the configuration options on {@link SimulatedVanillaSoftwareProcessImpl}.
+ *
+ * The {@link SimulatedExternalMonitor} is used to simulate us not polling the entities directly
+ * (over ssh, http or whatever). Instead we simulate the metrics being retrieved from some external
+ * source, and injected directly into the entities by calling {@code sensors().set()}. For example,
+ * this could be collected from a Graphite server.
+ *
+ * If using {@link TestConfig#simulateExternalMonitor(Predicate, int, Duration)}, it will
+ * automatically turn off {@code useSshMonitoring}, {@code useHttpMonitoring} and
+ * {@code useFunctionMonitoring} for <em>all</em> entities (not just for those that match
+ * the predicate passed to simulateExternalMonitor).
+ */
+public class AbstractLoadTest extends AbstractYamlTest {
+
+ // TODO Could/should issue provisioning request through REST api, rather than programmatically;
+ // and poll to detect completion.
+
+ /*
+ * Useful commands when investigating:
+ * LOG_FILE=usage/qa/brooklyn-camp-tests.log
+ * grep -E "OutOfMemoryError|[P|p]rovisioning time|sleeping before|CPU fraction|LoadTest using" $LOG_FILE | less
+ * grep -E "OutOfMemoryError|[P|p]rovisioning time" $LOG_FILE; grep "CPU fraction" $LOG_FILE | tail -1; grep "LoadTest using" $LOG_FILE | tail -1
+ * grep -E "OutOfMemoryError|LoadTest using" $LOG_FILE
+ */
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractLoadTest.class);
+
+ private File persistenceDir;
+ private BrooklynLauncher launcher;
+ private ListeningExecutorService executor;
+ private Future<?> cpuFuture;
+
+ private Location localhost;
+
+ List<Duration> provisioningTimes;
+
+ private HttpService httpService;
+ private URI httpServiceUri;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ super.setUp();
+
+ localhost = mgmt().getLocationRegistry().getLocationManaged("localhost");
+
+ provisioningTimes = Collections.synchronizedList(Lists.<Duration>newArrayList());
+
+ // Create executors
+ executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
+
+ // Monitor utilisation (memory/CPU) while tests run
+ executor.submit(new Callable<Void>() {
+ public Void call() {
+ try {
+ mgmt().getExecutionManager(); // force GC to be instantiated
+ while (true) {
+ String usage = ((LocalManagementContext)mgmt()).getGarbageCollector().getUsageString();
+ LOG.info("LoadTest using "+usage);
+ Thread.sleep(1000);
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt(); // exit gracefully
+ } catch (Exception e) {
+ LOG.error("Error getting usage info", e);
+ }
+ return null;
+ }});
+
+ cpuFuture = PerformanceTestUtils.sampleProcessCpuTime(Duration.ONE_SECOND, "during LoadTest");
+
+ httpService = new HttpService(PortRanges.fromString("9000+"), true).start();
+ httpServiceUri = new URI(httpService.getUrl());
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ try {
+ if (httpService != null) httpService.shutdown();
+ if (cpuFuture != null) cpuFuture.cancel(true);
+ if (executor != null) executor.shutdownNow();
+ } finally {
+ super.tearDown();
+ }
+ }
+
+ @Override
+ protected ManagementContext setUpPlatform() {
+ // Create management node
+ persistenceDir = Files.createTempDir();
+ launcher = BrooklynLauncher.newInstance()
+ .persistMode(PersistMode.CLEAN)
+ .highAvailabilityMode(HighAvailabilityMode.MASTER)
+ .persistenceDir(persistenceDir)
+ .start();
+
+ String webServerUrl = launcher.getServerDetails().getWebServerUrl();
+ LOG.info("Brooklyn web-console running at " + webServerUrl);
+
+ return launcher.getServerDetails().getManagementContext();
+ }
+
+ @Override
+ protected void tearDownPlatform() {
+ if (launcher != null) launcher.terminate();
+ if (persistenceDir != null) Os.deleteRecursively(persistenceDir);
+ }
+
+ public static class TestConfig {
+ public int totalApps = 1;
+ public int numAppsPerBatch = 1;
+ public Duration sleepBetweenBatch = Duration.ZERO;
+
+ int clusterSize = 2;
+
+ boolean simulateExternalMonitor = false;
+ Predicate<? super Entity> externalMonitorFilter;
+ int externalMonitorNumSensors;
+ Duration externalMonitorPollPeriod;
+
+
+ boolean execSshOnStart = SimulatedVanillaSoftwareProcessImpl.EXEC_SSH_ON_START.getDefaultValue();
+ Duration functionFeedPollPeriod = SimulatedVanillaSoftwareProcessImpl.FUNCTION_FEED_POLL_PERIOD.getDefaultValue();
+ boolean useSshMonitoring = SimulatedVanillaSoftwareProcessImpl.USE_SSH_MONITORING.getDefaultValue();
+ Duration httpFeedPollPeriod = SimulatedVanillaSoftwareProcessImpl.HTTP_FEED_POLL_PERIOD.getDefaultValue();
+ URI httpFeedUri;
+
+ public TestConfig(AbstractLoadTest tester) {
+ httpFeedUri = tester.httpServiceUri;
+ }
+ public TestConfig simulateExternalMonitor(Predicate<? super Entity> filter, int numSensors, Duration pollPeriod) {
+ simulateExternalMonitor = true;
+ externalMonitorFilter = filter;
+ externalMonitorNumSensors = numSensors;
+ externalMonitorPollPeriod = pollPeriod;
+ useSshMonitoring(false);
+ useHttpMonitoring(false);
+ useFunctionMonitoring(false);
+ return this;
+ }
+ public TestConfig totalApps(int totalApps) {
+ return totalApps(totalApps, totalApps);
+ }
+ public TestConfig totalApps(int totalApps, int numAppsPerBatch) {
+ this.totalApps = totalApps;
+ this.numAppsPerBatch = numAppsPerBatch;
+ return this;
+ }
+ public TestConfig sleepBetweenBatch(Duration val) {
+ sleepBetweenBatch = val;
+ return this;
+ }
+ public TestConfig clusterSize(int val) {
+ clusterSize = val;
+ return this;
+ }
+ public TestConfig execSshOnStart(boolean val) {
+ execSshOnStart = val;
+ return this;
+ }
+ public TestConfig useSshMonitoring(boolean val) {
+ useSshMonitoring = val;
+ return this;
+ }
+ public TestConfig useHttpMonitoring(boolean val) {
+ if (val) {
+ if (httpFeedUri == null) {
+ throw new IllegalStateException("No HTTP URI; expected to be set by AbstractLoadTest.httpServiceUri");
+ }
+ } else {
+ httpFeedUri = null;
+ }
+ return this;
+ }
+ public TestConfig useFunctionMonitoring(boolean val) {
+ if (val) {
+ functionFeedPollPeriod = SimulatedVanillaSoftwareProcessImpl.FUNCTION_FEED_POLL_PERIOD.getDefaultValue();
+ } else {
+ functionFeedPollPeriod = null;
+ }
+ return this;
+ }
+ }
+
+ protected void runLocalhostManyApps(TestConfig config) throws Exception {
+ final int totalApps = config.totalApps;
+ final int numAppsPerBatch = config.numAppsPerBatch;
+ final int numCycles = (totalApps / numAppsPerBatch);
+ final Duration sleepBetweenBatch = config.sleepBetweenBatch;
+
+ int counter = 0;
+
+ if (config.simulateExternalMonitor) {
+ SimulatedExternalMonitor externalMonitor = mgmt().getEntityManager().createEntity(EntitySpec.create(SimulatedExternalMonitor.class)
+ .configure(SimulatedExternalMonitor.ENTITY_FILTER, config.externalMonitorFilter)
+ .configure(SimulatedExternalMonitor.NUM_SENSORS, config.externalMonitorNumSensors)
+ .configure(SimulatedExternalMonitor.POLL_PERIOD, config.externalMonitorPollPeriod));
+ externalMonitor.start(ImmutableList.<Location>of());
+ }
+ for (int i = 0; i < numCycles; i++) {
+ List<ListenableFuture<? extends Entity>> futures = Lists.newArrayList();
+ for (int j = 0; j < numAppsPerBatch; j++) {
+ String yamlApp = newYamlApp("Simulated App " + i, config);
+
+ ListenableFuture<? extends Entity> future = executor.submit(newProvisionAppTask(yamlApp));
+ futures.add(future);
+ counter++;
+ }
+
+ List<? extends Entity> apps = Futures.allAsList(futures).get();
+
+ for (Entity app : apps) {
+ assertEquals(app.getAttribute(Startable.SERVICE_UP), (Boolean)true);
+ }
+
+ synchronized (provisioningTimes) {
+ LOG.info("cycle="+i+"; numApps="+counter+": provisioning times: "+provisioningTimes);
+ provisioningTimes.clear();
+ }
+
+ LOG.info("cycle="+i+"; numApps="+counter+": sleeping for "+sleepBetweenBatch+" before next batch of apps");
+ Time.sleep(sleepBetweenBatch);
+ }
+ }
+
+ protected String newYamlApp(String appName, TestConfig config) {
+ return Joiner.on("\n").join(
+ "name: " + appName,
+ "location: localhost",
+
+ "services:",
+ "- type: " + DynamicCluster.class.getName(),
+ " id: cluster",
+ " brooklyn.config:",
+ " cluster.initial.size: " + config.clusterSize,
+ " memberSpec:",
+ " $brooklyn:entitySpec:",
+ " type: " + SimulatedVanillaSoftwareProcessImpl.class.getName(),
+ " brooklyn.config:",
+ " shell.env:",
+ " ENV1: val1",
+ " ENV2: val2",
+ " install.command: echo myInstallCommand",
+ " customize.command: echo myCustomizeCommand",
+ " launch.command: echo myLaunchCommand",
+ " checkRunning.command: echo myCheckRunningCommand",
+ " " + SimulatedVanillaSoftwareProcessImpl.EXEC_SSH_ON_START.getName() + ": " + config.execSshOnStart,
+ " " + SimulatedVanillaSoftwareProcessImpl.USE_SSH_MONITORING.getName() + ": " + config.useSshMonitoring,
+ " " + SimulatedVanillaSoftwareProcessImpl.FUNCTION_FEED_POLL_PERIOD.getName() + ": " + config.functionFeedPollPeriod,
+ " " + SimulatedVanillaSoftwareProcessImpl.HTTP_FEED_POLL_PERIOD.getName() + ": " + config.httpFeedPollPeriod,
+ " " + (config.httpFeedUri != null ? SimulatedVanillaSoftwareProcessImpl.HTTP_FEED_URI.getName() + ": " + config.httpFeedUri : ""),
+ " brooklyn.enrichers:",
+ " - type: org.apache.brooklyn.enricher.stock.Aggregator",
+ " brooklyn.config:",
+ " enricher.sourceSensor: counter",
+ " enricher.targetSensor: counter",
+ " transformation: sum",
+ " brooklyn.policies:",
+ " - type: " + AutoScalerPolicy.class.getName(),
+ " brooklyn.config:",
+ " metric: sensorDoesNotExist",
+ " metricLowerBound: 1",
+ " metricUpperBound: 3",
+ " minPoolSize: " + config.clusterSize,
+ " maxPoolSize: " + (config.clusterSize + 3));
+ }
+
+ protected Callable<Entity> newProvisionAppTask(final String yaml) {
+ return new Callable<Entity>() {
+ public Entity call() throws Exception {
+ try {
+ Stopwatch stopwatch = Stopwatch.createStarted();
+ Entity app = createAndStartApplication(yaml);
+ Duration duration = Duration.of(stopwatch.elapsed(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS);
+ LOG.info("Provisioning time: "+duration);
+ provisioningTimes.add(duration);
+
+ return app;
+ } catch (Throwable t) {
+ LOG.error("Error deploying app (rethrowing)", t);
+ throw Exceptions.propagate(t);
+ }
+ }
+ };
+ }
+
+ protected <T extends StartableApplication> Callable<T> newProvisionAppTask(final EntitySpec<T> appSpec) {
+ return new Callable<T>() {
+ public T call() {
+ try {
+ Stopwatch stopwatch = Stopwatch.createStarted();
+ T app = mgmt().getEntityManager().createEntity(appSpec);
+ app.start(ImmutableList.of(localhost));
+ Duration duration = Duration.of(stopwatch.elapsed(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS);
+ LOG.info("Provisioning time: "+duration);
+ provisioningTimes.add(duration);
+
+ return app;
+ } catch (Throwable t) {
+ LOG.error("Error deploying app (rethrowing)", t);
+ throw Exceptions.propagate(t);
+ }
+ }
+ };
+ }
+}
diff --git a/qa/src/test/java/org/apache/brooklyn/qa/load/LoadSanityTest.java b/qa/src/test/java/org/apache/brooklyn/qa/load/LoadSanityTest.java
new file mode 100644
index 0000000..5f082f2
--- /dev/null
+++ b/qa/src/test/java/org/apache/brooklyn/qa/load/LoadSanityTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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 org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess;
+import org.apache.brooklyn.util.time.Duration;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicates;
+
+/**
+ * A trivially small "load" test, which just checks that our test is actually working.
+ * It deploys just one app.
+ */
+public class LoadSanityTest extends AbstractLoadTest {
+
+ @Test(groups="Integration")
+ public void testApp() throws Exception {
+ super.runLocalhostManyApps(new TestConfig(this)
+ .execSshOnStart(true) // default is true, but be explicit
+ .useSshMonitoring(true) // default is true, but be explicit
+ .useHttpMonitoring(true) // default is true, but be explicit
+ .useFunctionMonitoring(true) // default is true, but be explicit
+ .totalApps(1));
+ }
+
+ @Test(groups="Integration")
+ public void testAppExternallyMonitored() throws Exception {
+ super.runLocalhostManyApps(new TestConfig(this)
+ .simulateExternalMonitor(Predicates.instanceOf(VanillaSoftwareProcess.class), 5, Duration.ONE_SECOND)
+ .useSshMonitoring(false)
+ .useHttpMonitoring(false)
+ .useFunctionMonitoring(false)
+ .totalApps(1));
+ }
+}
diff --git a/qa/src/test/java/org/apache/brooklyn/qa/load/LoadTest.java b/qa/src/test/java/org/apache/brooklyn/qa/load/LoadTest.java
index cc779a9..50ffb6b 100644
--- a/qa/src/test/java/org/apache/brooklyn/qa/load/LoadTest.java
+++ b/qa/src/test/java/org/apache/brooklyn/qa/load/LoadTest.java
@@ -18,135 +18,15 @@
*/
package org.apache.brooklyn.qa.load;
-import static org.testng.Assert.assertEquals;
-
-import java.io.File;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
-import org.apache.brooklyn.api.mgmt.ha.HighAvailabilityMode;
-import org.apache.brooklyn.core.entity.Entities;
-import org.apache.brooklyn.core.entity.StartableApplication;
-import org.apache.brooklyn.core.entity.trait.Startable;
-import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
-import org.apache.brooklyn.core.mgmt.persist.PersistMode;
-import org.apache.brooklyn.launcher.BrooklynLauncher;
-import org.apache.brooklyn.test.PerformanceTestUtils;
-import org.apache.brooklyn.util.os.Os;
+import org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess;
+import org.apache.brooklyn.qa.load.AbstractLoadTest.TestConfig;
import org.apache.brooklyn.util.time.Duration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.common.io.Files;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.base.Predicates;
-/**
- * Customers ask about the scalability of Brooklyn. These load tests investigate how many
- * concurrent apps can be deployed and managed by a single Brooklyn management node.
- *
- * The apps are "simulated" in that they don't create the underlying resources
- * (we are not checking if the test machine can run 100s of app-servers simultaneously!)
- * The install/customize/launch will instead execute ssh commands of comparable length,
- * but that just echo rather than execute the actual commands.
- *
- * "SIMULATE_EXTERNAL_MONITORING" means that we do not poll the entities directly (over ssh, http or
- * whatever). Instead we simulate the metrics being injected directly to be set on the entity (e.g.
- * having been collected from a Graphite server).
- *
- * "SKIP_SSH_ON_START" means don't do the normal install+customize+launch ssh commands. Instead, just
- * startup the entities so we can monitor their resource usage.
- */
-public class LoadTest {
+public class LoadTest extends AbstractLoadTest {
- // TODO Could/should issue provisioning request through REST api, rather than programmatically;
- // and poll to detect completion.
-
- /*
- * Useful commands when investigating:
- * LOG_FILE=usage/qa/brooklyn-camp-tests.log
- * grep -E "OutOfMemoryError|[P|p]rovisioning time|sleeping before|CPU fraction|LoadTest using" $LOG_FILE | less
- * grep -E "OutOfMemoryError|[P|p]rovisioning time" $LOG_FILE; grep "CPU fraction" $LOG_FILE | tail -1; grep "LoadTest using" $LOG_FILE | tail -1
- * grep -E "OutOfMemoryError|LoadTest using" $LOG_FILE
- */
- private static final Logger LOG = LoggerFactory.getLogger(LoadTest.class);
-
- private File persistenceDir;
- private BrooklynLauncher launcher;
- private String webServerUrl;
- private ManagementContext managementContext;
- private ListeningExecutorService executor;
- private Future<?> cpuFuture;
-
- private Location localhost;
-
- List<Duration> provisioningTimes;
-
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- // Create management node
- persistenceDir = Files.createTempDir();
- launcher = BrooklynLauncher.newInstance()
- .persistMode(PersistMode.CLEAN)
- .highAvailabilityMode(HighAvailabilityMode.MASTER)
- .persistenceDir(persistenceDir)
- .start();
- webServerUrl = launcher.getServerDetails().getWebServerUrl();
- managementContext = launcher.getServerDetails().getManagementContext();
-
- localhost = managementContext.getLocationRegistry().getLocationManaged("localhost");
-
- provisioningTimes = Collections.synchronizedList(Lists.<Duration>newArrayList());
-
- // Create executors
- executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
-
- // Monitor utilisation (memory/CPU) while tests run
- executor.submit(new Callable<Void>() {
- public Void call() {
- try {
- while (true) {
- managementContext.getExecutionManager(); // force GC to be instantiated
- String usage = ((LocalManagementContext)managementContext).getGarbageCollector().getUsageString();
- LOG.info("LoadTest using "+usage);
- Thread.sleep(1000);
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt(); // exit gracefully
- } catch (Exception e) {
- LOG.error("Error getting usage info", e);
- }
- return null;
- }});
-
- cpuFuture = PerformanceTestUtils.sampleProcessCpuTime(Duration.ONE_SECOND, "during testProvisionAppsConcurrently");
-
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- if (cpuFuture != null) cpuFuture.cancel(true);
- if (executor != null) executor.shutdownNow();
- if (launcher != null) launcher.terminate();
- if (persistenceDir != null) Os.deleteRecursively(persistenceDir);
- }
-
/**
* Creates multiple apps simultaneously.
*
@@ -158,84 +38,35 @@
* TODO Does not measure the cost of jclouds for creating all the VMs/containers.
*/
@Test(groups="Acceptance")
- public void testLocalhostProvisioningAppsConcurrently() throws Exception {
- final int NUM_CONCURRENT_APPS_PROVISIONING = 20;
-
- List<ListenableFuture<StartableApplication>> futures = Lists.newArrayList();
- for (int i = 0; i < NUM_CONCURRENT_APPS_PROVISIONING; i++) {
- ListenableFuture<StartableApplication> future = executor.submit(newProvisionAppTask(managementContext,
- EntitySpec.create(StartableApplication.class, SimulatedTheeTierApp.class)
- .configure(SimulatedTheeTierApp.SIMULATE_EXTERNAL_MONITORING, true)
- .displayName("Simulated app "+i)));
- futures.add(future);
- }
-
- List<StartableApplication> apps = Futures.allAsList(futures).get();
-
- for (StartableApplication app : apps) {
- assertEquals(app.getAttribute(Startable.SERVICE_UP), (Boolean)true);
- }
+ public void testProvisioningConcurrently() throws Exception {
+ // TODO Getting ssh error (SocketException: Connection reset) with 10 entities, if don't disable ssh-on-start.
+ // Will still execute checkRunning to wait for process to start (even if execSshOnStart is false).
+ super.runLocalhostManyApps(new TestConfig(this)
+ .useSshMonitoring(false)
+ .execSshOnStart(false) // getting ssh errors otherwise!
+ .totalApps(10));
}
-
+
/**
* Creates many apps, to monitor resource usage etc.
*
- * "SIMULATE_EXTERNAL_MONITORING" means that we do not poll the entities directly (over ssh, http or
- * whatever). Instead we simulate the metrics being injected directly to be set on the entity (e.g.
- * having been collected from a Graphite server).
- *
* Long-term target is 2500 VMs under management.
* Until we reach that point, we can partition the load across multiple (separate) brooklyn management nodes.
*/
@Test(groups="Acceptance")
- public void testLocalhostManyApps() throws Exception {
- final int NUM_APPS = 630; // target is 2500 VMs; each blueprint has 4 (rounding up)
+ public void testManyAppsExternallyMonitored() throws Exception {
+ // TODO Getting ssh error ("Server closed connection during identification exchange")
+ // with only two cycles (i.e. 20 entities).
+ //
+ // The ssh activity is from `SoftwareProcessImpl.waitForEntityStart`, which calls
+ // `VanillaSoftwareProcessSshDriver.isRunning`.
+ final int TOTAL_APPS = 600; // target is 2500 VMs; each blueprint has 2 VanillaSoftwareProcess
final int NUM_APPS_PER_BATCH = 10;
- final int SLEEP_BETWEEN_BATCHES = 10*1000;
- final boolean SKIP_SSH_ON_START = true; // getting ssh errors otherwise!
-
- int counter = 0;
-
- for (int i = 0; i < NUM_APPS / NUM_APPS_PER_BATCH; i++) {
- List<ListenableFuture<StartableApplication>> futures = Lists.newArrayList();
- for (int j = 0; j < NUM_APPS_PER_BATCH; j++) {
- ListenableFuture<StartableApplication> future = executor.submit(newProvisionAppTask(
- managementContext,
- EntitySpec.create(StartableApplication.class, SimulatedTheeTierApp.class)
- .configure(SimulatedTheeTierApp.SIMULATE_EXTERNAL_MONITORING, true)
- .configure(SimulatedTheeTierApp.SKIP_SSH_ON_START, SKIP_SSH_ON_START)
- .displayName("Simulated app "+(++counter))));
- futures.add(future);
- }
-
- List<StartableApplication> apps = Futures.allAsList(futures).get();
-
- for (StartableApplication app : apps) {
- assertEquals(app.getAttribute(Startable.SERVICE_UP), (Boolean)true);
- }
-
- synchronized (provisioningTimes) {
- LOG.info("cycle="+i+"; numApps="+counter+": provisioning times: "+provisioningTimes);
- provisioningTimes.clear();
- }
-
- LOG.info("cycle="+i+"; numApps="+counter+": sleeping before next batch of apps");
- Thread.sleep(SLEEP_BETWEEN_BATCHES);
- }
- }
-
- protected <T extends StartableApplication> Callable<T> newProvisionAppTask(final ManagementContext managementContext, final EntitySpec<T> appSpec) {
- return new Callable<T>() {
- public T call() {
- Stopwatch stopwatch = Stopwatch.createStarted();
- T app = managementContext.getEntityManager().createEntity(appSpec);
- app.start(ImmutableList.of(localhost));
- Duration duration = Duration.of(stopwatch.elapsed(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS);
- LOG.info("Provisioning time: "+duration);
- provisioningTimes.add(duration);
-
- return app;
- }
- };
+ super.runLocalhostManyApps(new TestConfig(this)
+ .execSshOnStart(false) // getting ssh errors otherwise!
+ .simulateExternalMonitor(Predicates.instanceOf(VanillaSoftwareProcess.class), 5, Duration.ONE_SECOND)
+ .clusterSize(2)
+ .totalApps(TOTAL_APPS, NUM_APPS_PER_BATCH)
+ .sleepBetweenBatch(Duration.TEN_SECONDS));
}
}
diff --git a/qa/src/test/projects/downstream-parent-test/pom.xml b/qa/src/test/projects/downstream-parent-test/pom.xml
index a679026..801ad7b 100644
--- a/qa/src/test/projects/downstream-parent-test/pom.xml
+++ b/qa/src/test/projects/downstream-parent-test/pom.xml
@@ -23,7 +23,7 @@
<groupId>org.apache.brooklyn.downstream-parent-test</groupId>
<artifactId>catalogue-load-test</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<packaging>jar</packaging>
<name>Downstream parent catalogue load test test</name>
@@ -31,7 +31,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-downstream-parent</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
</parent>
<repositories>
@@ -62,7 +62,7 @@
<dependency>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-all</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<scope>provided</scope>
</dependency>
</dependencies>
diff --git a/qa/src/test/projects/downstream-parent-test/src/main/resources/catalog.bom b/qa/src/test/projects/downstream-parent-test/src/main/resources/catalog.bom
index 49510be..ac976c9 100644
--- a/qa/src/test/projects/downstream-parent-test/src/main/resources/catalog.bom
+++ b/qa/src/test/projects/downstream-parent-test/src/main/resources/catalog.bom
@@ -16,7 +16,7 @@
# under the License.
brooklyn.catalog:
- version: "0.10.0-SNAPSHOT" # BROOKLYN_VERSION
+ version: "0.11.0-SNAPSHOT" # BROOKLYN_VERSION
itemType: entity
items:
- id: com.example.HelloEntity
diff --git a/qa/src/test/resources/java-web-app-and-db-with-policy.bom b/qa/src/test/resources/java-web-app-and-db-with-policy.bom
index 8568f8b..f29757b 100644
--- a/qa/src/test/resources/java-web-app-and-db-with-policy.bom
+++ b/qa/src/test/resources/java-web-app-and-db-with-policy.bom
@@ -20,7 +20,7 @@
# standalone catalog file
brooklyn.catalog:
- version: "0.10.0-SNAPSHOT" # BROOKLYN_VERSION
+ version: "0.11.0-SNAPSHOT" # BROOKLYN_VERSION
items:
- id: java-cluster-db-policy-example
itemType: template
diff --git a/qa/start-monitor.sh b/qa/start-monitor.sh
index 3340b09..e5852fd 100755
--- a/qa/start-monitor.sh
+++ b/qa/start-monitor.sh
@@ -25,7 +25,7 @@
#set -x # debug
CLASS=org.apache.brooklyn.qa.longevity.Monitor
-VERSION=0.10.0-SNAPSHOT # BROOKLYN_VERSION
+VERSION=0.11.0-SNAPSHOT # BROOKLYN_VERSION
ROOT=$(cd $(dirname $0) && pwd)
cd $ROOT
diff --git a/qa/start-webcluster.sh b/qa/start-webcluster.sh
index c7eda34..ec2a4fa 100755
--- a/qa/start-webcluster.sh
+++ b/qa/start-webcluster.sh
@@ -25,7 +25,7 @@
#set -x # debug
CLASS=org.apache.brooklyn.qa.longevity.webcluster.WebClusterApp
-VERSION=0.10.0-SNAPSHOT # BROOKLYN_VERSION
+VERSION=0.11.0-SNAPSHOT # BROOKLYN_VERSION
ROOT=$(cd $(dirname $0) && pwd)
cd $ROOT
diff --git a/sandbox/cassandra-multicloud-snitch/pom.xml b/sandbox/cassandra-multicloud-snitch/pom.xml
index f1a49f4..62f5d9f 100644
--- a/sandbox/cassandra-multicloud-snitch/pom.xml
+++ b/sandbox/cassandra-multicloud-snitch/pom.xml
@@ -29,7 +29,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/sandbox/database/pom.xml b/sandbox/database/pom.xml
index cdd5f02..54a328f 100644
--- a/sandbox/database/pom.xml
+++ b/sandbox/database/pom.xml
@@ -31,7 +31,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbySchema.java b/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbySchema.java
index 07417a5..67b2a40 100644
--- a/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbySchema.java
+++ b/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbySchema.java
@@ -31,7 +31,6 @@
import org.apache.brooklyn.entity.database.Schema;
import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntityLocal;
import org.apache.brooklyn.entity.java.UsesJmx;
import org.apache.brooklyn.feed.jmx.JmxAttributePollConfig;
import org.apache.brooklyn.feed.jmx.JmxFeed;
@@ -104,7 +103,7 @@
exchange = new ObjectName(format("org.apache.derby:type=VirtualHost.Exchange,VirtualHost=\"%s\",name=\"amq.direct\",ExchangeType=direct", virtualHost));
create();
- jmxHelper = new JmxHelper((EntityLocal)getParent());
+ jmxHelper = new JmxHelper(getParent());
ObjectName schemaMBeanName = new ObjectName(format("org.apache.derby:type=VirtualHost.Schema,VirtualHost=\"%s\",name=\"%s\"", virtualHost, name));
diff --git a/sandbox/extra/pom.xml b/sandbox/extra/pom.xml
index d308833..eeebd44 100644
--- a/sandbox/extra/pom.xml
+++ b/sandbox/extra/pom.xml
@@ -31,7 +31,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/sandbox/mobile-app/pom.xml b/sandbox/mobile-app/pom.xml
index 60f26ad..3a40f13 100644
--- a/sandbox/mobile-app/pom.xml
+++ b/sandbox/mobile-app/pom.xml
@@ -35,7 +35,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version><!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version><!-- BROOKLYN_VERSION -->
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/sandbox/monitoring/pom.xml b/sandbox/monitoring/pom.xml
index 0298913..b9dd2ce 100644
--- a/sandbox/monitoring/pom.xml
+++ b/sandbox/monitoring/pom.xml
@@ -31,7 +31,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/sandbox/monitoring/src/main/resources/catalog.bom b/sandbox/monitoring/src/main/resources/catalog.bom
index 97704d3..6a8f064 100644
--- a/sandbox/monitoring/src/main/resources/catalog.bom
+++ b/sandbox/monitoring/src/main/resources/catalog.bom
@@ -16,7 +16,7 @@
# under the License.
brooklyn.catalog:
- version: "0.10.0-SNAPSHOT" # BROOKLYN_VERSION
+ version: "0.11.0-SNAPSHOT" # BROOKLYN_VERSION
items:
- id: org.apache.brooklyn.entity.monitoring.zabbix.ZabbixServer
item:
diff --git a/sandbox/nosql/pom.xml b/sandbox/nosql/pom.xml
index c821cb9..ae97aa8 100644
--- a/sandbox/nosql/pom.xml
+++ b/sandbox/nosql/pom.xml
@@ -32,7 +32,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/software/cm/ansible/pom.xml b/software/cm/ansible/pom.xml
index 6d55478..7054b39 100644
--- a/software/cm/ansible/pom.xml
+++ b/software/cm/ansible/pom.xml
@@ -30,7 +30,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleLifecycleEffectorTasks.java b/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleLifecycleEffectorTasks.java
index fd73c61..b2a104a 100644
--- a/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleLifecycleEffectorTasks.java
+++ b/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleLifecycleEffectorTasks.java
@@ -18,7 +18,8 @@
*/
package org.apache.brooklyn.entity.cm.ansible;
-import com.google.common.base.Supplier;
+import static org.apache.brooklyn.util.ssh.BashCommands.sudo;
+
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks;
@@ -35,14 +36,14 @@
import org.apache.brooklyn.util.core.task.DynamicTasks;
import org.apache.brooklyn.util.guava.Maybe;
import org.apache.brooklyn.util.net.Urls;
-
-import static org.apache.brooklyn.util.ssh.BashCommands.sudo;
import org.apache.brooklyn.util.text.Strings;
import org.apache.brooklyn.util.time.Duration;
import org.apache.brooklyn.util.time.Time;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Supplier;
+
public class AnsibleLifecycleEffectorTasks extends MachineLifecycleEffectorTasks implements AnsibleConfig {
private static final Logger LOG = LoggerFactory.getLogger(AnsibleLifecycleEffectorTasks.class);
@@ -135,6 +136,7 @@
}
+ @Override
protected void postStartCustom() {
boolean result = false;
result |= tryCheckStartService();
@@ -173,11 +175,12 @@
.setOnFailureOrException(false))
.build();
- entity().feeds().addFeed(serviceSshFeed);
+ entity().feeds().add(serviceSshFeed);
} else {
LOG.warn("Location(s) {} not an ssh-machine location, so not polling for status; "
+ "setting serviceUp immediately", entity().getLocations());
}
+ super.postStartCustom();
}
protected boolean tryCheckStartService() {
diff --git a/software/cm/ansible/src/main/resources/catalog.bom b/software/cm/ansible/src/main/resources/catalog.bom
index 68f453d..e4f6a06 100644
--- a/software/cm/ansible/src/main/resources/catalog.bom
+++ b/software/cm/ansible/src/main/resources/catalog.bom
@@ -16,7 +16,7 @@
# under the License.
brooklyn.catalog:
- version: "0.10.0-SNAPSHOT" # BROOKLYN_VERSION
+ version: "0.11.0-SNAPSHOT" # BROOKLYN_VERSION
itemType: entity
items:
- id: org.apache.brooklyn.entity.cm.ansible.AnsibleEntity
diff --git a/software/cm/pom.xml b/software/cm/pom.xml
index 0bfde48..3cfbe2b 100644
--- a/software/cm/pom.xml
+++ b/software/cm/pom.xml
@@ -25,13 +25,13 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../../pom.xml</relativePath>
</parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-software-cm</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<packaging>pom</packaging>
<name>Brooklyn CM Integration Root</name>
diff --git a/software/cm/salt/pom.xml b/software/cm/salt/pom.xml
index a5ba926..8e95954 100644
--- a/software/cm/salt/pom.xml
+++ b/software/cm/salt/pom.xml
@@ -30,7 +30,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/software/cm/salt/src/main/java/org/apache/brooklyn/entity/cm/salt/impl/SaltHighstate.java b/software/cm/salt/src/main/java/org/apache/brooklyn/entity/cm/salt/impl/SaltHighstate.java
index e48c0b2..fdae93b 100644
--- a/software/cm/salt/src/main/java/org/apache/brooklyn/entity/cm/salt/impl/SaltHighstate.java
+++ b/software/cm/salt/src/main/java/org/apache/brooklyn/entity/cm/salt/impl/SaltHighstate.java
@@ -73,7 +73,7 @@
private static String adaptForSaltYamlTypes(String description) {
- return description.replaceAll("!!python/unicode", "!!java.lang.String");
+ return description.replaceAll("!!python/unicode\\s+", "");
}
@SuppressWarnings("unchecked")
diff --git a/software/cm/salt/src/main/java/org/apache/brooklyn/entity/cm/salt/impl/SaltLifecycleEffectorTasks.java b/software/cm/salt/src/main/java/org/apache/brooklyn/entity/cm/salt/impl/SaltLifecycleEffectorTasks.java
index 871caea..49fd336 100644
--- a/software/cm/salt/src/main/java/org/apache/brooklyn/entity/cm/salt/impl/SaltLifecycleEffectorTasks.java
+++ b/software/cm/salt/src/main/java/org/apache/brooklyn/entity/cm/salt/impl/SaltLifecycleEffectorTasks.java
@@ -18,21 +18,26 @@
*/
package org.apache.brooklyn.entity.cm.salt.impl;
-import com.google.common.annotations.Beta;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableMap;
+import static java.util.regex.Pattern.DOTALL;
+import static java.util.regex.Pattern.MULTILINE;
+import static org.apache.brooklyn.entity.software.base.SoftwareProcess.StopSoftwareParameters.StopMode.ALWAYS;
+import static org.apache.brooklyn.entity.software.base.SoftwareProcess.StopSoftwareParameters.StopMode.NEVER;
+
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
import org.apache.brooklyn.api.effector.Effector;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.mgmt.TaskAdaptable;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
-import org.apache.brooklyn.entity.cm.salt.SaltConfig;
import org.apache.brooklyn.core.effector.Effectors;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic;
import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.entity.cm.salt.SaltConfig;
import org.apache.brooklyn.entity.software.base.SoftwareProcess;
import org.apache.brooklyn.entity.software.base.SoftwareProcess.StopSoftwareParameters;
import org.apache.brooklyn.entity.software.base.lifecycle.MachineLifecycleEffectorTasks;
@@ -46,14 +51,10 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static java.util.regex.Pattern.DOTALL;
-import static java.util.regex.Pattern.MULTILINE;
-import static org.apache.brooklyn.entity.software.base.SoftwareProcess.StopSoftwareParameters.StopMode.ALWAYS;
-import static org.apache.brooklyn.entity.software.base.SoftwareProcess.StopSoftwareParameters.StopMode.NEVER;
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
@Beta
public class SaltLifecycleEffectorTasks extends MachineLifecycleEffectorTasks implements SaltConfig {
@@ -165,10 +166,11 @@
SaltHighstate.applyHighstate(stateDescription, entity());
}
-
+ @Override
protected void postStartCustom() {
// TODO: check for package installed?
entity().sensors().set(SoftwareProcess.SERVICE_UP, true);
+ super.postStartCustom();
}
diff --git a/software/cm/salt/src/main/resources/catalog.bom b/software/cm/salt/src/main/resources/catalog.bom
index afe09ab..acd9556 100644
--- a/software/cm/salt/src/main/resources/catalog.bom
+++ b/software/cm/salt/src/main/resources/catalog.bom
@@ -16,7 +16,7 @@
# under the License.
brooklyn.catalog:
- version: "0.10.0-SNAPSHOT" # BROOKLYN_VERSION
+ version: "0.11.0-SNAPSHOT" # BROOKLYN_VERSION
itemType: entity
items:
- id: org.apache.brooklyn.entity.cm.salt.SaltEntity
diff --git a/software/database/pom.xml b/software/database/pom.xml
index faf5a8d..b2818d6 100644
--- a/software/database/pom.xml
+++ b/software/database/pom.xml
@@ -29,7 +29,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/software/database/src/main/java/org/apache/brooklyn/entity/database/mariadb/MariaDbNode.java b/software/database/src/main/java/org/apache/brooklyn/entity/database/mariadb/MariaDbNode.java
index 3c78d99..bd06c6f 100644
--- a/software/database/src/main/java/org/apache/brooklyn/entity/database/mariadb/MariaDbNode.java
+++ b/software/database/src/main/java/org/apache/brooklyn/entity/database/mariadb/MariaDbNode.java
@@ -42,7 +42,7 @@
@SetFromFlag("version")
public static final ConfigKey<String> SUGGESTED_VERSION =
- ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION, "5.5.40");
+ ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION, "5.5.53");
// https://downloads.mariadb.org/interstitial/mariadb-5.5.33a/kvm-bintar-hardy-amd64/mariadb-5.5.33a-linux-x86_64.tar.gz/from/http://mirrors.coreix.net/mariadb
// above redirects to download the artifactd from the URLs below.
@@ -57,7 +57,7 @@
/** download mirror, if desired */
@SetFromFlag("mirrorUrl")
public static final ConfigKey<String> MIRROR_URL = ConfigKeys.newStringConfigKey("mariadb.install.mirror.url", "URL of mirror",
- "http://mirrors.coreix.net/mariadb/"
+ "http://mirrors.coreix.net/mariadb"
);
@SetFromFlag("port")
diff --git a/software/database/src/main/java/org/apache/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java b/software/database/src/main/java/org/apache/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java
index 86a8bfb..4c960a6 100644
--- a/software/database/src/main/java/org/apache/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java
+++ b/software/database/src/main/java/org/apache/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java
@@ -78,7 +78,7 @@
String cmd = getDriver().getStatusCmd();
feed = SshFeed.builder()
.entity(this)
- .period(Duration.FIVE_SECONDS)
+ .period(config().get(SERVICE_PROCESS_IS_RUNNING_POLL_PERIOD))
.machine(machine.get())
.poll(new SshPollConfig<Boolean>(SERVICE_UP)
.command(cmd)
diff --git a/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlClusterImpl.java b/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlClusterImpl.java
index d356fc5..cbc0272 100644
--- a/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlClusterImpl.java
+++ b/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlClusterImpl.java
@@ -29,7 +29,6 @@
import javax.annotation.Nullable;
import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntityLocal;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.sensor.AttributeSensor;
@@ -205,11 +204,10 @@
protected Entity createNode(Location loc, Map<?, ?> flags) {
MySqlNode node = (MySqlNode) super.createNode(loc, flags);
if (!MySqlClusterUtils.IS_MASTER.apply(node)) {
- EntityLocal localNode = (EntityLocal) node;
- ServiceNotUpLogic.updateNotUpIndicator(localNode, MySqlSlave.SLAVE_HEALTHY, "Replication not started");
+ ServiceNotUpLogic.updateNotUpIndicator(node, MySqlSlave.SLAVE_HEALTHY, "Replication not started");
addFeed(FunctionFeed.builder()
- .entity(localNode)
+ .entity(node)
.period(Duration.FIVE_SECONDS)
.poll(FunctionPollConfig.forSensor(MySqlSlave.SLAVE_HEALTHY)
.callable(new SlaveStateCallable(node))
@@ -310,7 +308,6 @@
DynamicTasks.submitTopLevelTask(TaskBuilder.builder()
.displayName("setup master-slave replication")
.body(nodeInitTaskBody)
- .tag(BrooklynTaskTags.tagForContextEntity(node))
.tag(BrooklynTaskTags.NON_TRANSIENT_TASK_TAG)
.build(),
node);
diff --git a/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlNodeImpl.java b/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlNodeImpl.java
index 8a4c177..d71d5e1 100644
--- a/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlNodeImpl.java
+++ b/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlNodeImpl.java
@@ -107,7 +107,7 @@
String cmd = getDriver().getStatusCmd();
feed = SshFeed.builder()
.entity(this)
- .period(Duration.FIVE_SECONDS)
+ .period(config().get(SERVICE_PROCESS_IS_RUNNING_POLL_PERIOD))
.machine(machine.get())
.poll(new SshPollConfig<Double>(QUERIES_PER_SECOND_FROM_MYSQL)
.command(cmd)
diff --git a/software/database/src/main/java/org/apache/brooklyn/entity/database/postgresql/PostgreSqlNodeChefImplFromScratch.java b/software/database/src/main/java/org/apache/brooklyn/entity/database/postgresql/PostgreSqlNodeChefImplFromScratch.java
index 96e65a5..0c52f20 100644
--- a/software/database/src/main/java/org/apache/brooklyn/entity/database/postgresql/PostgreSqlNodeChefImplFromScratch.java
+++ b/software/database/src/main/java/org/apache/brooklyn/entity/database/postgresql/PostgreSqlNodeChefImplFromScratch.java
@@ -32,8 +32,6 @@
import org.apache.brooklyn.entity.stock.EffectorStartableImpl;
import org.apache.brooklyn.feed.ssh.SshFeed;
import org.apache.brooklyn.feed.ssh.SshPollConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.apache.brooklyn.location.ssh.SshMachineLocation;
import org.apache.brooklyn.util.collections.Jsonya;
import org.apache.brooklyn.util.core.ResourceUtils;
@@ -41,6 +39,8 @@
import org.apache.brooklyn.util.core.task.DynamicTasks;
import org.apache.brooklyn.util.guava.Maybe;
import org.apache.brooklyn.util.ssh.BashCommands;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class PostgreSqlNodeChefImplFromScratch extends EffectorStartableImpl implements PostgreSqlNode {
@@ -77,6 +77,7 @@
usePidFile("/var/run/postgresql/*.pid");
useService("postgresql");
}
+ @Override
protected void startWithKnifeAsync() {
Entities.warnOnIgnoringConfig(entity(), ChefConfig.CHEF_LAUNCH_RUN_LIST);
Entities.warnOnIgnoringConfig(entity(), ChefConfig.CHEF_LAUNCH_ATTRIBUTES);
@@ -95,9 +96,8 @@
// no other arguments currenty supported; chef will pick a password for us
);
}
+ @Override
protected void postStartCustom() {
- super.postStartCustom();
-
// now run the creation script
String creationScript;
String creationScriptUrl = entity().getConfig(PostgreSqlNode.CREATION_SCRIPT_URL);
@@ -110,11 +110,14 @@
// and finally connect sensors
entity().connectSensors();
+ super.postStartCustom();
}
+ @Override
protected void preStopCustom() {
entity().disconnectSensors();
super.preStopCustom();
}
+ @Override
protected PostgreSqlNodeChefImplFromScratch entity() {
return (PostgreSqlNodeChefImplFromScratch) super.entity();
}
diff --git a/software/database/src/main/resources/catalog.bom b/software/database/src/main/resources/catalog.bom
index 7d65e6b..6f24a9e 100644
--- a/software/database/src/main/resources/catalog.bom
+++ b/software/database/src/main/resources/catalog.bom
@@ -16,7 +16,7 @@
# under the License.
brooklyn.catalog:
- version: "0.10.0-SNAPSHOT" # BROOKLYN_VERSION
+ version: "0.11.0-SNAPSHOT" # BROOKLYN_VERSION
itemType: entity
items:
- id: org.apache.brooklyn.entity.database.crate.CrateNode
diff --git a/software/messaging/pom.xml b/software/messaging/pom.xml
index d9984be..bf80c61 100644
--- a/software/messaging/pom.xml
+++ b/software/messaging/pom.xml
@@ -29,7 +29,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../../pom.xml</relativePath>
</parent>
@@ -219,9 +219,22 @@
<groupId>storm</groupId>
<artifactId>carbonite</artifactId>
</exclusion>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>log4j-over-slf4j</artifactId>
+ </exclusion>
</exclusions>
</dependency>
+ <dependency>
+ <!-- We exclude jsr311-api transitive dependency from jclouds (for javax.ws.rs) due to version conflict.
+ Therefore explicitly bring this one in.
+ -->
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+
<!-- Transitive dependencies, declared explicitly due to version mismatch -->
<dependency>
<groupId>log4j</groupId>
diff --git a/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/activemq/ActiveMQDestinationImpl.java b/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/activemq/ActiveMQDestinationImpl.java
index 6a27030..559a193 100644
--- a/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/activemq/ActiveMQDestinationImpl.java
+++ b/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/activemq/ActiveMQDestinationImpl.java
@@ -21,9 +21,6 @@
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntityLocal;
-
import com.google.common.base.Preconditions;
import org.apache.brooklyn.entity.messaging.jms.JMSDestinationImpl;
@@ -48,7 +45,7 @@
try {
brokerMBeanName = new ObjectName("org.apache.activemq:type=Broker,brokerName=" + brokerName);
- jmxHelper = new JmxHelper((EntityLocal) getParent());
+ jmxHelper = new JmxHelper(getParent());
} catch (MalformedObjectNameException e) {
throw Exceptions.propagate(e);
}
diff --git a/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/qpid/QpidDestinationImpl.java b/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/qpid/QpidDestinationImpl.java
index d475c5e..b514321 100644
--- a/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/qpid/QpidDestinationImpl.java
+++ b/software/messaging/src/main/java/org/apache/brooklyn/entity/messaging/qpid/QpidDestinationImpl.java
@@ -25,7 +25,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.brooklyn.api.entity.EntityLocal;
import org.apache.brooklyn.entity.java.UsesJmx;
import org.apache.brooklyn.entity.messaging.amqp.AmqpServer;
import org.apache.brooklyn.entity.messaging.jms.JMSDestinationImpl;
@@ -63,7 +62,7 @@
if (virtualHost == null) virtualHost = getConfig(QpidBroker.VIRTUAL_HOST_NAME);
sensors().set(QpidBroker.VIRTUAL_HOST_NAME, virtualHost);
virtualHostManager = new ObjectName(format("org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost=\"%s\"", virtualHost));
- jmxHelper = new JmxHelper((EntityLocal)getParent());
+ jmxHelper = new JmxHelper(getParent());
} catch (MalformedObjectNameException e) {
throw Exceptions.propagate(e);
}
diff --git a/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/AbstractZooKeeperImpl.java b/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/AbstractZooKeeperImpl.java
index 60175c9..b3ced27 100644
--- a/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/AbstractZooKeeperImpl.java
+++ b/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/AbstractZooKeeperImpl.java
@@ -94,9 +94,9 @@
@Override
public void disconnectSensors() {
- super.disconnectSensors();
- disconnectServiceUpIsRunning();
if (jmxFeed != null) jmxFeed.stop();
+ disconnectServiceUpIsRunning();
+ super.disconnectSensors();
}
@Override
diff --git a/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperEnsemble.java b/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperEnsemble.java
index a5ba570..487d639 100644
--- a/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperEnsemble.java
+++ b/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperEnsemble.java
@@ -29,7 +29,10 @@
import org.apache.brooklyn.core.sensor.Sensors;
import org.apache.brooklyn.entity.group.DynamicCluster;
import org.apache.brooklyn.util.core.flags.SetFromFlag;
+import org.apache.brooklyn.util.guava.Suppliers;
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
import com.google.common.reflect.TypeToken;
@Catalog(name="ZooKeeper ensemble", description="A cluster of ZooKeeper servers. "
@@ -38,15 +41,26 @@
public interface ZooKeeperEnsemble extends DynamicCluster {
@SetFromFlag("clusterName")
- BasicAttributeSensorAndConfigKey<String> CLUSTER_NAME = new BasicAttributeSensorAndConfigKey<String>(String
- .class, "zookeeper.cluster.name", "Name of the Zookeeper cluster", "BrooklynZookeeperCluster");
+ BasicAttributeSensorAndConfigKey<String> CLUSTER_NAME = new BasicAttributeSensorAndConfigKey<String>(String.class,
+ "zookeeper.cluster.name", "Name of the Zookeeper cluster", "BrooklynZookeeperCluster");
@SetFromFlag("initialSize")
- public static final ConfigKey<Integer> INITIAL_SIZE = ConfigKeys.newConfigKeyWithDefault(DynamicCluster.INITIAL_SIZE, 3);
+ ConfigKey<Integer> INITIAL_SIZE = ConfigKeys.newConfigKeyWithDefault(DynamicCluster.INITIAL_SIZE, 3);
- @SuppressWarnings("serial")
+ ConfigKey<Supplier<Integer>> NODE_ID_SUPPLIER = ConfigKeys.builder(new TypeToken<Supplier<Integer>>() {})
+ .name("zookeeper.nodeId.supplier")
+ .description("Supplies values for members id in zoo.cfg")
+ .defaultValue(Suppliers.incrementing())
+ .constraint(Predicates.notNull())
+ .build();
+
AttributeSensor<List<String>> ZOOKEEPER_SERVERS = Sensors.newSensor(new TypeToken<List<String>>() { },
"zookeeper.servers", "Hostnames to connect to cluster with");
+ AttributeSensor<String> ZOOKEEPER_ENDPOINTS = Sensors.newStringSensor(
+ "zookeeper.endpoints", "A comma-separated host:port list of members of the ensemble");
+
+ /** @deprecated since 0.10.0 use <code>sensors().get(ZooKeeperEnsemble.CLUSTER_NAME)</code> instead */
+ @Deprecated
String getClusterName();
}
diff --git a/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperEnsembleImpl.java b/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperEnsembleImpl.java
index c2c3e3f..2588921 100644
--- a/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperEnsembleImpl.java
+++ b/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperEnsembleImpl.java
@@ -18,38 +18,31 @@
*/
package org.apache.brooklyn.entity.zookeeper;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.api.sensor.EnricherSpec;
import org.apache.brooklyn.core.entity.Attributes;
-import org.apache.brooklyn.core.entity.EntityInternal;
+import org.apache.brooklyn.enricher.stock.Enrichers;
import org.apache.brooklyn.entity.group.AbstractMembershipTrackingPolicy;
import org.apache.brooklyn.entity.group.DynamicClusterImpl;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.brooklyn.util.guava.Suppliers;
-import com.google.common.collect.Lists;
+import com.google.common.base.Supplier;
public class ZooKeeperEnsembleImpl extends DynamicClusterImpl implements ZooKeeperEnsemble {
- private static final Logger log = LoggerFactory.getLogger(ZooKeeperEnsembleImpl.class);
- private static final AtomicInteger myId = new AtomicInteger();
-
- private MemberTrackingPolicy policy;
-
public ZooKeeperEnsembleImpl() {}
/**
* Sets the default {@link #MEMBER_SPEC} to describe the ZooKeeper nodes.
+ * Overwrites any value configured for {@link ZooKeeperNode#MY_ID} to use
+ * the value given by {@link ZooKeeperEnsemble#NODE_ID_SUPPLIER}.
*/
@Override
protected EntitySpec<?> getMemberSpec() {
- return getConfig(MEMBER_SPEC, EntitySpec.create(ZooKeeperNode.class));
+ EntitySpec<?> spec = getConfig(MEMBER_SPEC, EntitySpec.create(ZooKeeperNode.class));
+ spec.configure(ZooKeeperNode.MY_ID, config().get(ZooKeeperEnsemble.NODE_ID_SUPPLIER).get());
+ return spec;
}
@Override
@@ -58,47 +51,48 @@
}
@Override
- public void init() {
- log.info("Initializing the ZooKeeper Ensemble");
- super.init();
-
- policy = policies().add(PolicySpec.create(MemberTrackingPolicy.class)
- .displayName("Members tracker")
- .configure("group", this));
+ protected void initEnrichers() {
+ super.initEnrichers();
+ EnricherSpec<?> zks = Enrichers.builder()
+ .aggregating(ZooKeeperNode.ZOOKEEPER_ENDPOINT)
+ .publishing(ZOOKEEPER_SERVERS)
+ .fromMembers()
+ .build();
+ EnricherSpec<?> zke = Enrichers.builder()
+ .joining(ZOOKEEPER_SERVERS)
+ .publishing(ZOOKEEPER_ENDPOINTS)
+ .quote(false)
+ .separator(",")
+ .build();
+ enrichers().add(zks);
+ enrichers().add(zke);
}
- public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
- @Override
- protected void onEntityChange(Entity member) {
- }
+ /**
+ * @deprecated since 0.10.0 class is unused but kept for persistence backwards compatibility
+ */
+ @Deprecated
+ private static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
+ private final Object[] mutex = new Object[0];
@Override
protected void onEntityAdded(Entity member) {
- if (member.getAttribute(ZooKeeperNode.MY_ID) == null) {
- ((EntityInternal) member).sensors().set(ZooKeeperNode.MY_ID, myId.incrementAndGet());
+ if (member.config().get(ZooKeeperNode.MY_ID) == null) {
+ Supplier<Integer> id;
+ synchronized (mutex) {
+ // Entities may not have been created with NODE_ID_SUPPLIER, so create it if
+ // it's not there. We can't provide any good guarantees about what number to
+ // start with, but then again the previous version of the entity gave no
+ // guarantee either.
+ id = entity.config().get(ZooKeeperEnsemble.NODE_ID_SUPPLIER);
+ if (id == null) {
+ id = Suppliers.incrementing();
+ entity.config().set(ZooKeeperEnsemble.NODE_ID_SUPPLIER, id);
+ }
+ }
+ member.config().set(ZooKeeperNode.MY_ID, id.get());
}
}
-
- @Override
- protected void onEntityRemoved(Entity member) {
- }
- };
-
- @Override
- protected void initEnrichers() {
- super.initEnrichers();
-
- }
-
- @Override
- public void start(Collection<? extends Location> locations) {
- super.start(locations);
-
- List<String> zookeeperServers = Lists.newArrayList();
- for (Entity zookeeper : getMembers()) {
- zookeeperServers.add(zookeeper.getAttribute(Attributes.HOSTNAME));
- }
- sensors().set(ZOOKEEPER_SERVERS, zookeeperServers);
}
}
diff --git a/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperNode.java b/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperNode.java
index 0dce3b7..54ed432 100644
--- a/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperNode.java
+++ b/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperNode.java
@@ -24,6 +24,7 @@
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey;
+import org.apache.brooklyn.core.sensor.BasicAttributeSensorAndConfigKey;
import org.apache.brooklyn.core.sensor.PortAttributeSensorAndConfigKey;
import org.apache.brooklyn.core.sensor.Sensors;
import org.apache.brooklyn.entity.software.base.SoftwareProcess;
@@ -38,14 +39,14 @@
public interface ZooKeeperNode extends SoftwareProcess {
@SetFromFlag("version")
- ConfigKey<String> SUGGESTED_VERSION = ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION, "3.4.5");
+ ConfigKey<String> SUGGESTED_VERSION = ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION, "3.4.9");
@SetFromFlag("archiveNameFormat")
ConfigKey<String> ARCHIVE_DIRECTORY_NAME_FORMAT = ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.ARCHIVE_DIRECTORY_NAME_FORMAT, "zookeeper-%s");
@SetFromFlag("downloadUrl")
AttributeSensorAndConfigKey<String, String> DOWNLOAD_URL = ConfigKeys.newSensorAndConfigKeyWithDefault(SoftwareProcess.DOWNLOAD_URL,
- "http://apache.fastbull.org/zookeeper/zookeeper-${version}/zookeeper-${version}.tar.gz");
+ "http://apache.org/dyn/closer.cgi?action=download&filename=zookeeper/zookeeper-${version}/zookeeper-${version}.tar.gz");
@SetFromFlag("zookeeperPort")
PortAttributeSensorAndConfigKey ZOOKEEPER_PORT = ConfigKeys.newPortSensorAndConfigKey("zookeeper.port", "Zookeeper port", "2181+");
@@ -64,12 +65,22 @@
"zookeeper.configTemplate", "Zookeeper configuration template (in freemarker format)",
"classpath://org/apache/brooklyn/entity/messaging/zookeeper/zoo.cfg");
+ @SetFromFlag("zookeeperId")
+ BasicAttributeSensorAndConfigKey<Integer> MY_ID = new BasicAttributeSensorAndConfigKey<>(Integer.class,
+ "zookeeper.myid", "ZooKeeper node's myId", 1);
+
AttributeSensor<Long> OUTSTANDING_REQUESTS = Sensors.newLongSensor("zookeeper.outstandingRequests", "Outstanding request count");
AttributeSensor<Long> PACKETS_RECEIVED = Sensors.newLongSensor("zookeeper.packets.received", "Total packets received");
AttributeSensor<Long> PACKETS_SENT = Sensors.newLongSensor("zookeeper.packets.sent", "Total packets sent");
- AttributeSensor<Integer> MY_ID = Sensors.newIntegerSensor("zookeeper.myid", "ZooKeeper node's myId");
+ AttributeSensor<String> ZOOKEEPER_ENDPOINT = Sensors.newStringSensor(
+ "zookeeper.endpoint", "The host:port of the node");
+
+ /** @deprecated since 0.10.0 use <code>sensors().get(ZooKeeperNode.ZOOKEEPER_PORT)</code> instead */
+ @Deprecated
Integer getZookeeperPort();
+ /** @deprecated since 0.10.0 use <code>sensors().get(ZooKeeperNode.HOSTNAME)</code> instead */
+ @Deprecated
String getHostname();
}
diff --git a/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperNodeImpl.java b/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperNodeImpl.java
index 275e101..718e360 100644
--- a/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperNodeImpl.java
+++ b/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperNodeImpl.java
@@ -18,6 +18,13 @@
*/
package org.apache.brooklyn.entity.zookeeper;
+import java.net.URI;
+
+import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.core.location.access.BrooklynAccessUtils;
+
+import com.google.common.net.HostAndPort;
+
/**
* An {@link org.apache.brooklyn.api.entity.Entity} that represents a single standalone zookeeper instance.
*/
@@ -26,8 +33,27 @@
public ZooKeeperNodeImpl() {}
@Override
+ public void init() {
+ super.init();
+ // MY_ID was changed from a sensor to config. Publish it as a sensor to maintain
+ // compatibility with any blueprints that reference it.
+ Integer myId = config().get(MY_ID);
+ if (myId == null) {
+ throw new NullPointerException("Require value for " + MY_ID.getName());
+ }
+ sensors().set(MY_ID, myId);
+ }
+
+ @Override
public Class<?> getDriverInterface() {
return ZooKeeperDriver.class;
}
+ @Override
+ protected void postStart() {
+ super.postStart();
+ HostAndPort hap = BrooklynAccessUtils.getBrooklynAccessibleAddress(this, sensors().get(ZOOKEEPER_PORT));
+ sensors().set(ZooKeeperNode.ZOOKEEPER_ENDPOINT, hap.toString());
+ sensors().set(Attributes.MAIN_URI, URI.create("zk://" +hap.toString()));
+ }
}
diff --git a/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperSshDriver.java b/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperSshDriver.java
index 87bf3ff..c7b1dc9 100644
--- a/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperSshDriver.java
+++ b/software/messaging/src/main/java/org/apache/brooklyn/entity/zookeeper/ZooKeeperSshDriver.java
@@ -54,25 +54,32 @@
return entity.getConfig(ZooKeeperNode.ZOOKEEPER_CONFIG_TEMPLATE);
}
- protected int getMyId() {
- return entity.getAttribute(ZooKeeperNode.MY_ID);
+ protected Integer getMyId() {
+ return entity.config().get(ZooKeeperNode.MY_ID);
}
// FIXME All for one, and one for all! If any node fails then we're stuck waiting for its hostname/port forever.
// Need a way to terminate the wait based on the entity going on-fire etc.
// FIXME Race in getMemebers. Should we change DynamicCluster.grow to create the members and only then call start on them all?
public List<ZooKeeperServerConfig> getZookeeperServers() throws ExecutionException, InterruptedException {
- ZooKeeperEnsemble ensemble = (ZooKeeperEnsemble) entity.getParent();
List<ZooKeeperServerConfig> result = Lists.newArrayList();
- for (Entity member : ensemble.getMembers()) {
- Integer myid = Entities.attributeSupplierWhenReady(member, ZooKeeperNode.MY_ID).get();
- String hostname = Entities.attributeSupplierWhenReady(member, ZooKeeperNode.HOSTNAME).get();
- Integer port = Entities.attributeSupplierWhenReady(member, ZooKeeperNode.ZOOKEEPER_PORT).get();
- Integer leaderPort = Entities.attributeSupplierWhenReady(member, ZooKeeperNode.ZOOKEEPER_LEADER_PORT).get();
- Integer electionPort = Entities.attributeSupplierWhenReady(member, ZooKeeperNode.ZOOKEEPER_ELECTION_PORT).get();
- result.add(new ZooKeeperServerConfig(myid, hostname, port, leaderPort, electionPort));
+ if (entity.getParent() instanceof ZooKeeperEnsemble) {
+ ZooKeeperEnsemble ensemble = (ZooKeeperEnsemble) entity.getParent();
+
+ for (Entity member : ensemble.getMembers()) {
+ Integer memberId = member.config().get(ZooKeeperNode.MY_ID);
+ if (memberId == null) {
+ throw new IllegalStateException(member + " has null value for " + ZooKeeperNode.MY_ID);
+ }
+ String hostname = Entities.attributeSupplierWhenReady(member, ZooKeeperNode.HOSTNAME).get();
+ Integer port = Entities.attributeSupplierWhenReady(member, ZooKeeperNode.ZOOKEEPER_PORT).get();
+ Integer leaderPort = Entities.attributeSupplierWhenReady(member, ZooKeeperNode.ZOOKEEPER_LEADER_PORT).get();
+ Integer electionPort = Entities.attributeSupplierWhenReady(member, ZooKeeperNode.ZOOKEEPER_ELECTION_PORT).get();
+ result.add(new ZooKeeperServerConfig(memberId, hostname, port, leaderPort, electionPort));
+ }
}
+
return result;
}
diff --git a/software/messaging/src/main/resources/catalog.bom b/software/messaging/src/main/resources/catalog.bom
index ec884ca..8209cc6 100644
--- a/software/messaging/src/main/resources/catalog.bom
+++ b/software/messaging/src/main/resources/catalog.bom
@@ -16,7 +16,7 @@
# under the License.
brooklyn.catalog:
- version: "0.10.0-SNAPSHOT" # BROOKLYN_VERSION
+ version: "0.11.0-SNAPSHOT" # BROOKLYN_VERSION
itemType: entity
items:
- id: org.apache.brooklyn.entity.messaging.activemq.ActiveMQBroker
diff --git a/software/messaging/src/test/java/org/apache/brooklyn/entity/messaging/zookeeper/ZooKeeperEc2LiveTest.java b/software/messaging/src/test/java/org/apache/brooklyn/entity/messaging/zookeeper/ZooKeeperEc2LiveTest.java
index f3557d1..5a435f0 100644
--- a/software/messaging/src/test/java/org/apache/brooklyn/entity/messaging/zookeeper/ZooKeeperEc2LiveTest.java
+++ b/software/messaging/src/test/java/org/apache/brooklyn/entity/messaging/zookeeper/ZooKeeperEc2LiveTest.java
@@ -18,16 +18,18 @@
*/
package org.apache.brooklyn.entity.messaging.zookeeper;
+import static org.testng.Assert.assertEquals;
+
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.EntityAsserts;
import org.apache.brooklyn.core.entity.trait.Startable;
-import org.testng.annotations.Test;
import org.apache.brooklyn.entity.AbstractEc2LiveTest;
import org.apache.brooklyn.entity.zookeeper.ZooKeeperNode;
+import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
+import com.google.common.net.HostAndPort;
public class ZooKeeperEc2LiveTest extends AbstractEc2LiveTest {
@@ -36,10 +38,17 @@
*/
@Override
protected void doTest(Location loc) throws Exception {
- ZooKeeperNode zookeeper = app.createAndManageChild(EntitySpec.create(ZooKeeperNode.class).configure("jmxPort", "31001+"));
+ ZooKeeperNode zookeeper = app.createAndManageChild(EntitySpec.create(ZooKeeperNode.class)
+ .configure("jmxPort", "31001+"));
app.start(ImmutableList.of(loc));
- Entities.dumpInfo(zookeeper);
EntityAsserts.assertAttributeEqualsEventually(zookeeper, Startable.SERVICE_UP, true);
+ HostAndPort conn = HostAndPort.fromParts(
+ zookeeper.sensors().get(ZooKeeperNode.HOSTNAME),
+ zookeeper.sensors().get(ZooKeeperNode.ZOOKEEPER_PORT));
+ try (ZooKeeperTestSupport zkts = new ZooKeeperTestSupport(conn)) {
+ zkts.create("/ec2livetest", "data".getBytes());
+ assertEquals(new String(zkts.get("/ec2livetest")), "data");
+ }
}
@Test(enabled=false)
diff --git a/software/messaging/src/test/java/org/apache/brooklyn/entity/messaging/zookeeper/ZooKeeperEnsembleLiveTest.java b/software/messaging/src/test/java/org/apache/brooklyn/entity/messaging/zookeeper/ZooKeeperEnsembleLiveTest.java
index 2721976..52b4d08 100644
--- a/software/messaging/src/test/java/org/apache/brooklyn/entity/messaging/zookeeper/ZooKeeperEnsembleLiveTest.java
+++ b/software/messaging/src/test/java/org/apache/brooklyn/entity/messaging/zookeeper/ZooKeeperEnsembleLiveTest.java
@@ -18,33 +18,39 @@
*/
package org.apache.brooklyn.entity.messaging.zookeeper;
-import org.apache.brooklyn.core.entity.Attributes;
-import org.apache.brooklyn.core.entity.Entities;
-import org.apache.brooklyn.core.entity.EntityAsserts;
-import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
-import org.apache.brooklyn.core.entity.trait.Startable;
-import org.apache.brooklyn.core.test.entity.TestApplication;
-import org.apache.brooklyn.entity.zookeeper.ZooKeeperEnsemble;
-import org.apache.brooklyn.entity.zookeeper.ZooKeeperNode;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
-import com.google.common.util.concurrent.Uninterruptibles;
+import java.util.List;
+import java.util.Set;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.EntityAsserts;
+import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.core.test.BrooklynAppLiveTestSupport;
+import org.apache.brooklyn.entity.group.DynamicCluster;
+import org.apache.brooklyn.entity.zookeeper.ZooKeeperEnsemble;
+import org.apache.brooklyn.entity.zookeeper.ZooKeeperNode;
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.text.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Optional;
+import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
-import java.net.Socket;
-import java.util.concurrent.TimeUnit;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+import com.google.common.net.HostAndPort;
/**
* A live test of the {@link org.apache.brooklyn.entity.zookeeper.ZooKeeperEnsemble} entity.
@@ -52,29 +58,28 @@
* Tests that a 3 node cluster can be started on Amazon EC2 and data written on one {@link org.apache.brooklyn.entity.zookeeper.ZooKeeperEnsemble}
* can be read from another, using the Astyanax API.
*/
-public class ZooKeeperEnsembleLiveTest {
+public class ZooKeeperEnsembleLiveTest extends BrooklynAppLiveTestSupport {
private static final Logger log = LoggerFactory.getLogger(ZooKeeperEnsembleLiveTest.class);
-
- private String provider =
- "gce-europe-west1";
-// "aws-ec2:eu-west-1";
-// "named:hpcloud-compute-at";
-// "localhost";
+ private static final String DEFAULT_LOCATION = "jclouds:aws-ec2:eu-west-1";
- protected TestApplication app;
- protected Location testLocation;
- protected ZooKeeperEnsemble cluster;
+ private Location testLocation;
+ private String locationSpec;
- @BeforeMethod(alwaysRun = true)
- public void setup() {
- app = ApplicationBuilder.newManagedApp(TestApplication.class);
- testLocation = app.getManagementContext().getLocationRegistry().getLocationManaged(provider);
+ @BeforeClass(alwaysRun = true)
+ @Parameters({"locationSpec"})
+ public void setLocationSpec(@Optional String locationSpec) {
+ this.locationSpec = !Strings.isBlank(locationSpec)
+ ? locationSpec
+ : DEFAULT_LOCATION;
+ log.info("Running {} with in {}", this, this.locationSpec);
}
- @AfterMethod(alwaysRun = true)
- public void shutdown() {
- Entities.destroyAll(app.getManagementContext());
+ @Override
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() throws Exception {
+ super.setUp();
+ testLocation = app.getManagementContext().getLocationRegistry().getLocationManaged(locationSpec);
}
/**
@@ -82,46 +87,61 @@
*/
@Test(groups = "Live")
public void testStartUpConnectAndResize() throws Exception {
- try {
- cluster = app.createAndManageChild(EntitySpec.create(ZooKeeperEnsemble.class)
- .configure("initialSize", 3)
- .configure("clusterName", "ZooKeeperEnsembleLiveTest"));
- assertEquals(cluster.getCurrentSize().intValue(), 0);
+ final String zkDataPath = "/ensembletest";
+ final int initialSize = 3;
+ ZooKeeperEnsemble ensemble = app.createAndManageChild(EntitySpec.create(ZooKeeperEnsemble.class)
+ .configure(DynamicCluster.INITIAL_SIZE, initialSize)
+ .configure(ZooKeeperEnsemble.CLUSTER_NAME, "ZooKeeperEnsembleLiveTest"));
- app.start(ImmutableList.of(testLocation));
+ app.start(ImmutableList.of(testLocation));
+ Entities.dumpInfo(app);
- EntityAsserts.assertAttributeEqualsEventually(cluster, ZooKeeperEnsemble.GROUP_SIZE, 3);
- Entities.dumpInfo(app);
+ EntityAsserts.assertAttributeEqualsEventually(ensemble, ZooKeeperEnsemble.GROUP_SIZE, 3);
+ EntityAsserts.assertAttributeEqualsEventually(ensemble, Startable.SERVICE_UP, true);
+ assertNotNull(ensemble.sensors().get(ZooKeeperEnsemble.ZOOKEEPER_ENDPOINTS),
+ "expected value for " + ZooKeeperEnsemble.ZOOKEEPER_ENDPOINTS + " on " + ensemble + ", was null");
+ Set<Integer> nodeIds = Sets.newHashSet();
+ for (Entity zkNode : ensemble.getMembers()) {
+ nodeIds.add(zkNode.config().get(ZooKeeperNode.MY_ID));
+ }
+ assertEquals(nodeIds.size(), initialSize, "expected " + initialSize + " node ids, found " + Iterables.toString(nodeIds));
- EntityAsserts.assertAttributeEqualsEventually(cluster, Startable.SERVICE_UP, true);
- for(Entity zkNode : cluster.getMembers()) {
- assertTrue(isSocketOpen((ZooKeeperNode) zkNode));
- }
- cluster.resize(1);
- EntityAsserts.assertAttributeEqualsEventually(cluster, ZooKeeperEnsemble.GROUP_SIZE, 1);
- Entities.dumpInfo(app);
- EntityAsserts.assertAttributeEqualsEventually(cluster, Startable.SERVICE_UP, true);
- for (Entity zkNode : cluster.getMembers()) {
- assertTrue(isSocketOpen((ZooKeeperNode) zkNode));
- }
- } catch (Throwable e) {
- throw Throwables.propagate(e);
+ // Write data to one and read from the others.
+ List<String> servers = ensemble.sensors().get(ZooKeeperEnsemble.ZOOKEEPER_SERVERS);
+ assertNotNull(servers, "value for sensor should not be null: " + ZooKeeperEnsemble.ZOOKEEPER_SERVERS);
+ assertEquals(servers.size(), initialSize, "expected " + initialSize + " entries in " + servers);
+
+ // Write to one
+ String firstServer = servers.get(0);
+ HostAndPort conn = HostAndPort.fromString(firstServer);
+ log.info("Writing data to {}", conn);
+ try (ZooKeeperTestSupport zkts = new ZooKeeperTestSupport(conn)) {
+ zkts.create(zkDataPath, "data".getBytes());
+ assertEquals(new String(zkts.get(zkDataPath)), "data");
+ }
+
+ // And read from the others.
+ for (int i = 1; i < servers.size(); i++) {
+ conn = HostAndPort.fromString(servers.get(i));
+ log.info("Asserting that data can be read from {}", conn);
+ assertPathDataEventually(conn, zkDataPath, "data");
}
}
- protected static boolean isSocketOpen(ZooKeeperNode node) {
- int attempt = 0, maxAttempts = 20;
- while(attempt < maxAttempts) {
- try {
- Socket s = new Socket(node.getAttribute(Attributes.HOSTNAME), node.getZookeeperPort());
- s.close();
- return true;
- } catch (Exception e) {
- attempt++;
- }
- Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
+ protected void assertPathDataEventually(HostAndPort hostAndPort, final String path, String expected) throws Exception {
+ try (ZooKeeperTestSupport zkts = new ZooKeeperTestSupport(hostAndPort)) {
+ final Supplier<String> dataSupplier = new Supplier<String>() {
+ @Override
+ public String get() {
+ try {
+ return new String(zkts.get(path));
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+ };
+ Asserts.eventually(dataSupplier, Predicates.equalTo(expected));
}
- return false;
}
-
+
}
diff --git a/software/messaging/src/test/java/org/apache/brooklyn/entity/messaging/zookeeper/ZooKeeperTestSupport.java b/software/messaging/src/test/java/org/apache/brooklyn/entity/messaging/zookeeper/ZooKeeperTestSupport.java
new file mode 100644
index 0000000..f1987d2
--- /dev/null
+++ b/software/messaging/src/test/java/org/apache/brooklyn/entity/messaging/zookeeper/ZooKeeperTestSupport.java
@@ -0,0 +1,88 @@
+/*
+ * 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.entity.messaging.zookeeper;
+
+import java.io.Closeable;
+import java.util.concurrent.CountDownLatch;
+
+import org.apache.brooklyn.location.paas.PaasLocation;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.data.Stat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.net.HostAndPort;
+
+/**
+ * Useful methods for writing to and reading from ZooKeeper nodes.
+ */
+public class ZooKeeperTestSupport implements Closeable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ZooKeeperTestSupport.class);
+ private final ZooKeeper zk;
+ private final CountDownLatch connSignal = new CountDownLatch(1);
+
+ public ZooKeeperTestSupport(final HostAndPort hostAndPort) throws Exception {
+ final int sessionTimeout = 3000;
+ zk = new ZooKeeper(hostAndPort.toString(), sessionTimeout, new Watcher() {
+ @Override
+ public void process(WatchedEvent event) {
+ if (event.getState() == Event.KeeperState.SyncConnected) {
+ LOG.debug("Connected to ZooKeeper at {}", hostAndPort);
+ connSignal.countDown();
+ } else {
+ LOG.info("WatchedEvent at {}: {}", hostAndPort, event.getState());
+ }
+ }
+ });
+ connSignal.await();
+ }
+
+ @Override
+ public void close() {
+ try {
+ zk.close();
+ } catch (InterruptedException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ public String create(String path, byte[] data) throws Exception {
+ return zk.create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+ }
+
+ public Stat update(String path, byte[] data) throws Exception {
+ return zk.setData(path, data, zk.exists(path, true).getVersion());
+ }
+
+ public void delete(String path) throws Exception {
+ zk.delete(path, zk.exists(path, true).getVersion());
+ }
+
+ public byte[] get(String path) throws Exception {
+ return zk.getData(path, false, zk.exists(path, false));
+ }
+
+}
diff --git a/software/monitoring/pom.xml b/software/monitoring/pom.xml
index 931c79e..901df83 100644
--- a/software/monitoring/pom.xml
+++ b/software/monitoring/pom.xml
@@ -30,7 +30,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/software/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/monit/MonitNodeImpl.java b/software/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/monit/MonitNodeImpl.java
index 2702994..f3b2863 100644
--- a/software/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/monit/MonitNodeImpl.java
+++ b/software/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/monit/MonitNodeImpl.java
@@ -71,7 +71,7 @@
String cmd = getDriver().getStatusCmd();
feed = SshFeed.builder()
.entity(this)
- .period(Duration.FIVE_SECONDS)
+ .period(config().get(SERVICE_PROCESS_IS_RUNNING_POLL_PERIOD))
.machine((SshMachineLocation) machine)
.poll(new SshPollConfig<Boolean>(SERVICE_UP)
.command(cmd)
diff --git a/software/monitoring/src/main/resources/catalog.bom b/software/monitoring/src/main/resources/catalog.bom
index 5388ae0..4ecc2a6 100644
--- a/software/monitoring/src/main/resources/catalog.bom
+++ b/software/monitoring/src/main/resources/catalog.bom
@@ -16,7 +16,7 @@
# under the License.
brooklyn.catalog:
- version: "0.10.0-SNAPSHOT" # BROOKLYN_VERSION
+ version: "0.11.0-SNAPSHOT" # BROOKLYN_VERSION
itemType: entity
items:
- id: org.apache.brooklyn.entity.monitoring.monit.MonitNode
diff --git a/software/network/pom.xml b/software/network/pom.xml
index 6f7a1bb..cc08b7a 100644
--- a/software/network/pom.xml
+++ b/software/network/pom.xml
@@ -28,7 +28,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/software/network/src/main/java/org/apache/brooklyn/entity/network/bind/BindDnsServerImpl.java b/software/network/src/main/java/org/apache/brooklyn/entity/network/bind/BindDnsServerImpl.java
index ef53bc4..a210e55 100644
--- a/software/network/src/main/java/org/apache/brooklyn/entity/network/bind/BindDnsServerImpl.java
+++ b/software/network/src/main/java/org/apache/brooklyn/entity/network/bind/BindDnsServerImpl.java
@@ -105,6 +105,7 @@
public void init() {
super.init();
checkNotNull(getConfig(HOSTNAME_SENSOR), "%s requires value for %s", getClass().getName(), HOSTNAME_SENSOR);
+ checkNotNull(getConfig(ADDRESS_SENSOR), "%s requires value for %s", getClass().getName(), ADDRESS_SENSOR);
DynamicGroup entities = addChild(EntitySpec.create(DynamicGroup.class)
.displayName("BIND-managed entities")
.configure(DynamicGroup.ENTITY_FILTER, getEntityFilter()));
diff --git a/software/network/src/main/java/org/apache/brooklyn/entity/network/bind/BindDnsServerSshDriver.java b/software/network/src/main/java/org/apache/brooklyn/entity/network/bind/BindDnsServerSshDriver.java
index ad0aaff..150cfb9 100644
--- a/software/network/src/main/java/org/apache/brooklyn/entity/network/bind/BindDnsServerSshDriver.java
+++ b/software/network/src/main/java/org/apache/brooklyn/entity/network/bind/BindDnsServerSshDriver.java
@@ -76,7 +76,7 @@
List<String> commands = Lists.newArrayList(
BashCommands.sudo("mkdir -p " + getDataDirectory() + " " + getDynamicDirectory() + " " + getOsSupport().getConfigDirectory()),
- BashCommands.sudo("chown -R bind:bind " + getDataDirectory() + " " + getDynamicDirectory()),
+ BashCommands.sudo("chown -R " + getOsSupport().getUser() + ":" + getOsSupport().getUser() + " " + getDataDirectory() + " " + getDynamicDirectory()),
// TODO determine name of ethernet interface if not eth0?
IptablesCommands.insertIptablesRule(Chain.INPUT, "eth0", Protocol.UDP, dnsPort, Policy.ACCEPT),
IptablesCommands.insertIptablesRule(Chain.INPUT, "eth0", Protocol.TCP, dnsPort, Policy.ACCEPT),
diff --git a/software/network/src/main/java/org/apache/brooklyn/entity/network/bind/BindOsSupport.java b/software/network/src/main/java/org/apache/brooklyn/entity/network/bind/BindOsSupport.java
index c48f8a3..ad681c7 100644
--- a/software/network/src/main/java/org/apache/brooklyn/entity/network/bind/BindOsSupport.java
+++ b/software/network/src/main/java/org/apache/brooklyn/entity/network/bind/BindOsSupport.java
@@ -30,6 +30,7 @@
// Likewise would make these package-private and have no getters if Freemarker was ok with it.
private final String packageName;
private final String serviceName;
+ private final String user;
private final String rootConfigFile;
private final String configDirectory;
private final String workingDirectory;
@@ -39,6 +40,7 @@
private BindOsSupport(
String packageName,
String serviceName,
+ String user,
String rootConfigFile,
String configDirectory,
String workingDirectory,
@@ -46,6 +48,7 @@
String keysFile) {
this.packageName = packageName;
this.serviceName = serviceName;
+ this.user = user;
this.rootConfigFile = rootConfigFile;
this.configDirectory = configDirectory;
this.workingDirectory = workingDirectory;
@@ -60,9 +63,10 @@
return new BindOsSupport(
"bind",
"named",
+ "named",
"/etc/named.conf",
"/var/named",
- "/var/named/data",
+ "/var/named",
"/var/named/named.ca",
"/etc/named.iscdlv.key");
}
@@ -74,6 +78,7 @@
return new BindOsSupport(
"bind9",
"bind9",
+ "bind",
"/etc/bind/named.conf",
"/etc/bind",
"/var/cache/bind",
@@ -110,4 +115,7 @@
return keysFile;
}
+ public String getUser() {
+ return user;
+ }
}
diff --git a/software/network/src/main/resources/catalog.bom b/software/network/src/main/resources/catalog.bom
index ceead03..6fbeca9 100644
--- a/software/network/src/main/resources/catalog.bom
+++ b/software/network/src/main/resources/catalog.bom
@@ -16,7 +16,7 @@
# under the License.
brooklyn.catalog:
- version: "0.10.0-SNAPSHOT" # BROOKLYN_VERSION
+ version: "0.11.0-SNAPSHOT" # BROOKLYN_VERSION
itemType: entity
items:
- id: org.apache.brooklyn.entity.network.bind.BindDnsServer
diff --git a/software/nosql/pom.xml b/software/nosql/pom.xml
index bc9dbc2..4c603f4 100644
--- a/software/nosql/pom.xml
+++ b/software/nosql/pom.xml
@@ -29,7 +29,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeSshDriver.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeSshDriver.java
index dbb743b..8831e81 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeSshDriver.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeSshDriver.java
@@ -28,7 +28,6 @@
import java.util.Set;
import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntityLocal;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.mgmt.TaskWrapper;
import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks;
@@ -263,10 +262,10 @@
queuedStart = root.getAttribute(CassandraDatacenter.QUEUED_START_NODES);
if (queuedStart==null) {
queuedStart = new ArrayList<Entity>();
- ((EntityLocal)root).sensors().set(CassandraDatacenter.QUEUED_START_NODES, queuedStart);
+ root.sensors().set(CassandraDatacenter.QUEUED_START_NODES, queuedStart);
}
queuedStart.add(getEntity());
- ((EntityLocal)root).sensors().set(CassandraDatacenter.QUEUED_START_NODES, queuedStart);
+ root.sensors().set(CassandraDatacenter.QUEUED_START_NODES, queuedStart);
}
do {
// get it again in case it is backed by something external
@@ -306,7 +305,7 @@
}
if (isClustered() && isFirst) {
for (Entity ancestor: getCassandraAncestors()) {
- ((EntityLocal)ancestor).sensors().set(CassandraDatacenter.FIRST_NODE_STARTED_TIME_UTC, System.currentTimeMillis());
+ ancestor.sensors().set(CassandraDatacenter.FIRST_NODE_STARTED_TIME_UTC, System.currentTimeMillis());
}
}
} finally {
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java
index 68d3a54..4dc9bbd 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java
@@ -252,7 +252,7 @@
if (toClusterO instanceof String) {
toClusterO = getManagementContext().lookup((String)toClusterO);
}
- Entity toCluster = Tasks.resolving(toClusterO, Entity.class).context(getExecutionContext()).get();
+ Entity toCluster = Tasks.resolving(toClusterO, Entity.class).context(this).get();
String fromBucket = Preconditions.checkNotNull( (String)ruleArgs.getStringKey("fromBucket"), "fromBucket must be specified" );
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNodeImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNodeImpl.java
index ccb09e8..6bc89df 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNodeImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNodeImpl.java
@@ -72,9 +72,7 @@
Integer rawPort = getAttribute(HTTP_PORT);
String hostname = getAttribute(HOSTNAME);
checkNotNull(rawPort, "HTTP_PORT sensors not set for %s; is an acceptable port available?", this);
-
- sensors().set(DATASTORE_URL, String.format("http://%s:%s", hostname, rawPort));
-
+
HostAndPort hp = BrooklynAccessUtils.getBrooklynAccessibleAddress(this, rawPort);
Function<Maybe<JsonElement>, String> getNodeId = new Function<Maybe<JsonElement>, String>() {
@Override public String apply(Maybe<JsonElement> input) {
@@ -85,6 +83,7 @@
}
};
+ sensors().set(DATASTORE_URL, String.format("http://%s", hp));
if (isHttpMonitoringEnabled()) {
boolean retrieveUsageMetrics = getConfig(RETRIEVE_USAGE_METRICS);
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
index 1a80c3a..63f0f86 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
@@ -35,7 +35,6 @@
import javax.annotation.Nullable;
import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntityLocal;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.policy.PolicySpec;
@@ -54,7 +53,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.collect.Sets;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
@@ -238,7 +236,7 @@
addSecondaryWhenPrimaryIsNonNull(server);
}
} catch (Exception e) {
- ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator((EntityLocal)server, "Failed to update replicaset", e);
+ ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator(server, "Failed to update replicaset", e);
}
}
@@ -338,7 +336,7 @@
}
});
} catch (Exception e) {
- ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator((EntityLocal)member, "Failed to update replicaset", e);
+ ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator(member, "Failed to update replicaset", e);
}
}
diff --git a/software/nosql/src/main/resources/catalog.bom b/software/nosql/src/main/resources/catalog.bom
index bbcb063..228442e 100644
--- a/software/nosql/src/main/resources/catalog.bom
+++ b/software/nosql/src/main/resources/catalog.bom
@@ -16,7 +16,7 @@
# under the License.
brooklyn.catalog:
- version: "0.10.0-SNAPSHOT" # BROOKLYN_VERSION
+ version: "0.11.0-SNAPSHOT" # BROOKLYN_VERSION
itemType: entity
items:
- id: org.apache.brooklyn.entity.nosql.redis.RedisStore
diff --git a/software/osgi/pom.xml b/software/osgi/pom.xml
index 7293674..d52a040 100644
--- a/software/osgi/pom.xml
+++ b/software/osgi/pom.xml
@@ -30,7 +30,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/software/osgi/src/main/resources/catalog.bom b/software/osgi/src/main/resources/catalog.bom
index 9cd81f1..eddddcb 100644
--- a/software/osgi/src/main/resources/catalog.bom
+++ b/software/osgi/src/main/resources/catalog.bom
@@ -16,7 +16,7 @@
# under the License.
brooklyn.catalog:
- version: "0.10.0-SNAPSHOT" # BROOKLYN_VERSION
+ version: "0.11.0-SNAPSHOT" # BROOKLYN_VERSION
itemType: entity
items:
- id: org.apache.brooklyn.entity.osgi.karaf.KarafContainer
diff --git a/software/webapp/pom.xml b/software/webapp/pom.xml
index ad6359f..dc75279 100644
--- a/software/webapp/pom.xml
+++ b/software/webapp/pom.xml
@@ -29,7 +29,7 @@
<parent>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-library</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<relativePath>../../pom.xml</relativePath>
</parent>
@@ -164,7 +164,7 @@
<dependency>
<groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-camp</artifactId>
- <version>0.10.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
+ <version>0.11.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION -->
<scope>test</scope>
</dependency>
<dependency>
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractController.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractController.java
index ec3d7a8..e76d89e 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractController.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractController.java
@@ -18,12 +18,14 @@
*/
package org.apache.brooklyn.entity.proxy;
+import java.net.URI;
import java.util.Set;
import org.apache.brooklyn.api.entity.ImplementedBy;
import org.apache.brooklyn.api.sensor.AttributeSensor;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.sensor.BasicAttributeSensorAndConfigKey;
import org.apache.brooklyn.entity.group.Cluster;
import org.apache.brooklyn.entity.software.base.SoftwareProcess;
@@ -48,6 +50,9 @@
ConfigKey<String> SERVICE_UP_URL_PATH = ConfigKeys.newStringConfigKey(
"controller.config.serviceUpUrlPath", "The path that will be appended to the root URL to determine SERVICE_UP", "");
+ AttributeSensor<URI> MAIN_URI_MAPPED_SUBNET = Attributes.MAIN_URI_MAPPED_SUBNET;
+ AttributeSensor<URI> MAIN_URI_MAPPED_PUBLIC = Attributes.MAIN_URI_MAPPED_PUBLIC;
+
boolean isActive();
ProxySslConfig getSslConfig();
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractControllerImpl.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractControllerImpl.java
index 257882d..3277e38 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractControllerImpl.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractControllerImpl.java
@@ -33,6 +33,7 @@
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.EntityInternal;
import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
@@ -53,6 +54,7 @@
import org.slf4j.LoggerFactory;
import com.google.common.base.Objects;
+import com.google.common.base.Optional;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
@@ -229,7 +231,15 @@
public String getDomain() {
return getAttribute(DOMAIN_NAME);
}
-
+
+ protected String getDomainWithoutWildcard() {
+ String domain = getDomain();
+ if (domain != null && domain.startsWith("*.")) {
+ domain = domain.replace("*.", ""); // Strip wildcard
+ }
+ return domain;
+ }
+
@Override
public Integer getPort() {
if (isSsl())
@@ -265,14 +275,22 @@
protected String inferProtocol() {
return isSsl() ? "https" : "http";
}
-
+
+ protected String inferUrlForSubnet() {
+ String domain = getDomainWithoutWildcard();
+ if (domain==null) domain = getAttribute(Attributes.SUBNET_ADDRESS);
+ return inferUrl(domain, Optional.<Integer>absent());
+ }
+
+ protected String inferUrlForPublic() {
+ String domain = getDomainWithoutWildcard();
+ if (domain==null) domain = getAttribute(Attributes.ADDRESS);
+ return inferUrl(domain, Optional.<Integer>absent());
+ }
+
/** returns URL, if it can be inferred; null otherwise */
protected String inferUrl(boolean requireManagementAccessible) {
- String protocol = checkNotNull(getProtocol(), "no protocol configured");
- String domain = getDomain();
- if (domain != null && domain.startsWith("*.")) {
- domain = domain.replace("*.", ""); // Strip wildcard
- }
+ String domain = getDomainWithoutWildcard();
Integer port = checkNotNull(getPort(), "no port configured (the requested port may be in use)");
if (requireManagementAccessible) {
HostAndPort accessible = BrooklynAccessUtils.getBrooklynAccessibleAddress(this, port);
@@ -282,8 +300,15 @@
}
}
if (domain==null) domain = Machines.findSubnetHostname(this).orNull();
- if (domain==null) return null;
- return protocol+"://"+domain+":"+port+"/"+getConfig(SERVICE_UP_URL_PATH);
+ return inferUrl(domain, Optional.of(port));
+ }
+
+ protected String inferUrl(String host, Optional<Integer> portOverride) {
+ if (host == null) return null;
+ String protocol = checkNotNull(getProtocol(), "no protocol configured");
+ int port = portOverride.isPresent() ? portOverride.get() : checkNotNull(getPort(), "no port configured (the requested port may be in use)");
+ String path = getConfig(SERVICE_UP_URL_PATH);
+ return protocol+"://"+host+":"+port+"/"+path;
}
protected String inferUrl() {
@@ -316,12 +341,26 @@
ConfigToAttributes.apply(this);
sensors().set(PROTOCOL, inferProtocol());
- sensors().set(MAIN_URI, URI.create(inferUrl()));
+ sensors().set(MAIN_URI, createUriOrNull(inferUrl()));
+ sensors().set(MAIN_URI_MAPPED_SUBNET, createUriOrNull(inferUrlForSubnet()));
+ sensors().set(MAIN_URI_MAPPED_PUBLIC, createUriOrNull(inferUrlForPublic()));
sensors().set(ROOT_URL, inferUrl());
checkNotNull(getPortNumberSensor(), "no sensor configured to infer port number");
}
+ private URI createUriOrNull(String val) {
+ if (val == null) {
+ return null;
+ }
+ try {
+ return URI.create(val);
+ } catch (IllegalArgumentException e) {
+ LOG.warn("Invalid URI for {}: {}", this, val);
+ return null;
+ }
+ }
+
@Override
protected void connectSensors() {
super.connectSensors();
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java
index 4e55780..4b3a46e 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java
@@ -27,7 +27,6 @@
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.entity.Attributes;
-import org.apache.brooklyn.core.entity.factory.ConfigurableEntityFactory;
import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
import org.apache.brooklyn.core.entity.trait.MemberReplaceable;
import org.apache.brooklyn.core.entity.trait.Resizable;
@@ -78,12 +77,6 @@
public static BasicAttributeSensorAndConfigKey<EntitySpec<? extends LoadBalancer>> CONTROLLER_SPEC = new BasicAttributeSensorAndConfigKey(
EntitySpec.class, "controlleddynamicwebappcluster.controllerSpec", "Spec for creating the controller (if one not supplied explicitly); if null an NGINX instance will be created");
- @SuppressWarnings({ "unchecked", "rawtypes", "deprecation" })
- /** factory (or closure) to create the web server, given flags */
- @SetFromFlag("factory")
- public static BasicAttributeSensorAndConfigKey<ConfigurableEntityFactory<? extends WebAppService>> FACTORY = new BasicAttributeSensorAndConfigKey(
- ConfigurableEntityFactory.class, DynamicCluster.FACTORY.getName(), "factory (or closure) to create the web server");
-
@SuppressWarnings({ "unchecked", "rawtypes" })
/** Spec for web server entiites to be created */
@SetFromFlag("memberSpec")
@@ -105,8 +98,6 @@
public LoadBalancer getController();
- public ConfigurableEntityFactory<WebAppService> getFactory();
-
public DynamicWebAppCluster getCluster();
public Group getControlledGroup();
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java
index 6ac61ce..dd658e0 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java
@@ -32,7 +32,6 @@
import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.EntityPredicates;
-import org.apache.brooklyn.core.entity.factory.ConfigurableEntityFactory;
import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic;
import org.apache.brooklyn.core.entity.trait.Startable;
@@ -79,16 +78,14 @@
public void init() {
super.init();
- ConfigToAttributes.apply(this, FACTORY);
ConfigToAttributes.apply(this, MEMBER_SPEC);
ConfigToAttributes.apply(this, CONTROLLER);
ConfigToAttributes.apply(this, CONTROLLER_SPEC);
ConfigToAttributes.apply(this, WEB_CLUSTER_SPEC);
ConfigToAttributes.apply(this, CONTROLLED_GROUP);
- ConfigurableEntityFactory<? extends WebAppService> webServerFactory = getAttribute(FACTORY);
EntitySpec<? extends WebAppService> webServerSpec = getAttribute(MEMBER_SPEC);
- if (webServerFactory == null && webServerSpec == null) {
+ if (webServerSpec == null) {
log.debug("creating default web server spec for {}", this);
webServerSpec = EntitySpec.create(TomcatServer.class);
sensors().set(MEMBER_SPEC, webServerSpec);
@@ -97,20 +94,14 @@
log.debug("creating cluster child for {}", this);
// Note relies on initial_size being inherited by DynamicWebAppCluster, because key id is identical
EntitySpec<? extends DynamicWebAppCluster> webClusterSpec = getAttribute(WEB_CLUSTER_SPEC);
- Map<String,Object> webClusterFlags;
- if (webServerSpec != null) {
- webClusterFlags = MutableMap.<String,Object>of("memberSpec", webServerSpec);
- } else {
- webClusterFlags = MutableMap.<String,Object>of("factory", webServerFactory);
- }
+ Map<String,Object> webClusterFlags = MutableMap.<String,Object>of("memberSpec", webServerSpec);
+
if (webClusterSpec == null) {
log.debug("creating default web cluster spec for {}", this);
webClusterSpec = EntitySpec.create(DynamicWebAppCluster.class);
}
boolean hasMemberSpec = webClusterSpec.getConfig().containsKey(DynamicWebAppCluster.MEMBER_SPEC) || webClusterSpec.getFlags().containsKey("memberSpec");
- @SuppressWarnings("deprecation")
- boolean hasMemberFactory = webClusterSpec.getConfig().containsKey(DynamicWebAppCluster.FACTORY) || webClusterSpec.getFlags().containsKey("factory");
- if (!(hasMemberSpec || hasMemberFactory)) {
+ if (!hasMemberSpec) {
webClusterSpec.configure(webClusterFlags);
} else {
log.warn("In {}, not setting cluster's {} because already set on webClusterSpec", new Object[] {this, webClusterFlags.keySet()});
@@ -182,12 +173,6 @@
return getAttribute(CONTROLLER);
}
- @SuppressWarnings("unchecked")
- @Override
- public ConfigurableEntityFactory<WebAppService> getFactory() {
- return (ConfigurableEntityFactory<WebAppService>) getAttribute(FACTORY);
- }
-
// TODO convert to an entity reference which is serializable
@Override
public DynamicWebAppCluster getCluster() {
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/WebAppServiceMethods.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/WebAppServiceMethods.java
index 3ce748b..a25b4f7 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/WebAppServiceMethods.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/WebAppServiceMethods.java
@@ -24,7 +24,6 @@
import java.util.concurrent.TimeUnit;
import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntityLocal;
import org.apache.brooklyn.core.location.access.BrooklynAccessUtils;
import org.apache.brooklyn.policy.enricher.RollingTimeWindowMeanEnricher;
import org.apache.brooklyn.policy.enricher.TimeFractionDeltaEnricher;
@@ -37,11 +36,11 @@
public static final Duration DEFAULT_WINDOW_DURATION = Duration.TEN_SECONDS;
- public static void connectWebAppServerPolicies(EntityLocal entity) {
+ public static void connectWebAppServerPolicies(Entity entity) {
connectWebAppServerPolicies(entity, DEFAULT_WINDOW_DURATION);
}
- public static void connectWebAppServerPolicies(EntityLocal entity, Duration windowPeriod) {
+ public static void connectWebAppServerPolicies(Entity entity, Duration windowPeriod) {
entity.enrichers().add(TimeWeightedDeltaEnricher.<Integer>getPerSecondDeltaEnricher(entity, REQUEST_COUNT, REQUESTS_PER_SECOND_LAST));
if (windowPeriod!=null) {
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/WebAppServiceMetrics.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/WebAppServiceMetrics.java
index 7264698..aa2c9ac 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/WebAppServiceMetrics.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/WebAppServiceMetrics.java
@@ -36,7 +36,7 @@
Sensors.newIntegerSensor("webapp.reqs.processingTime.max", "Max processing time for any single request, reported by webserver (millis)");
/** the fraction of time represented by the most recent delta to TOTAL_PROCESSING_TIME, ie 0.4 if 800 millis were accumulated in last 2s;
- * easily configured with {@link WebAppServiceMethods#connectWebAppServerPolicies(org.apache.brooklyn.api.internal.EntityLocal, org.apache.brooklyn.util.time.Duration)} */
+ * easily configured with {@link WebAppServiceMethods#connectWebAppServerPolicies(org.apache.brooklyn.api.entity.Entity, org.apache.brooklyn.util.time.Duration)} */
public static final AttributeSensor<Double> PROCESSING_TIME_FRACTION_LAST =
Sensors.newDoubleSensor("webapp.reqs.processingTime.fraction.last", "Fraction of time spent processing, reported by webserver (percentage, last datapoint)");
public static final AttributeSensor<Double> PROCESSING_TIME_FRACTION_IN_WINDOW =
@@ -52,7 +52,7 @@
Sensors.newDoubleSensor("webapp.reqs.perSec.last", "Reqs/sec (last datapoint)");
/** rolled-up req/second for a window,
- * easily configured with {@link WebAppServiceMethods#connectWebAppServerPolicies(org.apache.brooklyn.api.internal.EntityLocal, org.apache.brooklyn.util.time.Duration)} */
+ * easily configured with {@link WebAppServiceMethods#connectWebAppServerPolicies(org.apache.brooklyn.api.entity.Entity, org.apache.brooklyn.util.time.Duration)} */
public static final AttributeSensor<Double> REQUESTS_PER_SECOND_IN_WINDOW =
Sensors.newDoubleSensor("webapp.reqs.perSec.windowed", "Reqs/sec (over time window)");
diff --git a/software/webapp/src/main/resources/catalog.bom b/software/webapp/src/main/resources/catalog.bom
index cd42ead..d1349ef 100644
--- a/software/webapp/src/main/resources/catalog.bom
+++ b/software/webapp/src/main/resources/catalog.bom
@@ -16,7 +16,7 @@
# under the License.
brooklyn.catalog:
- version: "0.10.0-SNAPSHOT" # BROOKLYN_VERSION
+ version: "0.11.0-SNAPSHOT" # BROOKLYN_VERSION
itemType: entity
items:
- id: org.apache.brooklyn.entity.webapp.nodejs.NodeJsWebAppService
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/AbstractControllerTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/AbstractControllerTest.java
index 6daae33..94221c4 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/AbstractControllerTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/AbstractControllerTest.java
@@ -22,6 +22,7 @@
import static org.testng.Assert.assertTrue;
import java.net.Inet4Address;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -30,7 +31,6 @@
import java.util.Set;
import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntityLocal;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
@@ -39,8 +39,11 @@
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
import org.apache.brooklyn.api.sensor.AttributeSensor;
import org.apache.brooklyn.core.entity.Attributes;
-import org.apache.brooklyn.core.entity.factory.EntityFactory;
+import org.apache.brooklyn.core.entity.EntityAsserts;
import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.core.location.HasSubnetHostname;
+import org.apache.brooklyn.core.location.Machines;
+import org.apache.brooklyn.core.location.PortRanges;
import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
import org.apache.brooklyn.core.test.entity.TestEntity;
import org.apache.brooklyn.core.test.entity.TestEntityImpl;
@@ -53,6 +56,7 @@
import org.apache.brooklyn.util.collections.MutableSet;
import org.apache.brooklyn.util.core.flags.SetFromFlag;
import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.BeforeMethod;
@@ -77,7 +81,7 @@
super.setUp();
List<SshMachineLocation> machines = new ArrayList<SshMachineLocation>();
- for (int i=1; i<=10; i++) {
+ for (int i = 1; i <= 10; i++) {
SshMachineLocation machine = mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)
.configure("address", Inet4Address.getByName("1.1.1."+i)));
machines.add(machine);
@@ -85,13 +89,13 @@
loc = mgmt.getLocationManager().createLocation(LocationSpec.create(FixedListMachineProvisioningLocation.class)
.configure("machines", machines));
- cluster = app.createAndManageChild(EntitySpec.create(DynamicCluster.class)
+ cluster = app.addChild(EntitySpec.create(DynamicCluster.class)
.configure("initialSize", 0)
- .configure("factory", new ClusteredEntity.Factory()));
+ .configure("memberSpec", EntitySpec.create(TestEntity.class).impl(WebServerEntity.class)));
- controller = app.createAndManageChild(EntitySpec.create(TrackingAbstractController.class)
+ controller = app.addChild(EntitySpec.create(TrackingAbstractController.class)
.configure("serverPool", cluster)
- .configure("portNumberSensor", ClusteredEntity.HTTP_PORT)
+ .configure("portNumberSensor", WebServerEntity.HTTP_PORT)
.configure("domain", "mydomain"));
app.start(ImmutableList.of(loc));
@@ -114,9 +118,9 @@
// above may trigger error logged about no hostname, but should update again with the settings below
log.info("setting mymachine:1234");
- child.sensors().set(ClusteredEntity.HOSTNAME, "mymachine");
+ child.sensors().set(WebServerEntity.HOSTNAME, "mymachine");
child.sensors().set(Attributes.SUBNET_HOSTNAME, "mymachine");
- child.sensors().set(ClusteredEntity.HTTP_PORT, 1234);
+ child.sensors().set(WebServerEntity.HTTP_PORT, 1234);
assertEventuallyExplicitAddressesMatch(ImmutableList.of("mymachine:1234"));
/* a race failure has been observed, https://issues.apache.org/jira/browse/BROOKLYN-206
@@ -134,16 +138,16 @@
*/
log.info("setting mymachine2:1234");
- child.sensors().set(ClusteredEntity.HOSTNAME, "mymachine2");
+ child.sensors().set(WebServerEntity.HOSTNAME, "mymachine2");
child.sensors().set(Attributes.SUBNET_HOSTNAME, "mymachine2");
assertEventuallyExplicitAddressesMatch(ImmutableList.of("mymachine2:1234"));
log.info("setting mymachine2:1235");
- child.sensors().set(ClusteredEntity.HTTP_PORT, 1235);
+ child.sensors().set(WebServerEntity.HTTP_PORT, 1235);
assertEventuallyExplicitAddressesMatch(ImmutableList.of("mymachine2:1235"));
log.info("clearing");
- child.sensors().set(ClusteredEntity.HOSTNAME, null);
+ child.sensors().set(WebServerEntity.HOSTNAME, null);
child.sensors().set(Attributes.SUBNET_HOSTNAME, null);
assertEventuallyExplicitAddressesMatch(ImmutableList.<String>of());
}
@@ -152,12 +156,12 @@
public void testUpdateCalledWithAddressesOfNewChildren() {
// First child
cluster.resize(1);
- EntityLocal child = (EntityLocal) Iterables.getOnlyElement(cluster.getMembers());
+ Entity child = Iterables.getOnlyElement(cluster.getMembers());
List<Collection<String>> u = Lists.newArrayList(controller.getUpdates());
assertTrue(u.isEmpty(), "expected empty list but got "+u);
- child.sensors().set(ClusteredEntity.HTTP_PORT, 1234);
+ child.sensors().set(WebServerEntity.HTTP_PORT, 1234);
child.sensors().set(Startable.SERVICE_UP, true);
assertEventuallyAddressesMatchCluster();
@@ -168,9 +172,9 @@
public void run() {
assertEquals(cluster.getMembers().size(), 2);
}});
- EntityLocal child2 = (EntityLocal) Iterables.getOnlyElement(MutableSet.builder().addAll(cluster.getMembers()).remove(child).build());
+ Entity child2 = Iterables.getOnlyElement(MutableSet.<Entity>builder().addAll(cluster.getMembers()).remove(child).build());
- child2.sensors().set(ClusteredEntity.HTTP_PORT, 1234);
+ child2.sensors().set(WebServerEntity.HTTP_PORT, 1234);
child2.sensors().set(Startable.SERVICE_UP, true);
assertEventuallyAddressesMatchCluster();
@@ -189,8 +193,8 @@
// Get some children, so we can remove one...
cluster.resize(2);
for (Entity it: cluster.getMembers()) {
- ((EntityLocal)it).sensors().set(ClusteredEntity.HTTP_PORT, 1234);
- ((EntityLocal)it).sensors().set(Startable.SERVICE_UP, true);
+ it.sensors().set(WebServerEntity.HTTP_PORT, 1234);
+ it.sensors().set(Startable.SERVICE_UP, true);
}
assertEventuallyAddressesMatchCluster();
@@ -205,17 +209,17 @@
// Get some children, so we can remove one...
cluster.resize(2);
for (Entity it: cluster.getMembers()) {
- ((EntityLocal)it).sensors().set(ClusteredEntity.HTTP_PORT, 1234);
- ((EntityLocal)it).sensors().set(Startable.SERVICE_UP, true);
+ it.sensors().set(WebServerEntity.HTTP_PORT, 1234);
+ it.sensors().set(Startable.SERVICE_UP, true);
}
assertEventuallyAddressesMatchCluster();
// Now unset host/port, and remove children
// Note the unsetting of hostname is done in SoftwareProcessImpl.stop(), so this is realistic
for (Entity it : cluster.getMembers()) {
- ((EntityLocal)it).sensors().set(ClusteredEntity.HTTP_PORT, null);
- ((EntityLocal)it).sensors().set(ClusteredEntity.HOSTNAME, null);
- ((EntityLocal)it).sensors().set(Startable.SERVICE_UP, false);
+ it.sensors().set(WebServerEntity.HTTP_PORT, null);
+ it.sensors().set(WebServerEntity.HOSTNAME, null);
+ it.sensors().set(Startable.SERVICE_UP, false);
}
assertEventuallyAddressesMatch(ImmutableList.<Entity>of());
}
@@ -224,7 +228,7 @@
public void testUsesHostAndPortSensor() throws Exception {
controller = app.createAndManageChild(EntitySpec.create(TrackingAbstractController.class)
.configure("serverPool", cluster)
- .configure("hostAndPortSensor", ClusteredEntity.HOST_AND_PORT)
+ .configure("hostAndPortSensor", WebServerEntity.HOST_AND_PORT)
.configure("domain", "mydomain"));
controller.start(Arrays.asList(loc));
@@ -239,7 +243,7 @@
// TODO Ugly sleep to allow AbstractController to detect node having been added
Thread.sleep(100);
- child.sensors().set(ClusteredEntity.HOST_AND_PORT, "mymachine:1234");
+ child.sensors().set(WebServerEntity.HOST_AND_PORT, "mymachine:1234");
assertEventuallyExplicitAddressesMatch(ImmutableList.of("mymachine:1234"));
}
@@ -248,8 +252,8 @@
try {
TrackingAbstractController controller2 = app.createAndManageChild(EntitySpec.create(TrackingAbstractController.class)
.configure("serverPool", cluster)
- .configure("hostAndPortSensor", ClusteredEntity.HOST_AND_PORT)
- .configure("hostnameSensor", ClusteredEntity.HOSTNAME)
+ .configure("hostAndPortSensor", WebServerEntity.HOST_AND_PORT)
+ .configure("hostnameSensor", WebServerEntity.HOSTNAME)
.configure("domain", "mydomain"));
controller2.start(Arrays.asList(loc));
} catch (Exception e) {
@@ -264,8 +268,8 @@
try {
TrackingAbstractController controller3 = app.createAndManageChild(EntitySpec.create(TrackingAbstractController.class)
.configure("serverPool", cluster)
- .configure("hostAndPortSensor", ClusteredEntity.HOST_AND_PORT)
- .configure("portNumberSensor", ClusteredEntity.HTTP_PORT)
+ .configure("hostAndPortSensor", WebServerEntity.HOST_AND_PORT)
+ .configure("portNumberSensor", WebServerEntity.HTTP_PORT)
.configure("domain", "mydomain"));
controller3.start(Arrays.asList(loc));
} catch (Exception e) {
@@ -300,19 +304,58 @@
assertTrue(u.isEmpty(), "expected no updates, but got "+u);
}
+ @Test
+ public void testMainUriSensorsCorrectlyComputedWithDomain() throws Exception {
+ URI expected = URI.create("http://mydomain:8000/");
+
+ EntityAsserts.assertAttributeEquals(controller, TrackingAbstractController.MAIN_URI, expected);
+ EntityAsserts.assertAttributeEquals(controller, TrackingAbstractController.MAIN_URI_MAPPED_SUBNET, expected);
+ EntityAsserts.assertAttributeEquals(controller, TrackingAbstractController.MAIN_URI_MAPPED_PUBLIC, expected);
+ }
+
+ @Test
+ public void testMainUriSensorsCorrectlyComputedWithoutDomain() throws Exception {
+ // The MachineLocation needs to implement HasSubnetHostname for the Attributes.SUBNET_HOSTNAME
+ // to be set with the subnet addresss (otherwise it will fall back to using machine.getAddress()).
+ // See Machines.getSubnetHostname.
+
+ TrackingAbstractController controller2 = app.addChild(EntitySpec.create(TrackingAbstractController.class)
+ .configure(TrackingAbstractController.SERVER_POOL, cluster)
+ .configure(TrackingAbstractController.PROXY_HTTP_PORT, PortRanges.fromInteger(8081))
+ .location(LocationSpec.create(SshMachineLocationWithSubnetHostname.class)
+ .configure("address", Inet4Address.getByName("1.1.1.1"))
+ .configure(SshMachineLocation.PRIVATE_ADDRESSES, ImmutableList.of("2.2.2.2"))));
+ controller2.start(ImmutableList.<Location>of());
+
+ EntityAsserts.assertAttributeEquals(controller2, Attributes.ADDRESS, "1.1.1.1");
+ EntityAsserts.assertAttributeEquals(controller2, Attributes.SUBNET_ADDRESS, "2.2.2.2");
+ EntityAsserts.assertAttributeEquals(controller2, Attributes.MAIN_URI, URI.create("http://2.2.2.2:8081/"));
+ EntityAsserts.assertAttributeEquals(controller2, Attributes.MAIN_URI_MAPPED_PUBLIC, URI.create("http://1.1.1.1:8081/"));
+ EntityAsserts.assertAttributeEquals(controller2, Attributes.MAIN_URI_MAPPED_SUBNET, URI.create("http://2.2.2.2:8081/"));
+ }
+ public static class SshMachineLocationWithSubnetHostname extends SshMachineLocation implements HasSubnetHostname {
+ @Override public String getSubnetHostname() {
+ return getSubnetIp();
+ }
+ @Override public String getSubnetIp() {
+ Set<String> addrs = getPrivateAddresses();
+ return (addrs.isEmpty()) ? getAddress().getHostAddress() : Iterables.get(addrs, 0);
+ }
+ }
+
private void assertEventuallyAddressesMatchCluster() {
assertEventuallyAddressesMatch(cluster.getMembers());
}
private void assertEventuallyAddressesMatch(final Collection<Entity> expectedMembers) {
- Asserts.succeedsEventually(MutableMap.of("timeout", 15000), new Runnable() {
+ Asserts.succeedsEventually(new Runnable() {
@Override public void run() {
assertAddressesMatch(locationsToAddresses(1234, expectedMembers));
}} );
}
private void assertEventuallyExplicitAddressesMatch(final Collection<String> expectedAddresses) {
- Asserts.succeedsEventually(MutableMap.of("timeout", 15000), new Runnable() {
+ Asserts.succeedsEventually(new Runnable() {
@Override public void run() {
assertAddressesMatch(expectedAddresses);
}} );
@@ -329,24 +372,14 @@
private Collection<String> locationsToAddresses(int port, Collection<Entity> entities) {
Set<String> result = MutableSet.of();
- for (Entity e: entities) {
- result.add( ((SshMachineLocation) e.getLocations().iterator().next()) .getAddress().getHostName()+":"+port);
+ for (Entity e : entities) {
+ SshMachineLocation machine = Machines.findUniqueMachineLocation(e.getLocations(), SshMachineLocation.class).get();
+ result.add(machine.getAddress().getHostName()+":"+port);
}
return result;
}
- public static class ClusteredEntity extends TestEntityImpl {
- public static class Factory implements EntityFactory<ClusteredEntity> {
- @Override
- public ClusteredEntity newEntity(Map flags, Entity parent) {
- return new ClusteredEntity(flags, parent);
- }
- }
- public ClusteredEntity(Map flags, Entity parent) { super(flags,parent); }
- public ClusteredEntity(Entity parent) { super(MutableMap.of(),parent); }
- public ClusteredEntity(Map flags) { super(flags,null); }
- public ClusteredEntity() { super(MutableMap.of(),null); }
-
+ public static class WebServerEntity extends TestEntityImpl {
@SetFromFlag("hostname")
public static final AttributeSensor<String> HOSTNAME = Attributes.HOSTNAME;
@@ -356,10 +389,11 @@
@SetFromFlag("hostAndPort")
public static final AttributeSensor<String> HOST_AND_PORT = Attributes.HOST_AND_PORT;
- MachineProvisioningLocation provisioner;
+ MachineProvisioningLocation<MachineLocation> provisioner;
+ @Override
public void start(Collection<? extends Location> locs) {
- provisioner = (MachineProvisioningLocation) locs.iterator().next();
+ provisioner = (MachineProvisioningLocation<MachineLocation>) locs.iterator().next();
MachineLocation machine;
try {
machine = provisioner.obtain(MutableMap.of());
@@ -369,9 +403,16 @@
addLocations(Arrays.asList(machine));
sensors().set(HOSTNAME, machine.getAddress().getHostName());
sensors().set(Attributes.SUBNET_HOSTNAME, machine.getAddress().getHostName());
+ sensors().set(Attributes.MAIN_URI_MAPPED_SUBNET, URI.create(machine.getAddress().getHostName()));
+ sensors().set(Attributes.MAIN_URI_MAPPED_PUBLIC, URI.create("http://8.8.8.8:" + sensors().get(HTTP_PORT)));
}
+
+ @Override
public void stop() {
- if (provisioner!=null) provisioner.release((MachineLocation) firstLocation());
+ Maybe<MachineLocation> machine = Machines.findUniqueMachineLocation(getLocations(), MachineLocation.class);
+ if (provisioner != null) {
+ provisioner.release(machine.get());
+ }
}
}
}
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/StubAppServer.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/StubAppServer.java
index 7d18021..717c5d9 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/StubAppServer.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/StubAppServer.java
@@ -18,69 +18,15 @@
*/
package org.apache.brooklyn.entity.proxy;
-import java.util.Collection;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-
import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.location.MachineLocation;
-import org.apache.brooklyn.api.location.MachineProvisioningLocation;
-import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.api.entity.ImplementedBy;
import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.core.entity.AbstractEntity;
import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.trait.Startable;
import org.apache.brooklyn.core.sensor.PortAttributeSensorAndConfigKey;
-import org.apache.brooklyn.util.collections.MutableMap;
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-
-public class StubAppServer extends AbstractEntity implements Startable {
+@ImplementedBy(StubAppServerImpl.class)
+public interface StubAppServer extends Entity, Startable {
public static final AttributeSensor<String> HOSTNAME = Attributes.HOSTNAME;
public static final PortAttributeSensorAndConfigKey HTTP_PORT = Attributes.HTTP_PORT;
- public static AtomicInteger nextPort = new AtomicInteger(1234);
-
- public StubAppServer(Map flags) {
- super(flags);
- }
-
- public StubAppServer(Map flags, Entity parent) {
- super(flags, parent);
- }
-
- @Override
- public void start(Collection<? extends Location> locations) {
- Location location = Iterables.getOnlyElement(locations);
- if (location instanceof MachineProvisioningLocation) {
- startInLocation((MachineProvisioningLocation)location);
- } else {
- startInLocation((MachineLocation)location);
- }
- }
-
- private void startInLocation(MachineProvisioningLocation loc) {
- try {
- startInLocation(loc.obtain(MutableMap.of()));
- } catch (NoMachinesAvailableException e) {
- throw Throwables.propagate(e);
- }
- }
-
- private void startInLocation(MachineLocation loc) {
- addLocations(ImmutableList.of((Location)loc));
- sensors().set(HOSTNAME, loc.getAddress().getHostName());
- sensors().set(HTTP_PORT, nextPort.getAndIncrement());
- sensors().set(SERVICE_UP, true);
- }
-
- public void stop() {
- sensors().set(SERVICE_UP, false);
- }
-
- @Override
- public void restart() {
- }
-}
\ No newline at end of file
+}
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/StubAppServerImpl.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/StubAppServerImpl.java
new file mode 100644
index 0000000..7a51432
--- /dev/null
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/StubAppServerImpl.java
@@ -0,0 +1,70 @@
+/*
+ * 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.entity.proxy;
+
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.MachineLocation;
+import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.core.entity.AbstractEntity;
+import org.apache.brooklyn.util.collections.MutableMap;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+public class StubAppServerImpl extends AbstractEntity implements StubAppServer {
+ public static AtomicInteger nextPort = new AtomicInteger(1234);
+
+ @Override
+ public void start(Collection<? extends Location> locations) {
+ Location location = Iterables.getOnlyElement(locations);
+ if (location instanceof MachineProvisioningLocation) {
+ startInLocation((MachineProvisioningLocation)location);
+ } else {
+ startInLocation((MachineLocation)location);
+ }
+ }
+
+ private void startInLocation(MachineProvisioningLocation loc) {
+ try {
+ startInLocation(loc.obtain(MutableMap.of()));
+ } catch (NoMachinesAvailableException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ private void startInLocation(MachineLocation loc) {
+ addLocations(ImmutableList.of((Location)loc));
+ sensors().set(HOSTNAME, loc.getAddress().getHostName());
+ sensors().set(HTTP_PORT, nextPort.getAndIncrement());
+ sensors().set(SERVICE_UP, true);
+ }
+
+ public void stop() {
+ sensors().set(SERVICE_UP, false);
+ }
+
+ @Override
+ public void restart() {
+ }
+}
\ No newline at end of file
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/UrlMappingTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/UrlMappingTest.java
index a571627..65a6b4e 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/UrlMappingTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/UrlMappingTest.java
@@ -32,8 +32,6 @@
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.EntityInternal;
import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
-import org.apache.brooklyn.core.entity.factory.BasicConfigurableEntityFactory;
-import org.apache.brooklyn.core.entity.factory.EntityFactory;
import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
import org.apache.brooklyn.core.mgmt.rebind.RebindTestUtils;
import org.apache.brooklyn.core.test.entity.TestApplication;
@@ -79,10 +77,10 @@
app = ApplicationBuilder.newManagedApp(TestApplication.class, managementContext);
- EntityFactory<StubAppServer> serverFactory = new BasicConfigurableEntityFactory<StubAppServer>(StubAppServer.class);
+ EntitySpec<StubAppServer> serverSpec = EntitySpec.create(StubAppServer.class);
cluster = app.createAndManageChild(EntitySpec.create(DynamicCluster.class)
- .configure("initialSize", initialClusterSize)
- .configure("factory", serverFactory));
+ .configure(DynamicCluster.INITIAL_SIZE, initialClusterSize)
+ .configure(DynamicCluster.MEMBER_SPEC, serverSpec));
urlMapping = app.createAndManageChild(EntitySpec.create(UrlMapping.class)
.configure("domain", "localhost")
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxIntegrationTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxIntegrationTest.java
index f2c25d2..c533b8d 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxIntegrationTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxIntegrationTest.java
@@ -30,8 +30,8 @@
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.core.entity.EntityAsserts;
-import org.apache.brooklyn.core.entity.factory.EntityFactory;
import org.apache.brooklyn.core.test.BrooklynAppLiveTestSupport;
+import org.apache.brooklyn.core.test.entity.TestEntity;
import org.apache.brooklyn.entity.group.DynamicCluster;
import org.apache.brooklyn.entity.software.base.SoftwareProcess;
import org.apache.brooklyn.entity.webapp.JavaWebAppService;
@@ -79,10 +79,7 @@
public void testWhenNoServersReturns404() {
serverPool = app.createAndManageChild(EntitySpec.create(DynamicCluster.class)
.configure("initialSize", 0)
- .configure(DynamicCluster.FACTORY, new EntityFactory<Entity>() {
- @Override public Entity newEntity(Map flags, Entity parent) {
- throw new UnsupportedOperationException();
- }}));
+ .configure("memberSpec", EntitySpec.create(TestEntity.class)));
nginx = app.createAndManageChild(EntitySpec.create(NginxController.class)
.configure("serverPool", serverPool)
@@ -98,10 +95,7 @@
public void testRestart() {
serverPool = app.createAndManageChild(EntitySpec.create(DynamicCluster.class)
.configure("initialSize", 0)
- .configure(DynamicCluster.FACTORY, new EntityFactory<Entity>() {
- @Override public Entity newEntity(Map flags, Entity parent) {
- throw new UnsupportedOperationException();
- }}));
+ .configure("memberSpec", EntitySpec.create(TestEntity.class)));
nginx = app.createAndManageChild(EntitySpec.create(NginxController.class)
.configure("serverPool", serverPool)
@@ -244,10 +238,7 @@
public void testTwoNginxesGetDifferentPorts() {
serverPool = app.createAndManageChild(EntitySpec.create(DynamicCluster.class)
.configure("initialSize", 0)
- .configure(DynamicCluster.FACTORY, new EntityFactory<Entity>() {
- @Override public Entity newEntity(Map flags, Entity parent) {
- throw new UnsupportedOperationException();
- }}));
+ .configure("memberSpec", EntitySpec.create(TestEntity.class)));
NginxController nginx1 = app.createAndManageChild(EntitySpec.create(NginxController.class)
.configure("serverPool", serverPool)
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxLightIntegrationTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxLightIntegrationTest.java
index 4f80698..78759af 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxLightIntegrationTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxLightIntegrationTest.java
@@ -25,8 +25,6 @@
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.core.entity.Attributes;
-import org.apache.brooklyn.core.entity.factory.BasicConfigurableEntityFactory;
-import org.apache.brooklyn.core.entity.factory.EntityFactory;
import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
import org.apache.brooklyn.entity.group.DynamicCluster;
import org.apache.brooklyn.entity.proxy.StubAppServer;
@@ -39,20 +37,17 @@
public class NginxLightIntegrationTest extends BrooklynAppUnitTestSupport {
- private NginxController nginx;
- private DynamicCluster cluster;
-
// FIXME Fails because getting addEntity callback for group members while nginx is still starting,
// so important nginx fields are still null. Therefore get NPE for cluster members, and thus targets
// is of size zero.
@Test(groups = {"Integration", "WIP"})
public void testNginxTargetsMatchesClusterMembers() {
- EntityFactory<StubAppServer> serverFactory = new BasicConfigurableEntityFactory<StubAppServer>(StubAppServer.class);
+ EntitySpec<StubAppServer> serverSpec = EntitySpec.create(StubAppServer.class);
final DynamicCluster cluster = app.createAndManageChild(EntitySpec.create(DynamicCluster.class)
.configure("initialSize", 2)
- .configure("factory", serverFactory));
+ .configure(DynamicCluster.MEMBER_SPEC, serverSpec));
- nginx = app.createAndManageChild(EntitySpec.create(NginxController.class)
+ final NginxController nginx = app.createAndManageChild(EntitySpec.create(NginxController.class)
.configure("serverPool", cluster)
.configure("domain", "localhost"));
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxUrlMappingIntegrationTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxUrlMappingIntegrationTest.java
index 1aee752..9f40dd0 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxUrlMappingIntegrationTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxUrlMappingIntegrationTest.java
@@ -27,7 +27,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import org.apache.brooklyn.api.entity.Entity;
@@ -36,16 +35,14 @@
import org.apache.brooklyn.api.mgmt.EntityManager;
import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.Entities;
-import org.apache.brooklyn.core.entity.factory.EntityFactory;
import org.apache.brooklyn.core.test.BrooklynAppLiveTestSupport;
+import org.apache.brooklyn.core.test.entity.TestEntity;
import org.apache.brooklyn.entity.group.BasicGroup;
import org.apache.brooklyn.entity.group.DynamicCluster;
-import org.apache.brooklyn.entity.proxy.nginx.NginxController;
-import org.apache.brooklyn.entity.proxy.nginx.UrlMapping;
-import org.apache.brooklyn.entity.proxy.nginx.UrlRewriteRule;
import org.apache.brooklyn.entity.webapp.JavaWebAppService;
import org.apache.brooklyn.entity.webapp.WebAppService;
import org.apache.brooklyn.entity.webapp.tomcat.Tomcat8Server;
+import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.test.Asserts;
import org.apache.brooklyn.test.HttpTestUtils;
import org.apache.brooklyn.test.support.TestResourceUnavailableException;
@@ -53,7 +50,6 @@
import org.slf4j.LoggerFactory;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
@@ -429,10 +425,7 @@
public void testUrlMappingWithEmptyCoreCluster() throws Exception {
DynamicCluster nullCluster = app.createAndManageChild(EntitySpec.create(DynamicCluster.class)
.configure("initialSize", 0)
- .configure("factory", new EntityFactory<Entity>() {
- public Entity newEntity(Map flags, Entity parent) {
- throw new UnsupportedOperationException();
- }}));
+ .configure("membeSpec", EntitySpec.create(TestEntity.class)));
DynamicCluster c0 = app.createAndManageChild(EntitySpec.create(DynamicCluster.class)
.configure("initialSize", 1)
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java
index b4c7cb3..a6c9b2f 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java
@@ -39,7 +39,6 @@
import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntityLocal;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.mgmt.ManagementContext;
import org.apache.brooklyn.api.mgmt.SubscriptionHandle;
@@ -474,7 +473,7 @@
URL resource = getClass().getClassLoader().getResource(war);
assertNotNull(resource);
- ((EntityLocal)entity).config().set(JavaWebAppService.ROOT_WAR, resource.toString());
+ entity.config().set(JavaWebAppService.ROOT_WAR, resource.toString());
Entities.start(entity.getApplication(), ImmutableList.of(loc));
//tomcat may need a while to unpack everything
@@ -496,7 +495,7 @@
URL resource = getClass().getClassLoader().getResource(war);
assertNotNull(resource);
- ((EntityLocal)entity).config().set(JavaWebAppService.NAMED_WARS, ImmutableList.of(resource.toString()));
+ entity.config().set(JavaWebAppService.NAMED_WARS, ImmutableList.of(resource.toString()));
Entities.start(entity.getApplication(), ImmutableList.of(loc));
Asserts.succeedsEventually(MutableMap.of("timeout", 60*1000), new Runnable() {
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/DynamicWebAppClusterTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/DynamicWebAppClusterTest.java
index dfdc10a..5b9519c 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/DynamicWebAppClusterTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/DynamicWebAppClusterTest.java
@@ -21,7 +21,6 @@
import static org.testng.Assert.assertEquals;
import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntityLocal;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.Entities;
@@ -98,7 +97,7 @@
EntityAsserts.assertAttributeEqualsEventually(cluster, DynamicWebAppCluster.SERVICE_UP, true);
// When child is !service_up, should report false
- ((EntityLocal)Iterables.get(cluster.getMembers(), 0)).sensors().set(Startable.SERVICE_UP, false);
+ Iterables.get(cluster.getMembers(), 0).sensors().set(Startable.SERVICE_UP, false);
EntityAsserts.assertAttributeEqualsEventually(cluster, DynamicWebAppCluster.SERVICE_UP, false);
EntityAsserts.assertAttributeEqualsContinually(MutableMap.of("timeout", SHORT_WAIT_MS), cluster, DynamicWebAppCluster.SERVICE_UP, false);
@@ -109,7 +108,7 @@
// And if that serviceUp child goes away, should again report false
Entities.unmanage(Iterables.get(cluster.getMembers(), 1));
- ((EntityLocal)Iterables.get(cluster.getMembers(), 0)).sensors().set(Startable.SERVICE_UP, false);
+ Iterables.get(cluster.getMembers(), 0).sensors().set(Startable.SERVICE_UP, false);
EntityAsserts.assertAttributeEqualsEventually(cluster, DynamicWebAppCluster.SERVICE_UP, false);
}
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/DynamicWebAppFabricTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/DynamicWebAppFabricTest.java
index 10d07d0..a00f682 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/DynamicWebAppFabricTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/DynamicWebAppFabricTest.java
@@ -21,7 +21,6 @@
import java.util.List;
import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntityLocal;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.EntityAsserts;
@@ -73,7 +72,7 @@
app.start(locs);
for (Entity member : fabric.getChildren()) {
- ((EntityLocal)member).sensors().set(Changeable.GROUP_SIZE, 1);
+ member.sensors().set(Changeable.GROUP_SIZE, 1);
}
for (Entity member : fabric.getChildren()) {