You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2015/07/24 08:41:06 UTC
[1/2] incubator-brooklyn git commit: BROOKLYN-143 - support for
Hazelcast
Repository: incubator-brooklyn
Updated Branches:
refs/heads/master 3559b5d6d -> df4eb8a7f
BROOKLYN-143 - support for Hazelcast
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/e37f0585
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/e37f0585
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/e37f0585
Branch: refs/heads/master
Commit: e37f05856c7067081f8e37d3fbdc84408e1bbb9d
Parents: b2d3f33
Author: Yavor Yanchev <ya...@yanchev.com>
Authored: Wed May 13 03:05:54 2015 +0300
Committer: Aled Sage <al...@gmail.com>
Committed: Thu Jul 23 23:37:23 2015 -0700
----------------------------------------------------------------------
sandbox/nosql/pom.xml | 14 ++
.../nosql/hazelcast/HazelcastCluster.java | 59 +++++++
.../nosql/hazelcast/HazelcastClusterImpl.java | 124 +++++++++++++++
.../entity/nosql/hazelcast/HazelcastNode.java | 97 +++++++++++
.../nosql/hazelcast/HazelcastNodeDriver.java | 25 +++
.../nosql/hazelcast/HazelcastNodeImpl.java | 148 +++++++++++++++++
.../nosql/hazelcast/HazelcastNodeSshDriver.java | 159 +++++++++++++++++++
.../nosql/hazelcast/hazelcast-brooklyn.xml | 65 ++++++++
.../hazelcast/HazelcastClusterEc2LiveTest.java | 71 +++++++++
.../HazelcastClusterSoftlayerLiveTest.java | 71 +++++++++
10 files changed, 833 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e37f0585/sandbox/nosql/pom.xml
----------------------------------------------------------------------
diff --git a/sandbox/nosql/pom.xml b/sandbox/nosql/pom.xml
index 2de79ac..da6fe21 100644
--- a/sandbox/nosql/pom.xml
+++ b/sandbox/nosql/pom.xml
@@ -91,6 +91,20 @@
</execution>
</executions>
</plugin>
+ <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/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/e37f0585/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java b/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java
new file mode 100644
index 0000000..48ab1aa
--- /dev/null
+++ b/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.nosql.hazelcast;
+
+import java.util.List;
+
+import com.google.common.reflect.TypeToken;
+
+import brooklyn.catalog.Catalog;
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.group.DynamicCluster;
+import brooklyn.entity.proxying.ImplementedBy;
+import brooklyn.event.AttributeSensor;
+import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
+import brooklyn.event.basic.Sensors;
+import brooklyn.util.flags.SetFromFlag;
+
+/**
+ * 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/e37f0585/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java b/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java
new file mode 100644
index 0000000..e911318
--- /dev/null
+++ b/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.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 brooklyn.entity.Entity;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.group.AbstractMembershipTrackingPolicy;
+import brooklyn.entity.group.DynamicClusterImpl;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.location.Location;
+import brooklyn.policy.PolicySpec;
+import 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");
+ }
+ setConfig(CLUSTER_PASSWORD, Strings.makeRandomId(12));
+ }
+
+ addPolicy(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).setAttribute(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));
+ }
+ setAttribute(PUBLIC_CLUSTER_NODES, clusterNodes);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e37f0585/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastNode.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastNode.java b/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastNode.java
new file mode 100644
index 0000000..076b6f5
--- /dev/null
+++ b/sandbox/nosql/src/main/java/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 brooklyn.entity.nosql.hazelcast;
+
+import brooklyn.catalog.Catalog;
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.java.UsesJava;
+import brooklyn.entity.java.UsesJmx;
+import brooklyn.entity.proxying.ImplementedBy;
+import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
+import brooklyn.event.basic.BasicAttributeSensorAndConfigKey.StringAttributeSensorAndConfigKey;
+import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
+import brooklyn.location.basic.PortRanges;
+import brooklyn.util.flags.SetFromFlag;
+import 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/e37f0585/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastNodeDriver.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastNodeDriver.java b/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastNodeDriver.java
new file mode 100644
index 0000000..4e53add
--- /dev/null
+++ b/sandbox/nosql/src/main/java/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 brooklyn.entity.nosql.hazelcast;
+
+import brooklyn.entity.basic.SoftwareProcessDriver;
+
+public interface HazelcastNodeDriver extends SoftwareProcessDriver {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e37f0585/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java b/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java
new file mode 100644
index 0000000..0369934
--- /dev/null
+++ b/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.nosql.hazelcast;
+
+import java.net.URI;
+import java.util.concurrent.TimeUnit;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.SoftwareProcessImpl;
+import brooklyn.event.feed.http.HttpFeed;
+import brooklyn.event.feed.http.HttpPollConfig;
+import brooklyn.event.feed.http.HttpValueFunctions;
+import brooklyn.location.access.BrooklynAccessUtils;
+import brooklyn.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());
+ setAttribute(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/e37f0585/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java b/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java
new file mode 100644
index 0000000..5527a69
--- /dev/null
+++ b/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.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 brooklyn.entity.Entity;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityLocal;
+import brooklyn.entity.java.JavaSoftwareProcessSshDriver;
+import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.os.Os;
+import 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.setAttribute(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/e37f0585/sandbox/nosql/src/main/resources/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/resources/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml b/sandbox/nosql/src/main/resources/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml
new file mode 100644
index 0000000..459be4e
--- /dev/null
+++ b/sandbox/nosql/src/main/resources/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/e37f0585/sandbox/nosql/src/test/java/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/test/java/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java b/sandbox/nosql/src/test/java/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java
new file mode 100644
index 0000000..bce319c
--- /dev/null
+++ b/sandbox/nosql/src/test/java/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.nosql.hazelcast;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.AbstractEc2LiveTest;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.location.Location;
+import brooklyn.test.EntityTestUtils;
+
+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/e37f0585/sandbox/nosql/src/test/java/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/test/java/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java b/sandbox/nosql/src/test/java/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java
new file mode 100644
index 0000000..4ff4ab9
--- /dev/null
+++ b/sandbox/nosql/src/test/java/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.nosql.hazelcast;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.AbstractSoftlayerLiveTest;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.location.Location;
+import brooklyn.test.EntityTestUtils;
+
+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();
+ }
+}
[2/2] incubator-brooklyn git commit: This closes #767
Posted by al...@apache.org.
This closes #767
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/df4eb8a7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/df4eb8a7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/df4eb8a7
Branch: refs/heads/master
Commit: df4eb8a7fe7e8e0ba319b8051d730047c292d741
Parents: 3559b5d e37f058
Author: Aled Sage <al...@gmail.com>
Authored: Thu Jul 23 23:41:02 2015 -0700
Committer: Aled Sage <al...@gmail.com>
Committed: Thu Jul 23 23:41:02 2015 -0700
----------------------------------------------------------------------
sandbox/nosql/pom.xml | 14 ++
.../nosql/hazelcast/HazelcastCluster.java | 59 +++++++
.../nosql/hazelcast/HazelcastClusterImpl.java | 124 +++++++++++++++
.../entity/nosql/hazelcast/HazelcastNode.java | 97 +++++++++++
.../nosql/hazelcast/HazelcastNodeDriver.java | 25 +++
.../nosql/hazelcast/HazelcastNodeImpl.java | 148 +++++++++++++++++
.../nosql/hazelcast/HazelcastNodeSshDriver.java | 159 +++++++++++++++++++
.../nosql/hazelcast/hazelcast-brooklyn.xml | 65 ++++++++
.../hazelcast/HazelcastClusterEc2LiveTest.java | 71 +++++++++
.../HazelcastClusterSoftlayerLiveTest.java | 71 +++++++++
10 files changed, 833 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df4eb8a7/sandbox/nosql/pom.xml
----------------------------------------------------------------------