You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2015/12/17 12:59:49 UTC

[1/7] incubator-brooklyn git commit: Hazelcast Cluster support

Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master 85ff6afb0 -> 085e1cc5b


Hazelcast Cluster support

- Upgrade Hazelcast to v.3.5.4
- Small refactoring
- Adding integration tests

Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/894890af
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/894890af
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/894890af

Branch: refs/heads/master
Commit: 894890afe58f9662cc05deda73ee61ad02db32f4
Parents: 2cdd880
Author: Yavor Yanchev <ya...@yanchev.com>
Authored: Mon Dec 14 03:12:22 2015 +0200
Committer: Yavor Yanchev <ya...@yanchev.com>
Committed: Mon Dec 14 03:20:22 2015 +0200

----------------------------------------------------------------------
 software/nosql/pom.xml                          |   8 ++
 .../nosql/hazelcast/HazelcastCluster.java       |   1 -
 .../nosql/hazelcast/HazelcastClusterImpl.java   |   6 +-
 .../entity/nosql/hazelcast/HazelcastNode.java   |   8 +-
 .../nosql/hazelcast/HazelcastNodeImpl.java      |   1 -
 .../nosql/hazelcast/HazelcastNodeSshDriver.java |  50 +++++----
 .../nosql/hazelcast/hazelcast-brooklyn.xml      |  21 ++--
 .../hazelcast/HazelcastClusterEc2LiveTest.java  |  29 +----
 .../HazelcastClusterNodeIntegrationTest.java    |  49 +++++++++
 .../HazelcastClusterSoftlayerLiveTest.java      |  29 +----
 .../hazelcast/HazelcastNodeIntegrationTest.java | 107 +++++++++++++++++++
 .../nosql/hazelcast/HazelcastTestHelper.java    |  76 +++++++++++++
 12 files changed, 288 insertions(+), 97 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/894890af/software/nosql/pom.xml
----------------------------------------------------------------------
diff --git a/software/nosql/pom.xml b/software/nosql/pom.xml
index e3e9acf..32dbeb6 100644
--- a/software/nosql/pom.xml
+++ b/software/nosql/pom.xml
@@ -173,6 +173,14 @@
             </exclusions>
         </dependency>
 
+        <!-- for hazelcast testing -->
+        <dependency>
+            <groupId>com.hazelcast</groupId>
+            <artifactId>hazelcast-client</artifactId>
+            <version>${hazelcast.version}</version>
+            <scope>test</scope>
+        </dependency>
+
         <!-- for solr testing -->
         <dependency>
             <groupId>org.apache.solr</groupId>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/894890af/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java
index c43e882..3962fd1 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java
@@ -56,5 +56,4 @@ public interface HazelcastCluster extends DynamicCluster {
     String getClusterName();
     
     String getClusterPassword();
-    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/894890af/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java
index 83cf15a..854c0a3 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java
@@ -44,9 +44,10 @@ public class HazelcastClusterImpl extends DynamicClusterImpl implements Hazelcas
     
     @Override
     protected EntitySpec<?> getMemberSpec() {
-        EntitySpec<?> spec = EntitySpec.create(getConfig(MEMBER_SPEC, EntitySpec.create(HazelcastNode.class)));
+        EntitySpec<?> spec = EntitySpec.create(config().get(HazelcastCluster.MEMBER_SPEC));
         
-        spec.configure(HazelcastNode.GROUP_NAME, getConfig(HazelcastClusterImpl.CLUSTER_NAME));
+        spec.configure(HazelcastNode.NODE_CLUSTER_NAME, config().get(HazelcastCluster.CLUSTER_NAME));
+        spec.configure(HazelcastNode.GROUP_NAME, config().get(HazelcastCluster.CLUSTER_NAME));
         
         if (LOG.isInfoEnabled()) {
             LOG.info("Cluster name : {} : used as a group name", getConfig(HazelcastNode.GROUP_NAME));
@@ -115,7 +116,6 @@ public class HazelcastClusterImpl extends DynamicClusterImpl implements Hazelcas
     public void start(Collection<? extends Location> locations) {
         super.start(locations);
         
-        
         List<String> clusterNodes = Lists.newArrayList();
         for (Entity member : getMembers()) {
             clusterNodes.add(member.getAttribute(Attributes.ADDRESS));

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/894890af/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNode.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNode.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNode.java
index e53d0da..768179c 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNode.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNode.java
@@ -40,7 +40,7 @@ import org.apache.brooklyn.util.javalang.JavaClassNames;
 @ImplementedBy(HazelcastNodeImpl.class)
 public interface HazelcastNode extends SoftwareProcess, UsesJava, UsesJmx {
     @SetFromFlag("version")
-    ConfigKey<String> SUGGESTED_VERSION = ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION, "3.4.2");
+    ConfigKey<String> SUGGESTED_VERSION = ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION, "3.5.4");
     
     @SetFromFlag("downloadUrl")
     BasicAttributeSensorAndConfigKey<String> DOWNLOAD_URL = new BasicAttributeSensorAndConfigKey<String>(
@@ -53,7 +53,7 @@ public interface HazelcastNode extends SoftwareProcess, UsesJava, UsesJmx {
     
     @SetFromFlag("configFileName")
     ConfigKey<String> CONFIG_FILE_NAME = ConfigKeys.newStringConfigKey(
-            "hazelcast.node.config.fileName", "Name of the Hazelcast config file", "hazelcast.xml");    
+            "hazelcast.node.config.fileName", "Name of the Hazelcast config file", "hazelcast.xml");
     
     @SetFromFlag("nodeName")
     StringAttributeSensorAndConfigKey NODE_NAME = new StringAttributeSensorAndConfigKey("hazelcast.node.name", 
@@ -66,6 +66,10 @@ public interface HazelcastNode extends SoftwareProcess, UsesJava, UsesJmx {
     @SetFromFlag("nodePort")
     PortAttributeSensorAndConfigKey NODE_PORT = new PortAttributeSensorAndConfigKey("hazelcast.node.port", "Hazelcast communication port", PortRanges.fromString("5701+"));
 
+    @SetFromFlag("nodeClusterName")
+    BasicAttributeSensorAndConfigKey<String> NODE_CLUSTER_NAME = new BasicAttributeSensorAndConfigKey<String>(String.class, 
+            "hazelcast.node.cluster.name", "Name of the Hazelcast cluster which node is part of", "");
+
     /**
      * Specifies the group name in the configuration file. Each Hazelcast cluster has a separate group.
      */ 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/894890af/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java
index 6e17737..6d13b74 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java
@@ -134,7 +134,6 @@ public class HazelcastNodeImpl extends SoftwareProcessImpl implements HazelcastN
             LOG.info("Node {} is listening on {}", this, listenAddress);
         }
 
-         
         return listenAddress;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/894890af/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java
index 2d67453..2a9b9c5 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java
@@ -21,13 +21,11 @@ package org.apache.brooklyn.entity.nosql.hazelcast;
 import static java.lang.String.format;
 
 import java.util.List;
-import java.util.concurrent.ExecutionException;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntityLocal;
 import org.apache.brooklyn.core.entity.Entities;
 
 import org.apache.brooklyn.entity.java.JavaSoftwareProcessSshDriver;
@@ -35,7 +33,9 @@ import org.apache.brooklyn.location.ssh.SshMachineLocation;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.os.Os;
 import org.apache.brooklyn.util.ssh.BashCommands;
+import org.apache.brooklyn.util.text.Strings;
 
+import com.google.common.base.Joiner;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 
@@ -43,7 +43,7 @@ public class HazelcastNodeSshDriver extends JavaSoftwareProcessSshDriver impleme
     
     private static final Logger LOG = LoggerFactory.getLogger(HazelcastNodeSshDriver.class);
 
-    public HazelcastNodeSshDriver(EntityLocal entity, SshMachineLocation machine) {
+    public HazelcastNodeSshDriver(HazelcastNodeImpl entity, SshMachineLocation machine) {
         super(entity, machine);
     }
 
@@ -98,15 +98,16 @@ public class HazelcastNodeSshDriver extends JavaSoftwareProcessSshDriver impleme
         // Setting initial heap size (Xms) size to match max heap size (Xms) at first
         String initialHeapMemorySize = maxHeapMemorySize;
         
-        StringBuilder commandBuilder = new StringBuilder()
-            .append(format("nohup java -cp ./lib/%s", resolver.getFilename()))
-            .append(format(" -Xmx%s -Xms%s", maxHeapMemorySize, initialHeapMemorySize))
-            .append(format(" -Dhazelcast.config=./conf/%s", getConfigFileName()))
-            .append(format(" com.hazelcast.core.server.StartServer >> %s 2>&1 </dev/null &", getLogFileLocation()));
+        ImmutableList<String> commands = ImmutableList.<String>builder()
+            .add(format("nohup java -cp ./lib/%s", resolver.getFilename()))
+            .add(format("-Xmx%s -Xms%s", maxHeapMemorySize, initialHeapMemorySize))
+            .add(format("-Dhazelcast.config=./conf/%s", getConfigFileName()))
+            .add(format("com.hazelcast.core.server.StartServer >> %s 2>&1 </dev/null &", getLogFileLocation()))
+            .build();
         
         newScript(MutableMap.of(USE_PID_FILE, true), LAUNCHING)
             .updateTaskAndFailOnNonZeroResultCode()
-            .body.append(commandBuilder.toString())
+            .body.append(Joiner.on(" ").join(commands))
             .execute();
     }
        
@@ -119,7 +120,7 @@ public class HazelcastNodeSshDriver extends JavaSoftwareProcessSshDriver impleme
     }
     
     @Override
-    public boolean isRunning() {       
+    public boolean isRunning() {
         return newScript(MutableMap.of(USE_PID_FILE, true), CHECK_RUNNING).execute() == 0;
     }
     
@@ -133,22 +134,26 @@ public class HazelcastNodeSshDriver extends JavaSoftwareProcessSshDriver impleme
         newScript(MutableMap.of(USE_PID_FILE, true), KILLING).execute();
     }
 
-    public List<String> getHazelcastNodesList() throws ExecutionException, InterruptedException {
-        HazelcastCluster cluster = (HazelcastCluster) entity.getParent();
+    public List<String> getHazelcastNodesList() {
         List<String> result = Lists.newArrayList();
 
-        for (Entity member : cluster.getMembers()) {
-            String address = Entities.attributeSupplierWhenReady(member, HazelcastNode.SUBNET_ADDRESS).get();
-            Integer port = Entities.attributeSupplierWhenReady(member, HazelcastNode.NODE_PORT).get();
-            
-            String addressAndPort = String.format("%s:%d", address, port);
-            
-            if (LOG.isInfoEnabled()) {
-                LOG.info("Adding {} to the members' list of {}", addressAndPort, entity.getAttribute(HazelcastNode.NODE_NAME));
+        if (Strings.isBlank(entity.getAttribute(HazelcastNode.NODE_CLUSTER_NAME))) {
+            result.add(String.format("%s:%d", entity.getAttribute(HazelcastNode.SUBNET_ADDRESS),
+                                              entity.getAttribute(HazelcastNode.NODE_PORT)));
+        } else {
+            HazelcastCluster cluster = (HazelcastCluster) entity.getParent();
+
+            for (Entity member : cluster.getMembers()) {
+                String address = Entities.attributeSupplierWhenReady(member, HazelcastNode.SUBNET_ADDRESS).get();
+                Integer port = Entities.attributeSupplierWhenReady(member, HazelcastNode.NODE_PORT).get();
+                String addressAndPort = String.format("%s:%d", address, port);
+
+                if (LOG.isInfoEnabled()) {
+                    LOG.info("Adding {} to the members' list of {}", addressAndPort, entity.getAttribute(HazelcastNode.NODE_NAME));
+                }
+                result.add(addressAndPort);
             }
-            result.add(addressAndPort);
         }
-        
         return result;
     }
 
@@ -156,5 +161,4 @@ public class HazelcastNodeSshDriver extends JavaSoftwareProcessSshDriver impleme
     protected String getLogFileLocation() {
         return Os.mergePathsUnix(getRunDir(),"/log/out.log");
     }
-    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/894890af/software/nosql/src/main/resources/org/apache/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/resources/org/apache/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml b/software/nosql/src/main/resources/org/apache/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml
index 459be4e..2f4a263 100644
--- a/software/nosql/src/main/resources/org/apache/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml
+++ b/software/nosql/src/main/resources/org/apache/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml
@@ -1,9 +1,15 @@
 [#ftl]
 <?xml version="1.0" encoding="UTF-8"?>
 
-<hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.4.xsd"
-           xmlns="http://www.hazelcast.com/schema/config"
-           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<hazelcast xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xsi:schemaLocation="http://www.hazelcast.com/schema/config
+                               http://www.hazelcast.com/schema/config/hazelcast-config-3.5.xsd"
+           xmlns="http://www.hazelcast.com/schema/config">
+
+    <properties>
+        <property name="hazelcast.discovery.enabled">true</property>
+    </properties>
+
     <group>
         <name>${entity.groupName}</name>
         <password>${entity.groupPassword}</password>
@@ -18,11 +24,7 @@
             -->
             <ports>0</ports>
         </outbound-ports>
-        
-        <interfaces enabled="true">
-            <interface>${entity.listenAddress}</interface> 
-        </interfaces> 
-        
+
         <join>
             <multicast enabled="false" />
 
@@ -31,14 +33,11 @@
                 <member>${member}</member>
             [/#list]
             </tcp-ip>
-            
             <aws enabled="false" />
-
         </join>
 
         <ssl enabled="false"/>
         <socket-interceptor enabled="false"/>
-        <symmetric-encryption enabled="false"/>
 
     </network>
     <partition-group enabled="false"/>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/894890af/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java
index f1d44fc..111ba9e 100644
--- a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java
+++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java
@@ -18,21 +18,12 @@
  */
 package org.apache.brooklyn.entity.nosql.hazelcast;
 
-import org.apache.brooklyn.entity.nosql.hazelcast.HazelcastCluster;
-import org.apache.brooklyn.entity.nosql.hazelcast.HazelcastNode;
-import org.apache.brooklyn.test.EntityTestUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.annotations.Test;
 
 import org.apache.brooklyn.entity.AbstractEc2LiveTest;
-
-import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.core.entity.Attributes;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
 
 public class HazelcastClusterEc2LiveTest extends AbstractEc2LiveTest {
     @SuppressWarnings("unused")
@@ -40,25 +31,7 @@ public class HazelcastClusterEc2LiveTest extends AbstractEc2LiveTest {
 
     @Override
     protected void doTest(Location loc) throws Exception {
-        HazelcastCluster cluster = app.createAndManageChild(EntitySpec.create(HazelcastCluster.class)
-                .configure(HazelcastCluster.INITIAL_SIZE, 3)
-                .configure(HazelcastCluster.MEMBER_SPEC, EntitySpec.create(HazelcastNode.class)));
-        app.start(ImmutableList.of(loc));
-
-        EntityTestUtils.assertAttributeEqualsEventually(cluster, HazelcastNode.SERVICE_UP, true);
-
-        HazelcastNode first = (HazelcastNode) Iterables.get(cluster.getMembers(), 0);
-        HazelcastNode second = (HazelcastNode) Iterables.get(cluster.getMembers(), 1);
-
-        assertNodesUpAndInCluster(first, second);
-        
-        EntityTestUtils.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_UP, true);
-    }
-    
-    private void assertNodesUpAndInCluster(final HazelcastNode... nodes) {
-        for (final HazelcastNode node : nodes) {
-            EntityTestUtils.assertAttributeEqualsEventually(node, HazelcastNode.SERVICE_UP, true);
-        }
+        HazelcastTestHelper.testHazelcastCluster(app, loc);
     }
 
     @Test(enabled = false)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/894890af/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterNodeIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterNodeIntegrationTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterNodeIntegrationTest.java
new file mode 100644
index 0000000..dc89934
--- /dev/null
+++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterNodeIntegrationTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.nosql.hazelcast;
+
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
+
+public class HazelcastClusterNodeIntegrationTest {
+    private TestApplication app;
+    private Location location;
+
+    @BeforeMethod(alwaysRun = true)
+    public void setup() throws Exception {
+        app = TestApplication.Factory.newManagedInstanceForTests();;
+        location = new LocalhostMachineProvisioningLocation();
+    }
+
+    @AfterMethod(alwaysRun = true)
+    public void shutdown() {
+        Entities.destroyAll(app.getManagementContext());
+    }
+
+    @Test(groups = {"Integration"})
+    public void testHazelcastCluster() {
+        HazelcastTestHelper.testHazelcastCluster(app, location);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/894890af/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java
index 0e9fe0b..412ce87 100644
--- a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java
+++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java
@@ -18,21 +18,12 @@
  */
 package org.apache.brooklyn.entity.nosql.hazelcast;
 
-import org.apache.brooklyn.entity.nosql.hazelcast.HazelcastCluster;
-import org.apache.brooklyn.entity.nosql.hazelcast.HazelcastNode;
-import org.apache.brooklyn.test.EntityTestUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.annotations.Test;
 
 import org.apache.brooklyn.entity.AbstractSoftlayerLiveTest;
-
-import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.core.entity.Attributes;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
 
 public class HazelcastClusterSoftlayerLiveTest extends AbstractSoftlayerLiveTest {
     @SuppressWarnings("unused")
@@ -40,25 +31,7 @@ public class HazelcastClusterSoftlayerLiveTest extends AbstractSoftlayerLiveTest
 
     @Override
     protected void doTest(Location loc) throws Exception {
-        HazelcastCluster cluster = app.createAndManageChild(EntitySpec.create(HazelcastCluster.class)
-                .configure(HazelcastCluster.INITIAL_SIZE, 3)
-                .configure(HazelcastCluster.MEMBER_SPEC, EntitySpec.create(HazelcastNode.class)));
-        app.start(ImmutableList.of(loc));
-
-        EntityTestUtils.assertAttributeEqualsEventually(cluster, HazelcastNode.SERVICE_UP, true);
-
-        HazelcastNode first = (HazelcastNode) Iterables.get(cluster.getMembers(), 0);
-        HazelcastNode second = (HazelcastNode) Iterables.get(cluster.getMembers(), 1);
-
-        assertNodesUpAndInCluster(first, second);
-        
-        EntityTestUtils.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_UP, true);
-    }
-    
-    private void assertNodesUpAndInCluster(final HazelcastNode... nodes) {
-        for (final HazelcastNode node : nodes) {
-            EntityTestUtils.assertAttributeEqualsEventually(node, HazelcastNode.SERVICE_UP, true);
-        }
+        HazelcastTestHelper.testHazelcastCluster(app, loc);
     }
 
     @Test(enabled = false)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/894890af/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeIntegrationTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeIntegrationTest.java
new file mode 100644
index 0000000..26a18c5
--- /dev/null
+++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeIntegrationTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.nosql.hazelcast;
+
+import static org.testng.Assert.assertEquals;
+
+import java.net.URISyntaxException;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+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.trait.Startable;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.util.http.HttpTool;
+import org.apache.brooklyn.util.http.HttpToolResponse;
+import org.apache.http.client.methods.HttpGet;
+import com.hazelcast.core.HazelcastInstance;
+import com.hazelcast.core.IMap;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
+
+import com.google.common.collect.ImmutableList;
+
+public class HazelcastNodeIntegrationTest {
+    protected TestApplication app;
+    protected Location testLocation;
+    protected HazelcastNode hazelcastNode;
+
+    @BeforeMethod(alwaysRun = true)
+    public void setup() throws Exception {
+        app = TestApplication.Factory.newManagedInstanceForTests();;
+        testLocation = new LocalhostMachineProvisioningLocation();
+    }
+
+    @AfterMethod(alwaysRun = true)
+    public void shutdown() {
+        Entities.destroyAll(app.getManagementContext());
+    }
+    
+    @Test(groups = {"Integration"})
+    public void testHazelcastStartupAndShutdown() {
+        hazelcastNode = app.createAndManageChild(EntitySpec.create(HazelcastNode.class));
+        app.start(ImmutableList.of(testLocation));
+        EntityAsserts.assertAttributeEqualsEventually(hazelcastNode, Startable.SERVICE_UP, true);
+
+        hazelcastNode.stop();
+        EntityAsserts.assertAttributeEqualsEventually(hazelcastNode, Startable.SERVICE_UP, false);
+    }
+
+    @Test(groups = {"Integration"})
+    public void testHazelcastRestInterface() throws URISyntaxException {
+        hazelcastNode = app.createAndManageChild(EntitySpec.create(HazelcastNode.class));
+        app.start(ImmutableList.of(testLocation));
+
+        EntityAsserts.assertAttributeEqualsEventually(hazelcastNode, Startable.SERVICE_UP, true);
+        EntityAsserts.assertAttributeEquals(hazelcastNode, HazelcastNode.NODE_PORT, 5701);
+
+        String baseUri = String.format("http://%s:%d/hazelcast/rest/cluster", hazelcastNode.getAttribute(Attributes.HOSTNAME), hazelcastNode.getAttribute(HazelcastNode.NODE_PORT)); 
+        HttpToolResponse response = HttpTool.execAndConsume(
+                HttpTool.httpClientBuilder().build(),
+                new HttpGet(baseUri));
+        assertEquals(response.getResponseCode(), 200);
+    }
+
+    @Test(groups = {"Integration"})
+    public void testHazelcastClient() throws URISyntaxException {
+        hazelcastNode = app.createAndManageChild(EntitySpec.create(HazelcastNode.class));
+        app.start(ImmutableList.of(testLocation));
+
+        EntityAsserts.assertAttributeEqualsEventually(hazelcastNode, Startable.SERVICE_UP, true);
+        HazelcastTestHelper helper = new HazelcastTestHelper(hazelcastNode.getAttribute(Attributes.HOSTNAME), hazelcastNode.getAttribute(HazelcastNode.NODE_PORT));
+
+        HazelcastInstance client = helper.getClient();
+        HazelcastInstance client2 = helper.getClient();
+
+        client.getMap(HazelcastTestHelper.GROUP_NAME).put("A", "a");
+        client2.getMap(HazelcastTestHelper.GROUP_NAME).put("B", "b");
+
+        final IMap<Object, Object> map = client.getMap(HazelcastTestHelper.GROUP_NAME);
+        assertEquals("a", map.get("A"));
+        assertEquals("b", map.get("B"));
+
+        client.shutdown();
+        client2.shutdown();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/894890af/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastTestHelper.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastTestHelper.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastTestHelper.java
new file mode 100644
index 0000000..b48e0bd
--- /dev/null
+++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastTestHelper.java
@@ -0,0 +1,76 @@
+/*
+ * 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.nosql.hazelcast;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.core.entity.EntityAsserts;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.hazelcast.client.HazelcastClient;
+import com.hazelcast.client.config.ClientConfig;
+import com.hazelcast.core.HazelcastInstance;
+
+public class HazelcastTestHelper {
+    private static final Logger LOG = LoggerFactory.getLogger(HazelcastTestHelper.class);
+    private static ClientConfig clientConfig;
+
+    public static final String GROUP_NAME = "brooklyn";
+    public static final String GROUP_PASS = "brooklyn";
+
+    public HazelcastTestHelper(String hazelcastAddress, Integer hazelcastPort) {
+        clientConfig = new ClientConfig();
+        clientConfig.getGroupConfig().setName(GROUP_NAME).setPassword(GROUP_PASS);
+        clientConfig.getNetworkConfig().addAddress(String.format("%s:%d", hazelcastAddress, hazelcastPort));
+    }
+
+    public HazelcastInstance getClient() {
+        HazelcastInstance client = HazelcastClient.newHazelcastClient(clientConfig);
+        LOG.info("Hazelcast client {}", client.getName());
+
+        return client;
+    }
+
+    public static void testHazelcastCluster(TestApplication app, Location loc) {
+        HazelcastCluster cluster = app.createAndManageChild(EntitySpec.create(HazelcastCluster.class)
+                .configure(HazelcastCluster.INITIAL_SIZE, 3)
+                .configure(HazelcastCluster.MEMBER_SPEC, EntitySpec.create(HazelcastNode.class)));
+        app.start(ImmutableList.of(loc));
+
+        EntityAsserts.assertAttributeEqualsEventually(cluster, HazelcastNode.SERVICE_UP, true);
+
+        HazelcastNode first = (HazelcastNode) Iterables.get(cluster.getMembers(), 0);
+        HazelcastNode second = (HazelcastNode) Iterables.get(cluster.getMembers(), 1);
+
+        assertNodesUpAndInCluster(first, second);
+
+        EntityAsserts.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_UP, true);
+    }
+
+    private static void assertNodesUpAndInCluster(final HazelcastNode... nodes) {
+        for (final HazelcastNode node : nodes) {
+            EntityAsserts.assertAttributeEqualsEventually(node, HazelcastNode.SERVICE_UP, true);
+        }
+    }
+}


[3/7] incubator-brooklyn git commit: Moving HazelcastCluster out of the sandbox

Posted by he...@apache.org.
Moving HazelcastCluster out of the sandbox

Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/3635a465
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/3635a465
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/3635a465

Branch: refs/heads/master
Commit: 3635a46507085cac0e80ac448658f0f8e32133e1
Parents: ed928a5
Author: Yavor Yanchev <ya...@yanchev.com>
Authored: Fri Nov 27 01:41:15 2015 +0200
Committer: Yavor Yanchev <ya...@yanchev.com>
Committed: Mon Dec 14 03:20:22 2015 +0200

----------------------------------------------------------------------
 sandbox/nosql/pom.xml                           |  19 ---
 .../nosql/hazelcast/HazelcastCluster.java       |  60 -------
 .../nosql/hazelcast/HazelcastClusterImpl.java   | 125 ---------------
 .../entity/nosql/hazelcast/HazelcastNode.java   |  97 -----------
 .../nosql/hazelcast/HazelcastNodeDriver.java    |  25 ---
 .../nosql/hazelcast/HazelcastNodeImpl.java      | 147 -----------------
 .../nosql/hazelcast/HazelcastNodeSshDriver.java | 160 -------------------
 .../nosql/hazelcast/hazelcast-brooklyn.xml      |  65 --------
 .../hazelcast/HazelcastClusterEc2LiveTest.java  |  74 ---------
 .../HazelcastClusterSoftlayerLiveTest.java      |  74 ---------
 software/nosql/pom.xml                          |   1 +
 .../nosql/hazelcast/HazelcastCluster.java       |  60 +++++++
 .../nosql/hazelcast/HazelcastClusterImpl.java   | 125 +++++++++++++++
 .../entity/nosql/hazelcast/HazelcastNode.java   |  97 +++++++++++
 .../nosql/hazelcast/HazelcastNodeDriver.java    |  25 +++
 .../nosql/hazelcast/HazelcastNodeImpl.java      | 147 +++++++++++++++++
 .../nosql/hazelcast/HazelcastNodeSshDriver.java | 160 +++++++++++++++++++
 .../nosql/hazelcast/hazelcast-brooklyn.xml      |  65 ++++++++
 .../hazelcast/HazelcastClusterEc2LiveTest.java  |  74 +++++++++
 .../HazelcastClusterSoftlayerLiveTest.java      |  74 +++++++++
 20 files changed, 828 insertions(+), 846 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/sandbox/nosql/pom.xml
----------------------------------------------------------------------
diff --git a/sandbox/nosql/pom.xml b/sandbox/nosql/pom.xml
index d62be44..5b15536 100644
--- a/sandbox/nosql/pom.xml
+++ b/sandbox/nosql/pom.xml
@@ -76,23 +76,4 @@
             <scope>test</scope>
         </dependency>
     </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.rat</groupId>
-                <artifactId>apache-rat-plugin</artifactId>
-                <configuration>
-                    <excludes combine.children="append">
-                        <!--
-                            Configuration artifacts (for installations) are based on templated defaults for 
-                            the given components. These are files "without any degree of creativity" from the
-                            perspective of the Brooklyn/Apache contribution.
-                        -->
-                        <exclude>src/main/resources/org/apache/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml</exclude>
-                    </excludes>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java b/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java
deleted file mode 100644
index c43e882..0000000
--- a/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.brooklyn.entity.nosql.hazelcast;
-
-import java.util.List;
-
-import com.google.common.reflect.TypeToken;
-
-import org.apache.brooklyn.api.catalog.Catalog;
-import org.apache.brooklyn.api.entity.ImplementedBy;
-import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.util.core.flags.SetFromFlag;
-
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.sensor.BasicAttributeSensorAndConfigKey;
-import org.apache.brooklyn.core.sensor.Sensors;
-import org.apache.brooklyn.entity.group.DynamicCluster;
-
-/**
- * A cluster of {@link HazelcastNode}s based on {@link DynamicCluster}.
- */
-@Catalog(name="Hazelcast Cluster", description="Hazelcast is a clustering and highly scalable data distribution platform for Java.")
-
-@ImplementedBy(HazelcastClusterImpl.class)
-public interface HazelcastCluster extends DynamicCluster {
-
-    @SetFromFlag("clusterName")
-    BasicAttributeSensorAndConfigKey<String> CLUSTER_NAME = new BasicAttributeSensorAndConfigKey<String>(String.class, 
-            "hazelcast.cluster.name", "Name of the Hazelcast cluster", "HazelcastCluster");
-    
-    @SetFromFlag("clusterPassword")
-    ConfigKey<String> CLUSTER_PASSWORD =
-            ConfigKeys.newStringConfigKey("hazelcast.cluster.password", "Hazelcast cluster password.");
-    
-    @SuppressWarnings("serial")
-    AttributeSensor<List<String>> PUBLIC_CLUSTER_NODES = Sensors.newSensor(new TypeToken<List<String>>() {},
-        "hazelcast.cluster.public.nodes", "List of public addresses of all nodes in the cluster");
-    
-    String getClusterName();
-    
-    String getClusterPassword();
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java b/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java
deleted file mode 100644
index 83cf15a..0000000
--- a/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.brooklyn.entity.nosql.hazelcast;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Lists;
-import org.apache.brooklyn.api.entity.Entity;
-
-import org.apache.brooklyn.entity.group.AbstractMembershipTrackingPolicy;
-import org.apache.brooklyn.entity.group.DynamicClusterImpl;
-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.core.entity.Attributes;
-import org.apache.brooklyn.core.entity.EntityInternal;
-import org.apache.brooklyn.util.text.Strings;
-
-public class HazelcastClusterImpl extends DynamicClusterImpl implements HazelcastCluster {
-    private static final Logger LOG = LoggerFactory.getLogger(HazelcastClusterImpl.class);
-    
-    private static final AtomicInteger nextMemberId = new AtomicInteger(0);
-    
-    @Override
-    protected EntitySpec<?> getMemberSpec() {
-        EntitySpec<?> spec = EntitySpec.create(getConfig(MEMBER_SPEC, EntitySpec.create(HazelcastNode.class)));
-        
-        spec.configure(HazelcastNode.GROUP_NAME, getConfig(HazelcastClusterImpl.CLUSTER_NAME));
-        
-        if (LOG.isInfoEnabled()) {
-            LOG.info("Cluster name : {} : used as a group name", getConfig(HazelcastNode.GROUP_NAME));
-        }
-        
-        spec.configure(HazelcastNode.GROUP_PASSWORD, getClusterPassword());
-        
-        return spec;
-    }
-  
-    @Override
-    public void init() {
-        super.init();
-
-        String clusterPassword = getClusterPassword();
-        
-        if (Strings.isBlank(clusterPassword)) {
-            if (LOG.isInfoEnabled()) {
-                LOG.info(this + " cluster password not provided for " + CLUSTER_PASSWORD.getName() + " : generating random password");
-            }
-            config().set(CLUSTER_PASSWORD, Strings.makeRandomId(12));
-        }
-        
-        policies().add(PolicySpec.create(MemberTrackingPolicy.class)
-                .displayName("Hazelcast members tracker")
-                .configure("group", this));
-    }
-    
-    public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
-        @Override
-        protected void onEntityChange(Entity member) {
-        }
-
-        @Override
-        protected void onEntityAdded(Entity member) {
-            if (member.getAttribute(HazelcastNode.NODE_NAME) == null) {
-                ((EntityInternal) member).sensors().set(HazelcastNode.NODE_NAME, "hazelcast-" + nextMemberId.incrementAndGet());
-                if (LOG.isInfoEnabled()) {
-                    LOG.info("Node {} added to the cluster", member);
-                }
-            }
-        }
-
-        @Override
-        protected void onEntityRemoved(Entity member) {
-        }
-    };
-    
-    @Override
-    public String getClusterName() {
-        return getConfig(CLUSTER_NAME);
-    }
-
-    @Override
-    public String getClusterPassword() {
-        return getConfig(CLUSTER_PASSWORD);
-    }
-
-    @Override
-    protected void initEnrichers() {
-        super.initEnrichers();
-        
-    }
-    
-    @Override
-    public void start(Collection<? extends Location> locations) {
-        super.start(locations);
-        
-        
-        List<String> clusterNodes = Lists.newArrayList();
-        for (Entity member : getMembers()) {
-            clusterNodes.add(member.getAttribute(Attributes.ADDRESS));
-        }
-        sensors().set(PUBLIC_CLUSTER_NODES, clusterNodes);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNode.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNode.java b/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNode.java
deleted file mode 100644
index e53d0da..0000000
--- a/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNode.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.brooklyn.entity.nosql.hazelcast;
-
-import org.apache.brooklyn.api.catalog.Catalog;
-import org.apache.brooklyn.api.entity.ImplementedBy;
-import org.apache.brooklyn.util.core.flags.SetFromFlag;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.location.PortRanges;
-import org.apache.brooklyn.core.sensor.BasicAttributeSensorAndConfigKey;
-import org.apache.brooklyn.core.sensor.PortAttributeSensorAndConfigKey;
-import org.apache.brooklyn.core.sensor.BasicAttributeSensorAndConfigKey.StringAttributeSensorAndConfigKey;
-import org.apache.brooklyn.entity.software.base.SoftwareProcess;
-import org.apache.brooklyn.entity.java.UsesJava;
-import org.apache.brooklyn.entity.java.UsesJmx;
-import org.apache.brooklyn.util.javalang.JavaClassNames;
-
-/**
- * An {@link brooklyn.entity.Entity} that represents an Hazelcast node
- */
-@Catalog(name="Hazelcast Node", description="Hazelcast is a clustering and highly scalable data distribution platform for Java.")
-
-@ImplementedBy(HazelcastNodeImpl.class)
-public interface HazelcastNode extends SoftwareProcess, UsesJava, UsesJmx {
-    @SetFromFlag("version")
-    ConfigKey<String> SUGGESTED_VERSION = ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION, "3.4.2");
-    
-    @SetFromFlag("downloadUrl")
-    BasicAttributeSensorAndConfigKey<String> DOWNLOAD_URL = new BasicAttributeSensorAndConfigKey<String>(
-            SoftwareProcess.DOWNLOAD_URL, "https://repo1.maven.org/maven2/com/hazelcast/hazelcast/${version}/hazelcast-${version}.jar");
-    
-    @SetFromFlag("configTemplateUrl")
-    ConfigKey<String> CONFIG_TEMPLATE_URL = ConfigKeys.newStringConfigKey(
-            "hazelcast.node.config.templateUrl", "Template file (in freemarker format) for the Hazelcat config file", 
-            JavaClassNames.resolveClasspathUrl(HazelcastNode.class, "hazelcast-brooklyn.xml"));
-    
-    @SetFromFlag("configFileName")
-    ConfigKey<String> CONFIG_FILE_NAME = ConfigKeys.newStringConfigKey(
-            "hazelcast.node.config.fileName", "Name of the Hazelcast config file", "hazelcast.xml");    
-    
-    @SetFromFlag("nodeName")
-    StringAttributeSensorAndConfigKey NODE_NAME = new StringAttributeSensorAndConfigKey("hazelcast.node.name", 
-            "Node name (or randomly selected if not set", null);
-
-    @SetFromFlag("nodeHeapMemorySize")
-    ConfigKey<String> NODE_HEAP_MEMORY_SIZE = ConfigKeys.newStringConfigKey(
-            "hazelcast.node.heap.memory.size", "Node's heap memory size (-Xmx and -Xms) in megabytes. Default: 256m", "256m");
-    
-    @SetFromFlag("nodePort")
-    PortAttributeSensorAndConfigKey NODE_PORT = new PortAttributeSensorAndConfigKey("hazelcast.node.port", "Hazelcast communication port", PortRanges.fromString("5701+"));
-
-    /**
-     * Specifies the group name in the configuration file. Each Hazelcast cluster has a separate group.
-     */ 
-    @SetFromFlag("groupName")
-    ConfigKey<String> GROUP_NAME = ConfigKeys.newStringConfigKey("hazelcast.group.name", 
-            "Group name", "brooklyn");
-  
-    @SetFromFlag("groupPassword")
-    ConfigKey<String> GROUP_PASSWORD = ConfigKeys.newStringConfigKey("hazelcast.group.password", 
-            "Group password", "brooklyn");
-    
-    String getNodeName();
-    
-    Integer getNodePort();
-    
-    String getGroupName();
-    
-    String getGroupPassword();
-    
-    String getHostname();
-    
-    String getHostAddress();
-
-    String getPrivateIpAddress();
-
-    String getListenAddress();
-    
-    String getHeapMemorySize();
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeDriver.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeDriver.java b/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeDriver.java
deleted file mode 100644
index 8cf1e0c..0000000
--- a/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeDriver.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.brooklyn.entity.nosql.hazelcast;
-
-import org.apache.brooklyn.entity.software.base.SoftwareProcessDriver;
-
-public interface HazelcastNodeDriver extends SoftwareProcessDriver {
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java b/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java
deleted file mode 100644
index 6e17737..0000000
--- a/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.brooklyn.entity.nosql.hazelcast;
-
-import java.net.URI;
-import java.util.concurrent.TimeUnit;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.brooklyn.core.entity.Attributes;
-import org.apache.brooklyn.core.location.access.BrooklynAccessUtils;
-import org.apache.brooklyn.entity.software.base.SoftwareProcessImpl;
-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.util.text.Strings;
-
-import com.google.common.base.Functions;
-import com.google.common.net.HostAndPort;
-
-public class HazelcastNodeImpl extends SoftwareProcessImpl implements HazelcastNode {
-    
-    private static final Logger LOG = LoggerFactory.getLogger(HazelcastNodeImpl.class);
-    
-    HttpFeed httpFeed;
-
-    @Override
-    public Class<HazelcastNodeDriver> getDriverInterface() {
-        return HazelcastNodeDriver.class;
-    }
-    
-    @Override
-    protected void connectSensors() {
-        super.connectSensors();
-
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("Connecting sensors for node: {} ", getAttribute(Attributes.HOSTNAME));
-        }
-        
-        HostAndPort hp = BrooklynAccessUtils.getBrooklynAccessibleAddress(this, getNodePort());
-
-        String nodeUri = String.format("http://%s:%d/hazelcast/rest/cluster", hp.getHostText(), hp.getPort());
-        sensors().set(Attributes.MAIN_URI, URI.create(nodeUri));
-
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("Node {} is using {} as a main URI", this, nodeUri);
-        }
-        
-        httpFeed = HttpFeed.builder()
-                .entity(this)
-                .period(3000, TimeUnit.MILLISECONDS)
-                .baseUri(nodeUri)
-                .poll(new HttpPollConfig<Boolean>(SERVICE_UP)
-                        .onSuccess(HttpValueFunctions.responseCodeEquals(200))
-                        .onFailureOrException(Functions.constant(false)))
-                .build();
-    }
-    
-    @Override
-    protected void disconnectSensors() {
-        if (httpFeed != null) {
-            httpFeed.stop();
-        }
-
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("Disconnecting sensors for node: {} ", getAttribute(Attributes.HOSTNAME));
-        }
-        
-        super.disconnectSensors();
-        disconnectServiceUpIsRunning();
-    }
-
-
-    @Override
-    public String getGroupName() {
-        return getConfig(HazelcastNode.GROUP_NAME);
-    }
-
-    @Override
-    public String getGroupPassword() {
-        return getConfig(HazelcastNode.GROUP_PASSWORD);
-    }
-
-    @Override
-    public String getNodeName() {
-        return getAttribute(HazelcastNode.NODE_NAME);
-    }
-
-    @Override
-    public Integer getNodePort() {
-        return getAttribute(HazelcastNode.NODE_PORT);
-    }
-
-    @Override
-    public String getHostname() { 
-        return getAttribute(HOSTNAME); 
-    }
-    
-    @Override
-    public String getHostAddress() { 
-        return getAttribute(ADDRESS); 
-    }
-    
-    @Override
-    public String getPrivateIpAddress() {
-        return getAttribute(SUBNET_ADDRESS);
-    }
-    
-    @Override
-    public String getListenAddress() {
-        String listenAddress = getPrivateIpAddress();
-        
-        if (Strings.isBlank(listenAddress)) {
-            listenAddress = getAttribute(ADDRESS);
-        }
-        
-        if (LOG.isInfoEnabled()) {
-            LOG.info("Node {} is listening on {}", this, listenAddress);
-        }
-
-         
-        return listenAddress;
-    }
-
-
-    @Override
-    public String getHeapMemorySize() {
-        return getConfig(HazelcastNode.NODE_HEAP_MEMORY_SIZE);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java b/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java
deleted file mode 100644
index 2d67453..0000000
--- a/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.brooklyn.entity.nosql.hazelcast;
-
-import static java.lang.String.format;
-
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntityLocal;
-import org.apache.brooklyn.core.entity.Entities;
-
-import org.apache.brooklyn.entity.java.JavaSoftwareProcessSshDriver;
-import org.apache.brooklyn.location.ssh.SshMachineLocation;
-import org.apache.brooklyn.util.collections.MutableMap;
-import org.apache.brooklyn.util.os.Os;
-import org.apache.brooklyn.util.ssh.BashCommands;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-
-public class HazelcastNodeSshDriver extends JavaSoftwareProcessSshDriver implements HazelcastNodeDriver {
-    
-    private static final Logger LOG = LoggerFactory.getLogger(HazelcastNodeSshDriver.class);
-
-    public HazelcastNodeSshDriver(EntityLocal entity, SshMachineLocation machine) {
-        super(entity, machine);
-    }
-
-    @Override
-    public void preInstall() {
-        resolver = Entities.newDownloader(this);
-    }
-
-    @Override
-    public void install() {
-        List<String> urls = resolver.getTargets();
-        String saveAs = resolver.getFilename();
-        
-        List<String> commands = ImmutableList.<String>builder()
-            .add(BashCommands.installJavaLatestOrWarn())
-            .addAll(BashCommands.commandsToDownloadUrlsAs(urls, saveAs))
-            .build();
-        
-        newScript(INSTALLING).body.append(commands).execute();
-    }
-
-    @Override
-    public void customize() {
-        if (LOG.isInfoEnabled()) {
-            LOG.info("Customizing {}", entity.getAttribute(HazelcastNode.NODE_NAME));
-        }
-        
-        ImmutableList.Builder<String> commands = new ImmutableList.Builder<String>()
-                .add("mkdir -p lib conf log")
-                .add(String.format("cp %s/%s %s/lib/", getInstallDir(), resolver.getFilename(), getRunDir()));
-
-        newScript(CUSTOMIZING)
-                .body.append(commands.build())
-                .failOnNonZeroResultCode()
-                .execute();
-        
-        copyTemplate(entity.getConfig(HazelcastNode.CONFIG_TEMPLATE_URL), Os.mergePathsUnix(getRunDir(), "conf", getConfigFileName()));
-        
-    }
-
-    @Override
-    public void launch() {
-        
-        entity.sensors().set(HazelcastNode.PID_FILE, Os.mergePathsUnix(getRunDir(), PID_FILENAME));
-        
-        String maxHeapMemorySize = getHeapMemorySize();
-        
-        if (LOG.isInfoEnabled()) {
-            LOG.info("Launching {} with heap memory of {}", entity, maxHeapMemorySize);
-        }
-        
-        // Setting initial heap size (Xms) size to match max heap size (Xms) at first
-        String initialHeapMemorySize = maxHeapMemorySize;
-        
-        StringBuilder commandBuilder = new StringBuilder()
-            .append(format("nohup java -cp ./lib/%s", resolver.getFilename()))
-            .append(format(" -Xmx%s -Xms%s", maxHeapMemorySize, initialHeapMemorySize))
-            .append(format(" -Dhazelcast.config=./conf/%s", getConfigFileName()))
-            .append(format(" com.hazelcast.core.server.StartServer >> %s 2>&1 </dev/null &", getLogFileLocation()));
-        
-        newScript(MutableMap.of(USE_PID_FILE, true), LAUNCHING)
-            .updateTaskAndFailOnNonZeroResultCode()
-            .body.append(commandBuilder.toString())
-            .execute();
-    }
-       
-    public String getConfigFileName() {
-        return entity.getConfig(HazelcastNode.CONFIG_FILE_NAME);
-    }
-    
-    public String getHeapMemorySize() {
-        return entity.getConfig(HazelcastNode.NODE_HEAP_MEMORY_SIZE);
-    }
-    
-    @Override
-    public boolean isRunning() {       
-        return newScript(MutableMap.of(USE_PID_FILE, true), CHECK_RUNNING).execute() == 0;
-    }
-    
-    @Override
-    public void stop() {
-        newScript(MutableMap.of(USE_PID_FILE, true), STOPPING).execute();
-    }
-    
-    @Override
-    public void kill() {
-        newScript(MutableMap.of(USE_PID_FILE, true), KILLING).execute();
-    }
-
-    public List<String> getHazelcastNodesList() throws ExecutionException, InterruptedException {
-        HazelcastCluster cluster = (HazelcastCluster) entity.getParent();
-        List<String> result = Lists.newArrayList();
-
-        for (Entity member : cluster.getMembers()) {
-            String address = Entities.attributeSupplierWhenReady(member, HazelcastNode.SUBNET_ADDRESS).get();
-            Integer port = Entities.attributeSupplierWhenReady(member, HazelcastNode.NODE_PORT).get();
-            
-            String addressAndPort = String.format("%s:%d", address, port);
-            
-            if (LOG.isInfoEnabled()) {
-                LOG.info("Adding {} to the members' list of {}", addressAndPort, entity.getAttribute(HazelcastNode.NODE_NAME));
-            }
-            result.add(addressAndPort);
-        }
-        
-        return result;
-    }
-
-    @Override
-    protected String getLogFileLocation() {
-        return Os.mergePathsUnix(getRunDir(),"/log/out.log");
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/sandbox/nosql/src/main/resources/org/apache/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/resources/org/apache/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml b/sandbox/nosql/src/main/resources/org/apache/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml
deleted file mode 100644
index 459be4e..0000000
--- a/sandbox/nosql/src/main/resources/org/apache/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-[#ftl]
-<?xml version="1.0" encoding="UTF-8"?>
-
-<hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.4.xsd"
-           xmlns="http://www.hazelcast.com/schema/config"
-           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-    <group>
-        <name>${entity.groupName}</name>
-        <password>${entity.groupPassword}</password>
-    </group>
-    <management-center enabled="false">http://localhost:8080/mancenter</management-center>
-    <network>
-        <port auto-increment="true" port-count="100">${entity.nodePort?c}</port>
-        <outbound-ports>
-            <!--
-            Allowed port range when connecting to other nodes.
-            0 or * means use system provided port.
-            -->
-            <ports>0</ports>
-        </outbound-ports>
-        
-        <interfaces enabled="true">
-            <interface>${entity.listenAddress}</interface> 
-        </interfaces> 
-        
-        <join>
-            <multicast enabled="false" />
-
-            <tcp-ip enabled="true">
-            [#list driver.hazelcastNodesList as member]
-                <member>${member}</member>
-            [/#list]
-            </tcp-ip>
-            
-            <aws enabled="false" />
-
-        </join>
-
-        <ssl enabled="false"/>
-        <socket-interceptor enabled="false"/>
-        <symmetric-encryption enabled="false"/>
-
-    </network>
-    <partition-group enabled="false"/>
-
-    <map name="default">
-        <in-memory-format>BINARY</in-memory-format>
-        <backup-count>1</backup-count>
-        <async-backup-count>0</async-backup-count>
-        <time-to-live-seconds>0</time-to-live-seconds>
-        <max-idle-seconds>0</max-idle-seconds>
-        <eviction-policy>NONE</eviction-policy>
-        <max-size policy="PER_NODE">0</max-size>
-        <eviction-percentage>25</eviction-percentage>
-        <min-eviction-check-millis>100</min-eviction-check-millis>
-        <merge-policy>com.hazelcast.map.merge.PutIfAbsentMapMergePolicy</merge-policy>
-    </map>
-
-    <serialization>
-        <portable-version>0</portable-version>
-    </serialization>
-
-    <services enable-defaults="true"/>
-
-</hazelcast>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/sandbox/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java b/sandbox/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java
deleted file mode 100644
index f1d44fc..0000000
--- a/sandbox/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.brooklyn.entity.nosql.hazelcast;
-
-import org.apache.brooklyn.entity.nosql.hazelcast.HazelcastCluster;
-import org.apache.brooklyn.entity.nosql.hazelcast.HazelcastNode;
-import org.apache.brooklyn.test.EntityTestUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.Test;
-
-import org.apache.brooklyn.entity.AbstractEc2LiveTest;
-
-import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.core.entity.Attributes;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-
-public class HazelcastClusterEc2LiveTest extends AbstractEc2LiveTest {
-    @SuppressWarnings("unused")
-    private static final Logger LOG = LoggerFactory.getLogger(HazelcastClusterEc2LiveTest.class);
-
-    @Override
-    protected void doTest(Location loc) throws Exception {
-        HazelcastCluster cluster = app.createAndManageChild(EntitySpec.create(HazelcastCluster.class)
-                .configure(HazelcastCluster.INITIAL_SIZE, 3)
-                .configure(HazelcastCluster.MEMBER_SPEC, EntitySpec.create(HazelcastNode.class)));
-        app.start(ImmutableList.of(loc));
-
-        EntityTestUtils.assertAttributeEqualsEventually(cluster, HazelcastNode.SERVICE_UP, true);
-
-        HazelcastNode first = (HazelcastNode) Iterables.get(cluster.getMembers(), 0);
-        HazelcastNode second = (HazelcastNode) Iterables.get(cluster.getMembers(), 1);
-
-        assertNodesUpAndInCluster(first, second);
-        
-        EntityTestUtils.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_UP, true);
-    }
-    
-    private void assertNodesUpAndInCluster(final HazelcastNode... nodes) {
-        for (final HazelcastNode node : nodes) {
-            EntityTestUtils.assertAttributeEqualsEventually(node, HazelcastNode.SERVICE_UP, true);
-        }
-    }
-
-    @Test(enabled = false)
-    public void testDummy() {
-    } // Convince TestNG IDE integration that this really does have test methods
-
-    
-    @Test(groups = {"Live", "Live-sanity"})
-    @Override
-    public void test_CentOS_6_3() throws Exception {
-        super.test_CentOS_6_3();
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/sandbox/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java b/sandbox/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java
deleted file mode 100644
index 0e9fe0b..0000000
--- a/sandbox/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.brooklyn.entity.nosql.hazelcast;
-
-import org.apache.brooklyn.entity.nosql.hazelcast.HazelcastCluster;
-import org.apache.brooklyn.entity.nosql.hazelcast.HazelcastNode;
-import org.apache.brooklyn.test.EntityTestUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.Test;
-
-import org.apache.brooklyn.entity.AbstractSoftlayerLiveTest;
-
-import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.core.entity.Attributes;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-
-public class HazelcastClusterSoftlayerLiveTest extends AbstractSoftlayerLiveTest {
-    @SuppressWarnings("unused")
-    private static final Logger LOG = LoggerFactory.getLogger(HazelcastClusterSoftlayerLiveTest.class);
-
-    @Override
-    protected void doTest(Location loc) throws Exception {
-        HazelcastCluster cluster = app.createAndManageChild(EntitySpec.create(HazelcastCluster.class)
-                .configure(HazelcastCluster.INITIAL_SIZE, 3)
-                .configure(HazelcastCluster.MEMBER_SPEC, EntitySpec.create(HazelcastNode.class)));
-        app.start(ImmutableList.of(loc));
-
-        EntityTestUtils.assertAttributeEqualsEventually(cluster, HazelcastNode.SERVICE_UP, true);
-
-        HazelcastNode first = (HazelcastNode) Iterables.get(cluster.getMembers(), 0);
-        HazelcastNode second = (HazelcastNode) Iterables.get(cluster.getMembers(), 1);
-
-        assertNodesUpAndInCluster(first, second);
-        
-        EntityTestUtils.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_UP, true);
-    }
-    
-    private void assertNodesUpAndInCluster(final HazelcastNode... nodes) {
-        for (final HazelcastNode node : nodes) {
-            EntityTestUtils.assertAttributeEqualsEventually(node, HazelcastNode.SERVICE_UP, true);
-        }
-    }
-
-    @Test(enabled = false)
-    public void testDummy() {
-    } // Convince TestNG IDE integration that this really does have test methods
-
-    
-    @Test(groups = {"Live", "Live-sanity"})
-    @Override
-    public void test_Ubuntu_12_0_4() throws Exception {
-        super.test_Ubuntu_12_0_4();
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/software/nosql/pom.xml
----------------------------------------------------------------------
diff --git a/software/nosql/pom.xml b/software/nosql/pom.xml
index 4fd2d18..e3e9acf 100644
--- a/software/nosql/pom.xml
+++ b/software/nosql/pom.xml
@@ -251,6 +251,7 @@
                 <exclude>src/main/resources/org/apache/brooklyn/entity/nosql/cassandra/cassandra-rackdc.properties</exclude>
                 <exclude>src/main/resources/org/apache/brooklyn/entity/nosql/couchdb/couch.ini</exclude>
                 <exclude>src/main/resources/org/apache/brooklyn/entity/nosql/couchdb/couch.uri</exclude>
+                <exclude>src/main/resources/org/apache/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml</exclude>
                 <exclude>src/main/resources/org/apache/brooklyn/entity/nosql/mongodb/default.conf</exclude>
                 <exclude>src/main/resources/org/apache/brooklyn/entity/nosql/mongodb/default-mongod.conf</exclude>
                 <exclude>src/test/resources/test-mongodb.conf</exclude>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java
new file mode 100644
index 0000000..c43e882
--- /dev/null
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java
@@ -0,0 +1,60 @@
+/*
+ * 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.nosql.hazelcast;
+
+import java.util.List;
+
+import com.google.common.reflect.TypeToken;
+
+import org.apache.brooklyn.api.catalog.Catalog;
+import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.util.core.flags.SetFromFlag;
+
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.sensor.BasicAttributeSensorAndConfigKey;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.entity.group.DynamicCluster;
+
+/**
+ * A cluster of {@link HazelcastNode}s based on {@link DynamicCluster}.
+ */
+@Catalog(name="Hazelcast Cluster", description="Hazelcast is a clustering and highly scalable data distribution platform for Java.")
+
+@ImplementedBy(HazelcastClusterImpl.class)
+public interface HazelcastCluster extends DynamicCluster {
+
+    @SetFromFlag("clusterName")
+    BasicAttributeSensorAndConfigKey<String> CLUSTER_NAME = new BasicAttributeSensorAndConfigKey<String>(String.class, 
+            "hazelcast.cluster.name", "Name of the Hazelcast cluster", "HazelcastCluster");
+    
+    @SetFromFlag("clusterPassword")
+    ConfigKey<String> CLUSTER_PASSWORD =
+            ConfigKeys.newStringConfigKey("hazelcast.cluster.password", "Hazelcast cluster password.");
+    
+    @SuppressWarnings("serial")
+    AttributeSensor<List<String>> PUBLIC_CLUSTER_NODES = Sensors.newSensor(new TypeToken<List<String>>() {},
+        "hazelcast.cluster.public.nodes", "List of public addresses of all nodes in the cluster");
+    
+    String getClusterName();
+    
+    String getClusterPassword();
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java
new file mode 100644
index 0000000..83cf15a
--- /dev/null
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java
@@ -0,0 +1,125 @@
+/*
+ * 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.nosql.hazelcast;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+import org.apache.brooklyn.api.entity.Entity;
+
+import org.apache.brooklyn.entity.group.AbstractMembershipTrackingPolicy;
+import org.apache.brooklyn.entity.group.DynamicClusterImpl;
+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.core.entity.Attributes;
+import org.apache.brooklyn.core.entity.EntityInternal;
+import org.apache.brooklyn.util.text.Strings;
+
+public class HazelcastClusterImpl extends DynamicClusterImpl implements HazelcastCluster {
+    private static final Logger LOG = LoggerFactory.getLogger(HazelcastClusterImpl.class);
+    
+    private static final AtomicInteger nextMemberId = new AtomicInteger(0);
+    
+    @Override
+    protected EntitySpec<?> getMemberSpec() {
+        EntitySpec<?> spec = EntitySpec.create(getConfig(MEMBER_SPEC, EntitySpec.create(HazelcastNode.class)));
+        
+        spec.configure(HazelcastNode.GROUP_NAME, getConfig(HazelcastClusterImpl.CLUSTER_NAME));
+        
+        if (LOG.isInfoEnabled()) {
+            LOG.info("Cluster name : {} : used as a group name", getConfig(HazelcastNode.GROUP_NAME));
+        }
+        
+        spec.configure(HazelcastNode.GROUP_PASSWORD, getClusterPassword());
+        
+        return spec;
+    }
+  
+    @Override
+    public void init() {
+        super.init();
+
+        String clusterPassword = getClusterPassword();
+        
+        if (Strings.isBlank(clusterPassword)) {
+            if (LOG.isInfoEnabled()) {
+                LOG.info(this + " cluster password not provided for " + CLUSTER_PASSWORD.getName() + " : generating random password");
+            }
+            config().set(CLUSTER_PASSWORD, Strings.makeRandomId(12));
+        }
+        
+        policies().add(PolicySpec.create(MemberTrackingPolicy.class)
+                .displayName("Hazelcast members tracker")
+                .configure("group", this));
+    }
+    
+    public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
+        @Override
+        protected void onEntityChange(Entity member) {
+        }
+
+        @Override
+        protected void onEntityAdded(Entity member) {
+            if (member.getAttribute(HazelcastNode.NODE_NAME) == null) {
+                ((EntityInternal) member).sensors().set(HazelcastNode.NODE_NAME, "hazelcast-" + nextMemberId.incrementAndGet());
+                if (LOG.isInfoEnabled()) {
+                    LOG.info("Node {} added to the cluster", member);
+                }
+            }
+        }
+
+        @Override
+        protected void onEntityRemoved(Entity member) {
+        }
+    };
+    
+    @Override
+    public String getClusterName() {
+        return getConfig(CLUSTER_NAME);
+    }
+
+    @Override
+    public String getClusterPassword() {
+        return getConfig(CLUSTER_PASSWORD);
+    }
+
+    @Override
+    protected void initEnrichers() {
+        super.initEnrichers();
+        
+    }
+    
+    @Override
+    public void start(Collection<? extends Location> locations) {
+        super.start(locations);
+        
+        
+        List<String> clusterNodes = Lists.newArrayList();
+        for (Entity member : getMembers()) {
+            clusterNodes.add(member.getAttribute(Attributes.ADDRESS));
+        }
+        sensors().set(PUBLIC_CLUSTER_NODES, clusterNodes);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNode.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNode.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNode.java
new file mode 100644
index 0000000..e53d0da
--- /dev/null
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNode.java
@@ -0,0 +1,97 @@
+/*
+ * 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.nosql.hazelcast;
+
+import org.apache.brooklyn.api.catalog.Catalog;
+import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.util.core.flags.SetFromFlag;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.location.PortRanges;
+import org.apache.brooklyn.core.sensor.BasicAttributeSensorAndConfigKey;
+import org.apache.brooklyn.core.sensor.PortAttributeSensorAndConfigKey;
+import org.apache.brooklyn.core.sensor.BasicAttributeSensorAndConfigKey.StringAttributeSensorAndConfigKey;
+import org.apache.brooklyn.entity.software.base.SoftwareProcess;
+import org.apache.brooklyn.entity.java.UsesJava;
+import org.apache.brooklyn.entity.java.UsesJmx;
+import org.apache.brooklyn.util.javalang.JavaClassNames;
+
+/**
+ * An {@link brooklyn.entity.Entity} that represents an Hazelcast node
+ */
+@Catalog(name="Hazelcast Node", description="Hazelcast is a clustering and highly scalable data distribution platform for Java.")
+
+@ImplementedBy(HazelcastNodeImpl.class)
+public interface HazelcastNode extends SoftwareProcess, UsesJava, UsesJmx {
+    @SetFromFlag("version")
+    ConfigKey<String> SUGGESTED_VERSION = ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION, "3.4.2");
+    
+    @SetFromFlag("downloadUrl")
+    BasicAttributeSensorAndConfigKey<String> DOWNLOAD_URL = new BasicAttributeSensorAndConfigKey<String>(
+            SoftwareProcess.DOWNLOAD_URL, "https://repo1.maven.org/maven2/com/hazelcast/hazelcast/${version}/hazelcast-${version}.jar");
+    
+    @SetFromFlag("configTemplateUrl")
+    ConfigKey<String> CONFIG_TEMPLATE_URL = ConfigKeys.newStringConfigKey(
+            "hazelcast.node.config.templateUrl", "Template file (in freemarker format) for the Hazelcat config file", 
+            JavaClassNames.resolveClasspathUrl(HazelcastNode.class, "hazelcast-brooklyn.xml"));
+    
+    @SetFromFlag("configFileName")
+    ConfigKey<String> CONFIG_FILE_NAME = ConfigKeys.newStringConfigKey(
+            "hazelcast.node.config.fileName", "Name of the Hazelcast config file", "hazelcast.xml");    
+    
+    @SetFromFlag("nodeName")
+    StringAttributeSensorAndConfigKey NODE_NAME = new StringAttributeSensorAndConfigKey("hazelcast.node.name", 
+            "Node name (or randomly selected if not set", null);
+
+    @SetFromFlag("nodeHeapMemorySize")
+    ConfigKey<String> NODE_HEAP_MEMORY_SIZE = ConfigKeys.newStringConfigKey(
+            "hazelcast.node.heap.memory.size", "Node's heap memory size (-Xmx and -Xms) in megabytes. Default: 256m", "256m");
+    
+    @SetFromFlag("nodePort")
+    PortAttributeSensorAndConfigKey NODE_PORT = new PortAttributeSensorAndConfigKey("hazelcast.node.port", "Hazelcast communication port", PortRanges.fromString("5701+"));
+
+    /**
+     * Specifies the group name in the configuration file. Each Hazelcast cluster has a separate group.
+     */ 
+    @SetFromFlag("groupName")
+    ConfigKey<String> GROUP_NAME = ConfigKeys.newStringConfigKey("hazelcast.group.name", 
+            "Group name", "brooklyn");
+  
+    @SetFromFlag("groupPassword")
+    ConfigKey<String> GROUP_PASSWORD = ConfigKeys.newStringConfigKey("hazelcast.group.password", 
+            "Group password", "brooklyn");
+    
+    String getNodeName();
+    
+    Integer getNodePort();
+    
+    String getGroupName();
+    
+    String getGroupPassword();
+    
+    String getHostname();
+    
+    String getHostAddress();
+
+    String getPrivateIpAddress();
+
+    String getListenAddress();
+    
+    String getHeapMemorySize();
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeDriver.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeDriver.java
new file mode 100644
index 0000000..8cf1e0c
--- /dev/null
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeDriver.java
@@ -0,0 +1,25 @@
+/*
+ * 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.nosql.hazelcast;
+
+import org.apache.brooklyn.entity.software.base.SoftwareProcessDriver;
+
+public interface HazelcastNodeDriver extends SoftwareProcessDriver {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java
new file mode 100644
index 0000000..6e17737
--- /dev/null
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java
@@ -0,0 +1,147 @@
+/*
+ * 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.nosql.hazelcast;
+
+import java.net.URI;
+import java.util.concurrent.TimeUnit;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.core.location.access.BrooklynAccessUtils;
+import org.apache.brooklyn.entity.software.base.SoftwareProcessImpl;
+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.util.text.Strings;
+
+import com.google.common.base.Functions;
+import com.google.common.net.HostAndPort;
+
+public class HazelcastNodeImpl extends SoftwareProcessImpl implements HazelcastNode {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(HazelcastNodeImpl.class);
+    
+    HttpFeed httpFeed;
+
+    @Override
+    public Class<HazelcastNodeDriver> getDriverInterface() {
+        return HazelcastNodeDriver.class;
+    }
+    
+    @Override
+    protected void connectSensors() {
+        super.connectSensors();
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Connecting sensors for node: {} ", getAttribute(Attributes.HOSTNAME));
+        }
+        
+        HostAndPort hp = BrooklynAccessUtils.getBrooklynAccessibleAddress(this, getNodePort());
+
+        String nodeUri = String.format("http://%s:%d/hazelcast/rest/cluster", hp.getHostText(), hp.getPort());
+        sensors().set(Attributes.MAIN_URI, URI.create(nodeUri));
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Node {} is using {} as a main URI", this, nodeUri);
+        }
+        
+        httpFeed = HttpFeed.builder()
+                .entity(this)
+                .period(3000, TimeUnit.MILLISECONDS)
+                .baseUri(nodeUri)
+                .poll(new HttpPollConfig<Boolean>(SERVICE_UP)
+                        .onSuccess(HttpValueFunctions.responseCodeEquals(200))
+                        .onFailureOrException(Functions.constant(false)))
+                .build();
+    }
+    
+    @Override
+    protected void disconnectSensors() {
+        if (httpFeed != null) {
+            httpFeed.stop();
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Disconnecting sensors for node: {} ", getAttribute(Attributes.HOSTNAME));
+        }
+        
+        super.disconnectSensors();
+        disconnectServiceUpIsRunning();
+    }
+
+
+    @Override
+    public String getGroupName() {
+        return getConfig(HazelcastNode.GROUP_NAME);
+    }
+
+    @Override
+    public String getGroupPassword() {
+        return getConfig(HazelcastNode.GROUP_PASSWORD);
+    }
+
+    @Override
+    public String getNodeName() {
+        return getAttribute(HazelcastNode.NODE_NAME);
+    }
+
+    @Override
+    public Integer getNodePort() {
+        return getAttribute(HazelcastNode.NODE_PORT);
+    }
+
+    @Override
+    public String getHostname() { 
+        return getAttribute(HOSTNAME); 
+    }
+    
+    @Override
+    public String getHostAddress() { 
+        return getAttribute(ADDRESS); 
+    }
+    
+    @Override
+    public String getPrivateIpAddress() {
+        return getAttribute(SUBNET_ADDRESS);
+    }
+    
+    @Override
+    public String getListenAddress() {
+        String listenAddress = getPrivateIpAddress();
+        
+        if (Strings.isBlank(listenAddress)) {
+            listenAddress = getAttribute(ADDRESS);
+        }
+        
+        if (LOG.isInfoEnabled()) {
+            LOG.info("Node {} is listening on {}", this, listenAddress);
+        }
+
+         
+        return listenAddress;
+    }
+
+
+    @Override
+    public String getHeapMemorySize() {
+        return getConfig(HazelcastNode.NODE_HEAP_MEMORY_SIZE);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java
new file mode 100644
index 0000000..2d67453
--- /dev/null
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java
@@ -0,0 +1,160 @@
+/*
+ * 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.nosql.hazelcast;
+
+import static java.lang.String.format;
+
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntityLocal;
+import org.apache.brooklyn.core.entity.Entities;
+
+import org.apache.brooklyn.entity.java.JavaSoftwareProcessSshDriver;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.os.Os;
+import org.apache.brooklyn.util.ssh.BashCommands;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+public class HazelcastNodeSshDriver extends JavaSoftwareProcessSshDriver implements HazelcastNodeDriver {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(HazelcastNodeSshDriver.class);
+
+    public HazelcastNodeSshDriver(EntityLocal entity, SshMachineLocation machine) {
+        super(entity, machine);
+    }
+
+    @Override
+    public void preInstall() {
+        resolver = Entities.newDownloader(this);
+    }
+
+    @Override
+    public void install() {
+        List<String> urls = resolver.getTargets();
+        String saveAs = resolver.getFilename();
+        
+        List<String> commands = ImmutableList.<String>builder()
+            .add(BashCommands.installJavaLatestOrWarn())
+            .addAll(BashCommands.commandsToDownloadUrlsAs(urls, saveAs))
+            .build();
+        
+        newScript(INSTALLING).body.append(commands).execute();
+    }
+
+    @Override
+    public void customize() {
+        if (LOG.isInfoEnabled()) {
+            LOG.info("Customizing {}", entity.getAttribute(HazelcastNode.NODE_NAME));
+        }
+        
+        ImmutableList.Builder<String> commands = new ImmutableList.Builder<String>()
+                .add("mkdir -p lib conf log")
+                .add(String.format("cp %s/%s %s/lib/", getInstallDir(), resolver.getFilename(), getRunDir()));
+
+        newScript(CUSTOMIZING)
+                .body.append(commands.build())
+                .failOnNonZeroResultCode()
+                .execute();
+        
+        copyTemplate(entity.getConfig(HazelcastNode.CONFIG_TEMPLATE_URL), Os.mergePathsUnix(getRunDir(), "conf", getConfigFileName()));
+        
+    }
+
+    @Override
+    public void launch() {
+        
+        entity.sensors().set(HazelcastNode.PID_FILE, Os.mergePathsUnix(getRunDir(), PID_FILENAME));
+        
+        String maxHeapMemorySize = getHeapMemorySize();
+        
+        if (LOG.isInfoEnabled()) {
+            LOG.info("Launching {} with heap memory of {}", entity, maxHeapMemorySize);
+        }
+        
+        // Setting initial heap size (Xms) size to match max heap size (Xms) at first
+        String initialHeapMemorySize = maxHeapMemorySize;
+        
+        StringBuilder commandBuilder = new StringBuilder()
+            .append(format("nohup java -cp ./lib/%s", resolver.getFilename()))
+            .append(format(" -Xmx%s -Xms%s", maxHeapMemorySize, initialHeapMemorySize))
+            .append(format(" -Dhazelcast.config=./conf/%s", getConfigFileName()))
+            .append(format(" com.hazelcast.core.server.StartServer >> %s 2>&1 </dev/null &", getLogFileLocation()));
+        
+        newScript(MutableMap.of(USE_PID_FILE, true), LAUNCHING)
+            .updateTaskAndFailOnNonZeroResultCode()
+            .body.append(commandBuilder.toString())
+            .execute();
+    }
+       
+    public String getConfigFileName() {
+        return entity.getConfig(HazelcastNode.CONFIG_FILE_NAME);
+    }
+    
+    public String getHeapMemorySize() {
+        return entity.getConfig(HazelcastNode.NODE_HEAP_MEMORY_SIZE);
+    }
+    
+    @Override
+    public boolean isRunning() {       
+        return newScript(MutableMap.of(USE_PID_FILE, true), CHECK_RUNNING).execute() == 0;
+    }
+    
+    @Override
+    public void stop() {
+        newScript(MutableMap.of(USE_PID_FILE, true), STOPPING).execute();
+    }
+    
+    @Override
+    public void kill() {
+        newScript(MutableMap.of(USE_PID_FILE, true), KILLING).execute();
+    }
+
+    public List<String> getHazelcastNodesList() throws ExecutionException, InterruptedException {
+        HazelcastCluster cluster = (HazelcastCluster) entity.getParent();
+        List<String> result = Lists.newArrayList();
+
+        for (Entity member : cluster.getMembers()) {
+            String address = Entities.attributeSupplierWhenReady(member, HazelcastNode.SUBNET_ADDRESS).get();
+            Integer port = Entities.attributeSupplierWhenReady(member, HazelcastNode.NODE_PORT).get();
+            
+            String addressAndPort = String.format("%s:%d", address, port);
+            
+            if (LOG.isInfoEnabled()) {
+                LOG.info("Adding {} to the members' list of {}", addressAndPort, entity.getAttribute(HazelcastNode.NODE_NAME));
+            }
+            result.add(addressAndPort);
+        }
+        
+        return result;
+    }
+
+    @Override
+    protected String getLogFileLocation() {
+        return Os.mergePathsUnix(getRunDir(),"/log/out.log");
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/software/nosql/src/main/resources/org/apache/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/resources/org/apache/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml b/software/nosql/src/main/resources/org/apache/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml
new file mode 100644
index 0000000..459be4e
--- /dev/null
+++ b/software/nosql/src/main/resources/org/apache/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml
@@ -0,0 +1,65 @@
+[#ftl]
+<?xml version="1.0" encoding="UTF-8"?>
+
+<hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.4.xsd"
+           xmlns="http://www.hazelcast.com/schema/config"
+           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <group>
+        <name>${entity.groupName}</name>
+        <password>${entity.groupPassword}</password>
+    </group>
+    <management-center enabled="false">http://localhost:8080/mancenter</management-center>
+    <network>
+        <port auto-increment="true" port-count="100">${entity.nodePort?c}</port>
+        <outbound-ports>
+            <!--
+            Allowed port range when connecting to other nodes.
+            0 or * means use system provided port.
+            -->
+            <ports>0</ports>
+        </outbound-ports>
+        
+        <interfaces enabled="true">
+            <interface>${entity.listenAddress}</interface> 
+        </interfaces> 
+        
+        <join>
+            <multicast enabled="false" />
+
+            <tcp-ip enabled="true">
+            [#list driver.hazelcastNodesList as member]
+                <member>${member}</member>
+            [/#list]
+            </tcp-ip>
+            
+            <aws enabled="false" />
+
+        </join>
+
+        <ssl enabled="false"/>
+        <socket-interceptor enabled="false"/>
+        <symmetric-encryption enabled="false"/>
+
+    </network>
+    <partition-group enabled="false"/>
+
+    <map name="default">
+        <in-memory-format>BINARY</in-memory-format>
+        <backup-count>1</backup-count>
+        <async-backup-count>0</async-backup-count>
+        <time-to-live-seconds>0</time-to-live-seconds>
+        <max-idle-seconds>0</max-idle-seconds>
+        <eviction-policy>NONE</eviction-policy>
+        <max-size policy="PER_NODE">0</max-size>
+        <eviction-percentage>25</eviction-percentage>
+        <min-eviction-check-millis>100</min-eviction-check-millis>
+        <merge-policy>com.hazelcast.map.merge.PutIfAbsentMapMergePolicy</merge-policy>
+    </map>
+
+    <serialization>
+        <portable-version>0</portable-version>
+    </serialization>
+
+    <services enable-defaults="true"/>
+
+</hazelcast>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java
new file mode 100644
index 0000000..f1d44fc
--- /dev/null
+++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.nosql.hazelcast;
+
+import org.apache.brooklyn.entity.nosql.hazelcast.HazelcastCluster;
+import org.apache.brooklyn.entity.nosql.hazelcast.HazelcastNode;
+import org.apache.brooklyn.test.EntityTestUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Test;
+
+import org.apache.brooklyn.entity.AbstractEc2LiveTest;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.entity.Attributes;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+public class HazelcastClusterEc2LiveTest extends AbstractEc2LiveTest {
+    @SuppressWarnings("unused")
+    private static final Logger LOG = LoggerFactory.getLogger(HazelcastClusterEc2LiveTest.class);
+
+    @Override
+    protected void doTest(Location loc) throws Exception {
+        HazelcastCluster cluster = app.createAndManageChild(EntitySpec.create(HazelcastCluster.class)
+                .configure(HazelcastCluster.INITIAL_SIZE, 3)
+                .configure(HazelcastCluster.MEMBER_SPEC, EntitySpec.create(HazelcastNode.class)));
+        app.start(ImmutableList.of(loc));
+
+        EntityTestUtils.assertAttributeEqualsEventually(cluster, HazelcastNode.SERVICE_UP, true);
+
+        HazelcastNode first = (HazelcastNode) Iterables.get(cluster.getMembers(), 0);
+        HazelcastNode second = (HazelcastNode) Iterables.get(cluster.getMembers(), 1);
+
+        assertNodesUpAndInCluster(first, second);
+        
+        EntityTestUtils.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_UP, true);
+    }
+    
+    private void assertNodesUpAndInCluster(final HazelcastNode... nodes) {
+        for (final HazelcastNode node : nodes) {
+            EntityTestUtils.assertAttributeEqualsEventually(node, HazelcastNode.SERVICE_UP, true);
+        }
+    }
+
+    @Test(enabled = false)
+    public void testDummy() {
+    } // Convince TestNG IDE integration that this really does have test methods
+
+    
+    @Test(groups = {"Live", "Live-sanity"})
+    @Override
+    public void test_CentOS_6_3() throws Exception {
+        super.test_CentOS_6_3();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3635a465/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java
new file mode 100644
index 0000000..0e9fe0b
--- /dev/null
+++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.nosql.hazelcast;
+
+import org.apache.brooklyn.entity.nosql.hazelcast.HazelcastCluster;
+import org.apache.brooklyn.entity.nosql.hazelcast.HazelcastNode;
+import org.apache.brooklyn.test.EntityTestUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Test;
+
+import org.apache.brooklyn.entity.AbstractSoftlayerLiveTest;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.entity.Attributes;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+public class HazelcastClusterSoftlayerLiveTest extends AbstractSoftlayerLiveTest {
+    @SuppressWarnings("unused")
+    private static final Logger LOG = LoggerFactory.getLogger(HazelcastClusterSoftlayerLiveTest.class);
+
+    @Override
+    protected void doTest(Location loc) throws Exception {
+        HazelcastCluster cluster = app.createAndManageChild(EntitySpec.create(HazelcastCluster.class)
+                .configure(HazelcastCluster.INITIAL_SIZE, 3)
+                .configure(HazelcastCluster.MEMBER_SPEC, EntitySpec.create(HazelcastNode.class)));
+        app.start(ImmutableList.of(loc));
+
+        EntityTestUtils.assertAttributeEqualsEventually(cluster, HazelcastNode.SERVICE_UP, true);
+
+        HazelcastNode first = (HazelcastNode) Iterables.get(cluster.getMembers(), 0);
+        HazelcastNode second = (HazelcastNode) Iterables.get(cluster.getMembers(), 1);
+
+        assertNodesUpAndInCluster(first, second);
+        
+        EntityTestUtils.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_UP, true);
+    }
+    
+    private void assertNodesUpAndInCluster(final HazelcastNode... nodes) {
+        for (final HazelcastNode node : nodes) {
+            EntityTestUtils.assertAttributeEqualsEventually(node, HazelcastNode.SERVICE_UP, true);
+        }
+    }
+
+    @Test(enabled = false)
+    public void testDummy() {
+    } // Convince TestNG IDE integration that this really does have test methods
+
+    
+    @Test(groups = {"Live", "Live-sanity"})
+    @Override
+    public void test_Ubuntu_12_0_4() throws Exception {
+        super.test_Ubuntu_12_0_4();
+    }
+}


[7/7] incubator-brooklyn git commit: Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-brooklyn

Posted by he...@apache.org.
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-brooklyn


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/085e1cc5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/085e1cc5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/085e1cc5

Branch: refs/heads/master
Commit: 085e1cc5b87c78a3361e8a4cd1f4df19a766fe78
Parents: 7f3c4d7 85ff6af
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Dec 17 11:59:35 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Dec 17 11:59:35 2015 +0000

----------------------------------------------------------------------
 docs/guide/dev/env/ide/eclipse.include.md                          | 2 +-
 .../yaml/example_yaml/simple-appserver-with-location-byon.yaml     | 2 +-
 usage/cli/src/main/resources/brooklyn/default.catalog.bom          | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------



[4/7] incubator-brooklyn git commit: Formatting corrections, changed names assigned to ELK entities, misc other minor updateds to advanced-example doc.

Posted by he...@apache.org.
Formatting corrections, changed names assigned to ELK entities, misc other minor updateds to advanced-example doc.


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/6b7e0ad3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/6b7e0ad3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/6b7e0ad3

Branch: refs/heads/master
Commit: 6b7e0ad3d09816a0bfccba97788bb1306b55bdd4
Parents: ed928a5
Author: John McCabe <jo...@johnmccabe.net>
Authored: Mon Dec 14 17:11:14 2015 +0000
Committer: John McCabe <jo...@johnmccabe.net>
Committed: Mon Dec 14 17:11:14 2015 +0000

----------------------------------------------------------------------
 docs/guide/yaml/advanced-example.md             | 47 +++++++++++---------
 .../yaml/example_yaml/brooklyn-elk-catalog.bom  | 10 ++---
 2 files changed, 30 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6b7e0ad3/docs/guide/yaml/advanced-example.md
----------------------------------------------------------------------
diff --git a/docs/guide/yaml/advanced-example.md b/docs/guide/yaml/advanced-example.md
index b55fdf5..326feb7 100644
--- a/docs/guide/yaml/advanced-example.md
+++ b/docs/guide/yaml/advanced-example.md
@@ -5,20 +5,23 @@ layout: website-normal
 
 By this point you should be familiar with the fundamental concepts behind both Apache Brooklyn and YAML blueprints. This section of the documentation is intended to show a complete, advanced example of a YAML blueprint.
 
-The intention is that this example is used to learn the more in-depth concepts, but also to serve as a reference point when writing your own blueprints. This page will first explain what the example is and how to run it, then it will spotlight interesting features.
+The intention is that this example is used to learn the more in-depth concepts, and also to serve as a reference when writing your own blueprints. This page will first explain what the example application is and how to run it, then it will spotlight interesting features.
 
 
-### The Example
+### ELK Stack Example
 
-The example itself is a deployment of an ELK stack. ELK stands for Elasticsearch, Logstash and Kibana- and this blueprint deploys, installs, runs and manages all three. Briefly, the component parts are:
+This example demonstrates the deployment of an ELK Stack (Elasticsearch, Logstash and Kibana), using the provided blueprint to deploy, install, run and manage all three. Briefly, the component parts are:
 
 * Elasticsearch: A clustered search engine
-* Logstash: Collects, parses and stores logs. For our application it will store logs in Elasticsearch
-* Kibana: A front end to Elasticsearch
+* Logstash: Collects, parses and stores logs. For our example it will store logs in Elasticsearch
+* Kibana: A web front end to Elasticsearch
+
+We also deploy a simple webserver whose logs will be collected.
+
+* Tomcat 8: Web server whose logs will be stored in Elasticsearch by Logstash.
 
 For more about the ELK stack, please see the documentation [here](https://www.elastic.co/webinars/introduction-elk-stack).
 
-In our example, we will be creating the ELK stack, and a Tomcat8 server which sends its logs using Logstash to Elasticsearch.
 
 #### The Blueprints
 -----------
@@ -31,19 +34,19 @@ There are four blueprints that make up this application. Each of them are used t
 * [ELK](example_yaml/brooklyn-elk-catalog.bom)
 
 #### Running the example
-First, add all four blueprints to the Brooklyn Catalog. This can be done by clicking the 'Catalog' tab, clinking the '+' symbol and pasting the YAML. Once this is done, click the 'Application' tab, then the '+' button to bring up the add application wizard. A new Catalog item will be available called 'ELK Stack'. Using the add application wizard, you should be able to deploy an ELK stack to a location of your choosing.
+First, add all four blueprints to the Brooklyn Catalog. This can be done by clicking the 'Catalog' tab, clicking the '+' symbol and pasting the YAML. Once this is done, click the 'Application' tab, then the '+' button to bring up the add application wizard. A new Catalog application will be available called 'ELK Stack'. Using the add application wizard, you should be able to deploy an ELK stack to a location of your choosing.
 
 #### Exploring the example
-After the example has been deployed, you can ensure it is working as expected by checking the following:
+After the application has been deployed, you can ensure it is working as expected by checking the following:
 
-* There is a Kibana sensor called "main.uri", the value of which points to the Kibana front end. You can explore this front end, and observe the logs stored in Elasticsearch. Many Brooklyn applications have a "main.uri" set to point you in the right direction.
-* You can also use the Elasticsearch REST API to explore further. The ES entity has an "urls.http.list" sensor. Choosing an url from there you will be able to access the REST API. The following URL will give you the state of the cluster "{es-url}/\_cluster/health?pretty=true". As you can see the number_of_nodes is currently 2, indicating that the Elasticsearch nodes are communicating with each other.
+* There is a Kibana sensor called `main.uri`, the value of which points to the Kibana front end. You can explore this front end, and observe the logs stored in Elasticsearch. Many Brooklyn applications have a `main.uri` set to point you in the right direction.
+* You can also use the Elasticsearch REST API to explore further. The Elasticsearch Cluster entity has a `urls.http.list` sensor. Using a host:port from that list you will be able to access the REST API. The following URL will give you the state of the cluster `http://<host:port>/_cluster/health?pretty=true`. As you can see the `number_of_nodes` is currently 2, indicating that the Elasticsearch nodes are communicating with each other.
 
 ### Interesting Feature Spotlight
-We will mainly focus on the Elasticsearch blueprint, and will be clear when another blueprint is being discussed. This blueprint is a cluster of Elasticsearch nodes. Clustering is a useful technique that is explained in more depth [here](../clusters.html).
+We will mainly focus on the Elasticsearch blueprint, and will be clear when another blueprint is being discussed. This blueprint describes a cluster of Elasticsearch nodes. Clustering is a useful technique that is explained in more depth [here](../clusters.html).
 
 #### Provisioning Properties
-Our Elasticsearch blueprint has a few requirements of the location in which it is run. Firstly, it must be run on an Ubuntu machine to simplify installation. Secondly, there are two ports that need to be opened to ensure that the entities can be accessed from the outside world. These are configured on the provisioning.properties as follows:
+Our Elasticsearch blueprint has a few requirements of the location in which it is run. Firstly, it must be run on an Ubuntu machine as the example has been written specifically for this OS. Secondly, two ports must opened to ensure that the entities can be accessed from the outside world. Both of these requirements are configured via provisioning.properties as follows:
 
 ~~~yaml
 provisioning.properties:
@@ -54,7 +57,7 @@ provisioning.properties:
 ~~~
 
 #### VanillaSoftwareProcess
-When composing a YAML blueprint, the VanillaSoftwareProcess is a very useful entity to be aware of. A VanillaSoftwareProcess will instruct Brooklyn to provision an instance, and run a series of shell commands to setup, run, monitor and teardown your program. The commands are specified as configuration on the VanillaSoftwareProcess and there are several available. We will spotlight a few now. To simplify this blueprint, we have specified ubuntu only installs so that our commands can be tailored to this system (E.G. use apt-get rather than YUM).
+When composing a YAML blueprint, the VanillaSoftwareProcess is a very useful entity to be aware of. A VanillaSoftwareProcess will instruct Brooklyn to provision an instance, and run a series of shell commands to setup, run, monitor and teardown your program. The commands are specified as configuration on the VanillaSoftwareProcess and there are several available. We will spotlight a few now. To simplify this blueprint, we have specified ubuntu only installs so that our commands can be tailored to this system (e.g. use apt-get rather than yum).
 
 ##### Customize Command
 The Customize Command is run after the application has been installed but before it is run. It is the perfect place to create and amend config files. Please refer to the following section of the Elasticsearch blueprint:
@@ -74,10 +77,10 @@ customize.command: |
   $brooklyn:config("elasticsearch.tcp.port")
   )
 ~~~
-The purpose of this section is to create a YAML file with all of the required configuration. We use the YAML literal style "|" indicator to write a multi line command. We then use $brooklyn:formatString notation to build the string from configuration. We start our series of commands by using the "rm" command to remove the previous config file. We then use "echo" and "tee" to create the new config file and insert the config. Part of the configuration is a list of all hosts that is set on the parent entity- this is done by using a combination of the "component" and  "attributeWhenReady" DSL commands. More on how this is generated later.
+The purpose of this section is to create a YAML file with all of the required configuration. We use the YAML literal style `|` indicator to write a multi line command. We then use `$brooklyn:formatString` notation to build the string from configuration. We start our series of commands by using the `rm` command to remove the previous config file. We then use `echo` and `tee` to create the new config file and insert the config. Part of the configuration is a list of all hosts that is set on the parent entity- this is done by using a combination of the `component` and  `attributeWhenReady` DSL commands. More on how this is generated later.
 
 ##### Check running
-After an app is installed and run, this command will be run regularly and used to populate the "service.isUp" sensor. If this command is not specified, or returns an exit code of anything other than zero, then Brooklyn will assume that your entity is broken and will display the fire status symbol. Please refer to the following section of the Elasticsearch blueprint:
+After an app is installed and run, this command is scheduled to run regularly and used to populate the `service.isUp` sensor. If this command is not specified, or returns an exit code of anything other than zero, then Brooklyn will assume that your entity has failed and will display the fire status symbol. Please refer to the following section of the Elasticsearch blueprint:
 
 ~~~yaml
 checkRunning.command: |
@@ -85,7 +88,7 @@ checkRunning.command: |
   $brooklyn:attributeWhenReady("host.address"),
   $brooklyn:config("elasticsearch.http.port"))
 ~~~
-There are many different ways to implement this command. For this example, we are querying the REST API to get the status. This command creates a variable called counter, and populates it by performing a "WGET" call to the status URL or the Elasticsearch node, grepping for a 200 status OK code. We then check the counter is populated (I.E. that the end point does return status 200) and exit with an error code of one if not.
+There are many different ways to implement this command. For this example, we are querying the REST API to get the status. This command creates a variable called counter, and populates it by performing a `wget` call to the status URL or the Elasticsearch node, grepping for a 200 status OK code. We then check the counter is populated (i.e. that the end point does return status 200) and exit with an error code of one if not.
 
 #### Enrichers
 
@@ -101,7 +104,7 @@ brooklyn.enrichers:
       enricher.targetValue: $brooklyn:formatString("%s:%s", $brooklyn:attributeWhenReady("host.address"), $brooklyn:config("elasticsearch.tcp.port"))  
 ~~~
 
-In this example, we take the host.address and append the TCP port, outputting the result as url.tcp. After this has been done, we now need to collect all the URLs into a list in the Cluster entity, as follows:
+In this example, we take the host.address and append the TCP port, outputting the result as `url.tcp`. After this has been done, we now need to collect all the URLs into a list in the Cluster entity, as follows:
 
 ~~~yaml
 brooklyn.enrichers:
@@ -112,7 +115,7 @@ brooklyn.enrichers:
       enricher.aggregating.fromMembers: true
 
 ~~~
-In the preceding example, we aggregate all of the TCP urls generated in the early example. These are then stored in a sensor called urls.tcp.list. This list is then joined together into one long string:
+In the preceding example, we aggregated all of the TCP URLs generated in the early example. These are then stored in a sensor called `urls.tcp.list`. This list is then joined together into one long string:
 
 ~~~yaml
 - type: org.apache.brooklyn.enricher.stock.Joiner
@@ -132,7 +135,7 @@ Finally, the string has brackets added to the start and end:
     enricher.targetValue: $brooklyn:formatString("[%s]", $brooklyn:attributeWhenReady("urls.tcp.string"))
 ~~~
 
-The resulting sensor will be called urls.tcp.withBrackets and will be used by all Elasticsearch nodes during setup.
+The resulting sensor will be called `urls.tcp.withBrackets` and will be used by all Elasticsearch nodes during setup.
 
 ##### Kibana URL
 Kibana also needs to be configured such that it can access the Elasticsearch cluster. However, Kibana can only be configured to point at one Elasticsearch instance. To enable this, we use another enricher in the cluster to select the first URL from the list, as follows:
@@ -148,7 +151,7 @@ Kibana also needs to be configured such that it can access the Elasticsearch clu
        type: "org.apache.brooklyn.util.collections.CollectionFunctionals$FirstElementFunction"
 ~~~
 
-Similar to the above Aggregator, this Aggregator collects all the URLs from the members of the cluster. However, this Aggregator specifies a transformation. In this instance a transformation is a Java class that implements a Guava Function\<? super Collection\<?\>, ?\>\>, I.E. a function that takes in a collection and returns something. In this case we specify the FirstElementFunction from the CollectionFunctionals to ensure that we only get the first member of the URL list.
+Similar to the above Aggregator, this Aggregator collects all the URLs from the members of the cluster. However, this Aggregator specifies a transformation. In this instance a transformation is a Java class that implements a Guava Function `<? super Collection<?>, ?>>`, i.e. a function that takes in a collection and returns something. In this case we specify the FirstElementFunction from the CollectionFunctionals to ensure that we only get the first member of the URL list.
 
 #### Latches
 In the ELK blueprint, there is a good example of a latch. Latches are used to force an entity to wait until certain conditions are met before continuing. For example:
@@ -156,7 +159,7 @@ In the ELK blueprint, there is a good example of a latch. Latches are used to fo
 ~~~yaml
 - type: kibana-standalone
   ...
-  name: kibana
+  name: Kibana Server
   customize.latch: $brooklyn:component("es").attributeWhenReady("service.isUp")
 ~~~
 
@@ -174,4 +177,4 @@ The ELK blueprint also contains a good example of a child entity.
   - type: logstash-child
 ~~~
 
-In this example, a logstash-child is started as a child of the parent Tomcat server. The tomcat server needs to be configured with a "children.startable.mode" to inform Brooklyn when to bring up the child. In this case we have selected background so that the child is disassociated from the parent entity, and late to specify that the parent entity should start before we start the child.
+In this example, a logstash-child is started as a child of the parent Tomcat server. The Tomcat server needs to be configured with a `children.startable.mode` to inform Brooklyn when to bring up the child. In this case we have selected background so that the child is disassociated from the parent entity, and late to specify that the parent entity should start before we start the child.

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6b7e0ad3/docs/guide/yaml/example_yaml/brooklyn-elk-catalog.bom
----------------------------------------------------------------------
diff --git a/docs/guide/yaml/example_yaml/brooklyn-elk-catalog.bom b/docs/guide/yaml/example_yaml/brooklyn-elk-catalog.bom
index ffca3df..6fc11f4 100644
--- a/docs/guide/yaml/example_yaml/brooklyn-elk-catalog.bom
+++ b/docs/guide/yaml/example_yaml/brooklyn-elk-catalog.bom
@@ -9,27 +9,27 @@ brooklyn.catalog:
     name: ELK Stack
     id: ELK-Stack
     description: |
-      Simple ELK stack deployment: it installs ES, Kibana and lostash as a child of Apache Tomcat 8
+      Simple ELK stack deployment: provisions Elasticsearch, Kibana and Logtash as a child of Apache Tomcat 8
     services:
       - type: elasticsearch
         id: es
-        name:  es
+        name:  Elasticsearch Cluster
         brooklyn.config:
           install.version: 1.4.4
       - type: kibana-standalone
         id: kibana
-        name: kibana
+        name: Kibana Server
         customize.latch: $brooklyn:component("es").attributeWhenReady("service.isUp")
         brooklyn.config:
           kibana.elasticsearch.ip: $brooklyn:component("es").attributeWhenReady("host.address.first")
           kibana.elasticsearch.port: $brooklyn:component("es").config("elasticsearch.http.port")
       - type: org.apache.brooklyn.entity.webapp.tomcat.Tomcat8Server
-        id: jboss
+        id: tomcat
         customize.latch: $brooklyn:component("es").attributeWhenReady("service.isUp")
         brooklyn.config:
           children.startable.mode: background_late
         brooklyn.children:
         - type: logstash-child
-          name: logstash-child
+          name: Logstash Child
           brooklyn.config:
             logstash.elasticsearch.host: $brooklyn:component("es").attributeWhenReady("urls.http.withBrackets")


[6/7] incubator-brooklyn git commit: This closes #1107

Posted by he...@apache.org.
This closes #1107


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/7f3c4d78
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/7f3c4d78
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/7f3c4d78

Branch: refs/heads/master
Commit: 7f3c4d784ef8f6d3b007e495f4502c9890237b2b
Parents: af31ba8 6b7e0ad
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Dec 17 11:59:10 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Dec 17 11:59:10 2015 +0000

----------------------------------------------------------------------
 docs/guide/yaml/advanced-example.md             | 47 +++++++++++---------
 .../yaml/example_yaml/brooklyn-elk-catalog.bom  | 10 ++---
 2 files changed, 30 insertions(+), 27 deletions(-)
----------------------------------------------------------------------



[2/7] incubator-brooklyn git commit: Bumping Hazelcast's version to 3.5.4

Posted by he...@apache.org.
Bumping Hazelcast's version to 3.5.4

Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/2cdd880f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/2cdd880f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/2cdd880f

Branch: refs/heads/master
Commit: 2cdd880f747f927cedf4290ec6999079d6be3504
Parents: 3635a46
Author: Yavor Yanchev <ya...@yanchev.com>
Authored: Mon Dec 14 03:05:35 2015 +0200
Committer: Yavor Yanchev <ya...@yanchev.com>
Committed: Mon Dec 14 03:20:22 2015 +0200

----------------------------------------------------------------------
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2cdd880f/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index c053053..47925f2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -126,7 +126,7 @@
         <mockwebserver.version>20121111</mockwebserver.version>
         <freemarker.version>2.3.22</freemarker.version>
         <commons-io.version>2.4</commons-io.version>
-        <hazelcast.version>3.0</hazelcast.version>
+        <hazelcast.version>3.5.4</hazelcast.version>
         <jsonPath.version>2.0.0</jsonPath.version>
         <commons-compress.version>1.4</commons-compress.version>
         <qpid.version>0.20</qpid.version>


[5/7] incubator-brooklyn git commit: This closes #1108

Posted by he...@apache.org.
This closes #1108


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/af31ba83
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/af31ba83
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/af31ba83

Branch: refs/heads/master
Commit: af31ba83ca4021a4d4ddc55ae26d8e3962d8782b
Parents: 548eaba 894890a
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Dec 17 11:56:49 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Dec 17 11:56:49 2015 +0000

----------------------------------------------------------------------
 pom.xml                                         |   2 +-
 sandbox/nosql/pom.xml                           |  19 ---
 .../nosql/hazelcast/HazelcastCluster.java       |  60 -------
 .../nosql/hazelcast/HazelcastClusterImpl.java   | 125 --------------
 .../entity/nosql/hazelcast/HazelcastNode.java   |  97 -----------
 .../nosql/hazelcast/HazelcastNodeDriver.java    |  25 ---
 .../nosql/hazelcast/HazelcastNodeImpl.java      | 147 -----------------
 .../nosql/hazelcast/HazelcastNodeSshDriver.java | 160 ------------------
 .../nosql/hazelcast/hazelcast-brooklyn.xml      |  65 --------
 .../hazelcast/HazelcastClusterEc2LiveTest.java  |  74 ---------
 .../HazelcastClusterSoftlayerLiveTest.java      |  74 ---------
 software/nosql/pom.xml                          |   9 +
 .../nosql/hazelcast/HazelcastCluster.java       |  59 +++++++
 .../nosql/hazelcast/HazelcastClusterImpl.java   | 125 ++++++++++++++
 .../entity/nosql/hazelcast/HazelcastNode.java   | 101 ++++++++++++
 .../nosql/hazelcast/HazelcastNodeDriver.java    |  25 +++
 .../nosql/hazelcast/HazelcastNodeImpl.java      | 146 +++++++++++++++++
 .../nosql/hazelcast/HazelcastNodeSshDriver.java | 164 +++++++++++++++++++
 .../nosql/hazelcast/hazelcast-brooklyn.xml      |  64 ++++++++
 .../hazelcast/HazelcastClusterEc2LiveTest.java  |  47 ++++++
 .../HazelcastClusterNodeIntegrationTest.java    |  49 ++++++
 .../HazelcastClusterSoftlayerLiveTest.java      |  47 ++++++
 .../hazelcast/HazelcastNodeIntegrationTest.java | 107 ++++++++++++
 .../nosql/hazelcast/HazelcastTestHelper.java    |  76 +++++++++
 24 files changed, 1020 insertions(+), 847 deletions(-)
----------------------------------------------------------------------