You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ha...@apache.org on 2015/08/07 01:59:52 UTC
[1/6] incubator-brooklyn git commit: package rename to
org.apache.brooklyn: sandbox
Repository: incubator-brooklyn
Updated Branches:
refs/heads/master fc42b17ff -> 7154cc9ec
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/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
new file mode 100644
index 0000000..fadfe46
--- /dev/null
+++ b/sandbox/nosql/src/main/java/org/apache/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 org.apache.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/070b5ca7/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
new file mode 100644
index 0000000..1dea440
--- /dev/null
+++ b/sandbox/nosql/src/main/java/org/apache/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 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 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/070b5ca7/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/infinispan/Infinispan5Driver.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/infinispan/Infinispan5Driver.java b/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/infinispan/Infinispan5Driver.java
new file mode 100644
index 0000000..810450e
--- /dev/null
+++ b/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/infinispan/Infinispan5Driver.java
@@ -0,0 +1,23 @@
+/*
+ * 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.infinispan;
+
+public interface Infinispan5Driver {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/infinispan/Infinispan5Server.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/infinispan/Infinispan5Server.java b/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/infinispan/Infinispan5Server.java
new file mode 100644
index 0000000..cb1043b
--- /dev/null
+++ b/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/infinispan/Infinispan5Server.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.nosql.infinispan;
+
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.basic.SoftwareProcessImpl;
+import brooklyn.entity.java.UsesJmx;
+import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
+import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.flags.SetFromFlag;
+
+/**
+ * An {@link brooklyn.entity.Entity} that represents an Infinispan service
+ */
+public class Infinispan5Server extends SoftwareProcessImpl implements UsesJmx {
+ private static final Logger log = LoggerFactory.getLogger(Infinispan5Server.class);
+
+ public static final BasicAttributeSensorAndConfigKey<String> PROTOCOL = new BasicAttributeSensorAndConfigKey<String>(
+ String.class, "infinispan.server.protocol",
+ "Infinispan protocol (e.g. memcached, hotrod, or websocket)", "memcached");
+
+ public static final PortAttributeSensorAndConfigKey PORT = new PortAttributeSensorAndConfigKey(
+ "infinispan.server.port", "TCP port number to listen on");
+
+ @SetFromFlag("version")
+ public static final ConfigKey<String> SUGGESTED_VERSION =
+ ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION, "5.0.0.CR8");
+
+ // Default filename is "infinispan-${version}-all.zip"
+ @SetFromFlag("downloadUrl")
+ public static final BasicAttributeSensorAndConfigKey<String> DOWNLOAD_URL = new BasicAttributeSensorAndConfigKey<String>(
+ SoftwareProcess.DOWNLOAD_URL, "http://sourceforge.net/projects/infinispan/files/infinispan/${version}/infinispan-${version}-all.zip/download");
+
+ public Infinispan5Server() {
+ this(MutableMap.of(), null);
+ }
+ public Infinispan5Server(Map properties) {
+ this(properties, null);
+ }
+ public Infinispan5Server(Entity parent) {
+ this(MutableMap.of(), parent);
+ }
+ public Infinispan5Server(Map properties, Entity parent) {
+ super(properties, parent);
+ }
+
+ @Override
+ public Class getDriverInterface() {
+ return Infinispan5Driver.class;
+ }
+
+ @Override
+ protected void connectSensors() {
+ super.connectSensors();
+ super.connectServiceUpIsRunning();
+ }
+
+ @Override
+ protected void disconnectSensors() {
+ super.disconnectServiceUpIsRunning();
+ super.disconnectSensors();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/infinispan/Infinispan5SshDriver.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/infinispan/Infinispan5SshDriver.java b/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/infinispan/Infinispan5SshDriver.java
new file mode 100644
index 0000000..1c2d33b
--- /dev/null
+++ b/sandbox/nosql/src/main/java/org/apache/brooklyn/entity/nosql/infinispan/Infinispan5SshDriver.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 org.apache.brooklyn.entity.nosql.infinispan;
+
+import static java.lang.String.format;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import brooklyn.entity.java.JavaSoftwareProcessSshDriver;
+import brooklyn.location.Location;
+import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.net.Networking;
+import brooklyn.util.ssh.BashCommands;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Start a {@link TomcatServer} in a {@link Location} accessible over ssh.
+ */
+public class Infinispan5SshDriver extends JavaSoftwareProcessSshDriver implements Infinispan5Driver {
+
+ public Infinispan5SshDriver(Infinispan5Server entity, SshMachineLocation machine) {
+ super(entity, machine);
+ }
+
+ @Override
+ protected String getLogFileLocation() {
+ throw new UnsupportedOperationException("Work in progress");
+ }
+
+ protected String getProtocol() {
+ return entity.getAttribute(Infinispan5Server.PROTOCOL);
+ }
+
+ protected Integer getPort() {
+ return entity.getAttribute(Infinispan5Server.PORT);
+ }
+
+ @Override
+ public void install() {
+ List<String> urls = resolver.getTargets();
+ String saveAs = resolver.getFilename();
+
+ List<String> commands = ImmutableList.<String>builder()
+ .addAll(BashCommands.commandsToDownloadUrlsAs(urls, saveAs))
+ .add(BashCommands.INSTALL_ZIP)
+ .add("unzip " + saveAs)
+ .build();
+
+ newScript(INSTALLING).
+ failOnNonZeroResultCode().
+ body.append(commands).execute();
+ }
+
+ @Override
+ public void customize() {
+ // TODO create and reference a conf.xml? And start with --cache_config <path>
+ Map ports = MutableMap.of("port", getPort(), "jmxPort", getJmxPort());
+ Networking.checkPortsValid(ports);
+
+ newScript(CUSTOMIZING)
+ .body.append()
+ .execute();
+ }
+
+ @Override
+ public void launch() {
+ // FIXME Do we want to redirect stdout/stderr: >> %s/console 2>&1 </dev/null &", getRunDir())
+ newScript(MutableMap.of("usePidFile", true), LAUNCHING).
+ body.append(
+ format("%s/bin/startServer.sh --protocol %s "
+ +(getPort() != null ? " --port %s" : "")+" &",
+ getExpandedInstallDir(), getProtocol(), getPort()))
+ .execute();
+ }
+
+
+ @Override
+ public boolean isRunning() {
+ Map flags = MutableMap.of("usePidFile", true);
+ return newScript(flags, CHECK_RUNNING).execute() == 0;
+ }
+
+ @Override
+ public void stop() {
+ Map flags = MutableMap.of("usePidFile", true);
+ newScript(flags, STOPPING).execute();
+ }
+
+ @Override
+ public void kill() {
+ Map flags = MutableMap.of("usePidFile", true);
+ newScript(flags, KILLING).execute();
+ }
+
+ @Override
+ protected List<String> getCustomJavaConfigOptions() {
+ List<String> options = new LinkedList<String>();
+ options.addAll(super.getCustomJavaConfigOptions());
+ options.add("-Xms200m");
+ options.add("-Xmx800m");
+ options.add("-XX:MaxPermSize=400m");
+ return options;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/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
deleted file mode 100644
index 459be4e..0000000
--- a/sandbox/nosql/src/main/resources/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/070b5ca7/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
new file mode 100644
index 0000000..459be4e
--- /dev/null
+++ b/sandbox/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/070b5ca7/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
deleted file mode 100644
index bce319c..0000000
--- a/sandbox/nosql/src/test/java/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.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/070b5ca7/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
deleted file mode 100644
index 4ff4ab9..0000000
--- a/sandbox/nosql/src/test/java/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.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();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/nosql/src/test/java/brooklyn/entity/nosql/infinispan/Infinispan5ServerIntegrationTest.groovy
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/test/java/brooklyn/entity/nosql/infinispan/Infinispan5ServerIntegrationTest.groovy b/sandbox/nosql/src/test/java/brooklyn/entity/nosql/infinispan/Infinispan5ServerIntegrationTest.groovy
deleted file mode 100644
index 40eb546..0000000
--- a/sandbox/nosql/src/test/java/brooklyn/entity/nosql/infinispan/Infinispan5ServerIntegrationTest.groovy
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.nosql.infinispan
-
-import static brooklyn.test.TestUtils.*
-import static java.util.concurrent.TimeUnit.*
-import static org.testng.Assert.*
-
-import java.util.concurrent.TimeUnit
-
-import org.slf4j.Logger
-import org.slf4j.LoggerFactory
-import org.testng.annotations.AfterMethod
-import org.testng.annotations.BeforeMethod
-import org.testng.annotations.Test
-
-import brooklyn.entity.Application
-import brooklyn.entity.basic.Entities
-import brooklyn.location.basic.LocalhostMachineProvisioningLocation
-import brooklyn.test.entity.TestApplicationImpl
-import brooklyn.util.internal.TimeExtras
-import brooklyn.util.net.Networking
-import brooklyn.util.repeat.Repeater
-
-class Infinispan5ServerIntegrationTest {
- private static final Logger logger = LoggerFactory.getLogger(Infinispan5ServerIntegrationTest.class)
-
- static String DEFAULT_PROTOCOL = "memcached"
- static int DEFAULT_PORT = 11219
-
- static boolean portLeftOpen = false;
-
- static { TimeExtras.init() }
-
- @BeforeMethod(groups = [ "Integration" ])
- public void failIfPortInUse() {
- if (isPortInUse(DEFAULT_PORT, 5000L)) {
- portLeftOpen = true;
- fail "someone is already listening on port $DEFAULT_PORT; tests assume that port $DEFAULT_PORT is free on localhost"
- }
- }
-
- @AfterMethod(groups = [ "Integration" ])
- public void ensureIsShutDown() {
- Socket shutdownSocket = null;
- SocketException gotException = null;
-
- boolean socketClosed = new Repeater("Checking Infinispan has shut down")
- .repeat {
- if (shutdownSocket) shutdownSocket.close();
- try { shutdownSocket = new Socket(Networking.localHost, DEFAULT_PORT); }
- catch (SocketException e) { gotException = e; return; }
- gotException = null
- }
- .every(100 * MILLISECONDS)
- .until { gotException }
- .limitIterationsTo(25)
- .run();
-
- if (socketClosed == false) {
- logger.error "Infinispan did not shut down";
- throw new Exception("Infinispan did not shut down")
- }
- }
-
- public void ensureIsUp() {
- Socket socket = new Socket(Networking.localHost, DEFAULT_PORT);
- socket.close();
- }
-
- @Test(groups = [ "Integration", "WIP" ])
- public void testInfinispanStartsAndStops() {
- Application app = new TestApplicationImpl();
- try {
- final Infinispan5Server infini = new Infinispan5Server(parent:app)
- infini.setConfig(Infinispan5Server.PORT.getConfigKey(), DEFAULT_PORT)
- infini.start([ new LocalhostMachineProvisioningLocation(name:'london') ])
-
- executeUntilSucceeds {
- assertTrue infini.getAttribute(Infinispan5Server.SERVICE_UP)
- }
- } finally {
- Entities.destroy(app);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/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
new file mode 100644
index 0000000..552ad02
--- /dev/null
+++ b/sandbox/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterEc2LiveTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.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/070b5ca7/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
new file mode 100644
index 0000000..03d95af
--- /dev/null
+++ b/sandbox/nosql/src/test/java/org/apache/brooklyn/entity/nosql/hazelcast/HazelcastClusterSoftlayerLiveTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.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();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/nosql/src/test/java/org/apache/brooklyn/entity/nosql/infinispan/Infinispan5ServerIntegrationTest.groovy
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/test/java/org/apache/brooklyn/entity/nosql/infinispan/Infinispan5ServerIntegrationTest.groovy b/sandbox/nosql/src/test/java/org/apache/brooklyn/entity/nosql/infinispan/Infinispan5ServerIntegrationTest.groovy
new file mode 100644
index 0000000..b7d8d1a
--- /dev/null
+++ b/sandbox/nosql/src/test/java/org/apache/brooklyn/entity/nosql/infinispan/Infinispan5ServerIntegrationTest.groovy
@@ -0,0 +1,103 @@
+/*
+ * 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.infinispan
+
+import static brooklyn.test.TestUtils.*
+import static java.util.concurrent.TimeUnit.*
+import static org.testng.Assert.*
+
+import java.util.concurrent.TimeUnit
+
+import org.apache.brooklyn.entity.nosql.infinispan.Infinispan5Server;
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import org.testng.annotations.AfterMethod
+import org.testng.annotations.BeforeMethod
+import org.testng.annotations.Test
+
+import brooklyn.entity.Application
+import brooklyn.entity.basic.Entities
+import brooklyn.location.basic.LocalhostMachineProvisioningLocation
+import brooklyn.test.entity.TestApplicationImpl
+import brooklyn.util.internal.TimeExtras
+import brooklyn.util.net.Networking
+import brooklyn.util.repeat.Repeater
+
+class Infinispan5ServerIntegrationTest {
+ private static final Logger logger = LoggerFactory.getLogger(Infinispan5ServerIntegrationTest.class)
+
+ static String DEFAULT_PROTOCOL = "memcached"
+ static int DEFAULT_PORT = 11219
+
+ static boolean portLeftOpen = false;
+
+ static { TimeExtras.init() }
+
+ @BeforeMethod(groups = [ "Integration" ])
+ public void failIfPortInUse() {
+ if (isPortInUse(DEFAULT_PORT, 5000L)) {
+ portLeftOpen = true;
+ fail "someone is already listening on port $DEFAULT_PORT; tests assume that port $DEFAULT_PORT is free on localhost"
+ }
+ }
+
+ @AfterMethod(groups = [ "Integration" ])
+ public void ensureIsShutDown() {
+ Socket shutdownSocket = null;
+ SocketException gotException = null;
+
+ boolean socketClosed = new Repeater("Checking Infinispan has shut down")
+ .repeat {
+ if (shutdownSocket) shutdownSocket.close();
+ try { shutdownSocket = new Socket(Networking.localHost, DEFAULT_PORT); }
+ catch (SocketException e) { gotException = e; return; }
+ gotException = null
+ }
+ .every(100 * MILLISECONDS)
+ .until { gotException }
+ .limitIterationsTo(25)
+ .run();
+
+ if (socketClosed == false) {
+ logger.error "Infinispan did not shut down";
+ throw new Exception("Infinispan did not shut down")
+ }
+ }
+
+ public void ensureIsUp() {
+ Socket socket = new Socket(Networking.localHost, DEFAULT_PORT);
+ socket.close();
+ }
+
+ @Test(groups = [ "Integration", "WIP" ])
+ public void testInfinispanStartsAndStops() {
+ Application app = new TestApplicationImpl();
+ try {
+ final Infinispan5Server infini = new Infinispan5Server(parent:app)
+ infini.setConfig(Infinispan5Server.PORT.getConfigKey(), DEFAULT_PORT)
+ infini.start([ new LocalhostMachineProvisioningLocation(name:'london') ])
+
+ executeUntilSucceeds {
+ assertTrue infini.getAttribute(Infinispan5Server.SERVICE_UP)
+ }
+ } finally {
+ Entities.destroy(app);
+ }
+ }
+}
[3/6] incubator-brooklyn git commit: package rename to
org.apache.brooklyn: sandbox
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/resources/brooklyn/entity/salt/minion
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/resources/brooklyn/entity/salt/minion b/sandbox/extra/src/main/resources/brooklyn/entity/salt/minion
deleted file mode 100644
index cff42c7..0000000
--- a/sandbox/extra/src/main/resources/brooklyn/entity/salt/minion
+++ /dev/null
@@ -1,52 +0,0 @@
-[#ftl]
-##
-# 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.
-#
-# SaltStack Minion Configuration
-#
-# /etc/salt/minion
-##
-
-# The salt master server
-master: ${entity.master.hostname}
-ipv6: False
-retry_dns: 30
-master_port: ${entity.master.saltPort,c} # 4506
-acceptance_wait_time: 30
-acceptance_wait_time_max: 300
-
-# Minion configuration
-id: ${entity.id}
-user: root
-backup_mode: minion
-
-# Directory settings
-root_dir: /
-pidfile: ${runDir}/salt-minion.pid
-pki_dir: ${runDir}/pki
-cachedir: ${runDir}/cache
-log_file: ${runDir}/minion.log
-key_logfile: ${runDir}/key.log
-
-#verify_env: True
-#cache_jobs: True # Debugging
-
-output: nested
-color: False
-log_level: info
-log_level_logfile: debug # Debugging
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/resources/org/apache/brooklyn/entity/salt/master
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/resources/org/apache/brooklyn/entity/salt/master b/sandbox/extra/src/main/resources/org/apache/brooklyn/entity/salt/master
new file mode 100644
index 0000000..72d7eb9
--- /dev/null
+++ b/sandbox/extra/src/main/resources/org/apache/brooklyn/entity/salt/master
@@ -0,0 +1,65 @@
+[#ftl]
+#
+# 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.
+#
+# /etc/salt/master
+##
+
+#interface: 0.0.0.0
+#ipv6: False
+#publish_port: ${entity.publishPort,c} # 4505
+
+#user: root
+#max_open_files: 100000
+#worker_threads: 5
+ret_port: ${entity.saltPort,c} # 4506
+
+root_dir: /
+pidfile: ${driver.pidFile}
+pki_dir: ${runDir}/pki
+cachedir: ${runDir}/cache
+log_file: ${driver.logFileLocation}
+key_logfile: ${runDir}/key.log
+
+#verify_env: True
+#keep_jobs: 24
+
+#timeout: 5
+#loop_interval: 60
+
+output: nested
+color: False
+log_level: info
+log_level_logfile: debug # Debugging
+
+#job_cache: True
+#minion_data_cache: True
+
+#open_mode: False
+#auto_accept: False
+#autosign_file: autosign.conf
+#permissive_pki_access: False
+
+fileserver_backend:
+ - git
+
+gitfs_remotes:
+ - git://github.com/saltstack/salt-states.git
+ - git://github.com/saltstack-formulas/postgres-formula.git
+ - ${entity.remoteUrl}
+ # TODO iterate through formula URLs
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/resources/org/apache/brooklyn/entity/salt/masterless
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/resources/org/apache/brooklyn/entity/salt/masterless b/sandbox/extra/src/main/resources/org/apache/brooklyn/entity/salt/masterless
new file mode 100644
index 0000000..ba41c6e
--- /dev/null
+++ b/sandbox/extra/src/main/resources/org/apache/brooklyn/entity/salt/masterless
@@ -0,0 +1,53 @@
+[#ftl]
+##
+#
+# 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.
+#
+# SaltStack Masterless Minion Configuration
+#
+# /etc/salt/minion
+##
+
+# Minion configuration
+id: ${entity.id}
+user: root
+backup_mode: minion
+
+# Directory settings
+root_dir: /
+pidfile: ${runDir}/salt-minion.pid
+pki_dir: ${runDir}/pki
+cachedir: ${runDir}/cache
+log_file: ${runDir}/minion.log
+key_logfile: ${runDir}/key.log
+
+file_client: local
+file_roots:
+ base:
+ - ${runDir}/base
+[#list formulas?keys as formulaName]
+ - ${installDir}/${formulaName}
+[/#list]
+
+#verify_env: True
+#cache_jobs: True # Debugging
+
+output: nested
+color: False
+log_level: info
+log_level_logfile: debug # Debugging
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/resources/org/apache/brooklyn/entity/salt/minion
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/resources/org/apache/brooklyn/entity/salt/minion b/sandbox/extra/src/main/resources/org/apache/brooklyn/entity/salt/minion
new file mode 100644
index 0000000..cff42c7
--- /dev/null
+++ b/sandbox/extra/src/main/resources/org/apache/brooklyn/entity/salt/minion
@@ -0,0 +1,52 @@
+[#ftl]
+##
+# 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.
+#
+# SaltStack Minion Configuration
+#
+# /etc/salt/minion
+##
+
+# The salt master server
+master: ${entity.master.hostname}
+ipv6: False
+retry_dns: 30
+master_port: ${entity.master.saltPort,c} # 4506
+acceptance_wait_time: 30
+acceptance_wait_time_max: 300
+
+# Minion configuration
+id: ${entity.id}
+user: root
+backup_mode: minion
+
+# Directory settings
+root_dir: /
+pidfile: ${runDir}/salt-minion.pid
+pki_dir: ${runDir}/pki
+cachedir: ${runDir}/cache
+log_file: ${runDir}/minion.log
+key_logfile: ${runDir}/key.log
+
+#verify_env: True
+#cache_jobs: True # Debugging
+
+output: nested
+color: False
+log_level: info
+log_level_logfile: debug # Debugging
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/test/java/brooklyn/entity/database/postgresql/PostgreSqlSaltLiveTest.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/test/java/brooklyn/entity/database/postgresql/PostgreSqlSaltLiveTest.java b/sandbox/extra/src/test/java/brooklyn/entity/database/postgresql/PostgreSqlSaltLiveTest.java
deleted file mode 100644
index a44efa9..0000000
--- a/sandbox/extra/src/test/java/brooklyn/entity/database/postgresql/PostgreSqlSaltLiveTest.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.database.postgresql;
-
-import java.util.Random;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.database.VogellaExampleAccess;
-import brooklyn.entity.effector.EffectorTasks;
-import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.entity.salt.SaltConfig;
-import brooklyn.entity.salt.SaltLiveTestSupport;
-import brooklyn.entity.software.SshEffectorTasks;
-import brooklyn.location.PortRange;
-import brooklyn.location.basic.PortRanges;
-import brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.task.system.ProcessTaskWrapper;
-import brooklyn.util.time.Duration;
-
-import com.google.common.collect.ImmutableList;
-
-/**
- * Tests Salt installation of {@link PostgreSqlNode} entity.
- */
-public class PostgreSqlSaltLiveTest extends SaltLiveTestSupport {
-
- private static final Logger log = LoggerFactory.getLogger(PostgreSqlSaltLiveTest.class);
-
- private PostgreSqlNode psql;
-
- @Override
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- try {
- if (psql != null) psql.stop();
- } finally {
- super.tearDown();
- }
- }
-
- @Test(groups="Live")
- public void testPostgresStartsAndStops() throws Exception {
- psql = app.createAndManageChild(EntitySpec.create(PostgreSqlNode.class, PostgreSqlNodeSaltImpl.class)
- .configure(SaltConfig.MASTERLESS_MODE, true));
-
- app.start(ImmutableList.of(targetLocation));
-
- Entities.submit(psql, SshEffectorTasks.ssh("ps aux | grep [p]ostgres").requiringExitCodeZero());
- SshMachineLocation targetMachine = EffectorTasks.getSshMachine(psql);
-
- psql.stop();
-
- try {
- // if host is still contactable ensure postgres is not running
- ProcessTaskWrapper<Integer> t = Entities.submit(app, SshEffectorTasks.ssh("ps aux | grep [p]ostgres").machine(targetMachine).allowingNonZeroExitCode());
- t.getTask().blockUntilEnded(Duration.TEN_SECONDS);
- if (!t.isDone()) {
- Assert.fail("Task not finished yet: "+t.getTask());
- }
- Assert.assertNotEquals(t.get(), (Integer)0, "Task ended with code "+t.get()+"; output: "+t.getStdout() );
- } catch (Exception e) {
- // host has been killed, that is fine
- log.info("Machine "+targetMachine+" destroyed on stop (expected - "+e+")");
- }
- }
-
- @Test(groups="Live")
- public void testPostgresScriptAndAccess() throws Exception {
- SaltLiveTestSupport.createLocation(mgmt);
- PortRange randomPort = PortRanges.fromString(""+(5420+new Random().nextInt(10))+"+");
- psql = app.createAndManageChild(EntitySpec.create(PostgreSqlNode.class, PostgreSqlNodeSaltImpl.class)
- .configure(SaltConfig.MASTERLESS_MODE, true)
- .configure(PostgreSqlNode.CREATION_SCRIPT_CONTENTS, PostgreSqlIntegrationTest.CREATION_SCRIPT)
- .configure(PostgreSqlNode.POSTGRESQL_PORT, randomPort));
-
- app.start(ImmutableList.of(targetLocation));
-
- String url = psql.getAttribute(PostgreSqlNode.DATASTORE_URL);
- log.info("Trying to connect to "+psql+" at "+url);
- Assert.assertNotNull(url);
- Assert.assertTrue(url.contains("542"));
-
- new VogellaExampleAccess("org.postgresql.Driver", url).readModifyAndRevertDataBase();
- }
-
-}
-
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/test/java/brooklyn/entity/salt/SaltConfigsTest.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/test/java/brooklyn/entity/salt/SaltConfigsTest.java b/sandbox/extra/src/test/java/brooklyn/entity/salt/SaltConfigsTest.java
deleted file mode 100644
index 6706748..0000000
--- a/sandbox/extra/src/test/java/brooklyn/entity/salt/SaltConfigsTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.salt;
-
-import java.util.Map;
-import java.util.Set;
-
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.basic.ApplicationBuilder;
-import brooklyn.entity.basic.Entities;
-import brooklyn.test.entity.TestApplication;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-
-public class SaltConfigsTest {
-
- private TestApplication app = null;
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() {
- if (app!=null) Entities.destroyAll(app.getManagementContext());
- app = null;
- }
-
- @Test
- public void testAddToRunList() {
- app = ApplicationBuilder.newManagedApp(TestApplication.class);
- SaltConfigs.addToRunList(app, "a", "b");
- Set<? extends String> runs = app.getConfig(SaltConfig.SALT_RUN_LIST);
- Assert.assertEquals(runs, ImmutableSet.of("a", "b"));
- }
-
- @Test
- public void testAddToFormulas() {
- app = ApplicationBuilder.newManagedApp(TestApplication.class);
- SaltConfigs.addToFormulas(app, "k1", "v1");
- SaltConfigs.addToFormulas(app, "k2", "v2");
- Map<String, String> formulas = app.getConfig(SaltConfig.SALT_FORMULAS);
- Assert.assertEquals(formulas, ImmutableMap.of("k1", "v1", "k2", "v2"));
- }
-
- @Test
- public void testAddLaunchAttributes() {
- app = ApplicationBuilder.newManagedApp(TestApplication.class);
- SaltConfigs.addLaunchAttributes(app, ImmutableMap.of("k1", "v1"));
- Map<String, Object> attribs = app.getConfig(SaltConfig.SALT_LAUNCH_ATTRIBUTES);
- Assert.assertEquals(attribs, ImmutableMap.of("k1", "v1"));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/test/java/brooklyn/entity/salt/SaltLiveTestSupport.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/test/java/brooklyn/entity/salt/SaltLiveTestSupport.java b/sandbox/extra/src/test/java/brooklyn/entity/salt/SaltLiveTestSupport.java
deleted file mode 100644
index 6cb7409..0000000
--- a/sandbox/extra/src/test/java/brooklyn/entity/salt/SaltLiveTestSupport.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.salt;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.BeforeMethod;
-
-import brooklyn.entity.BrooklynAppLiveTestSupport;
-import brooklyn.location.Location;
-import brooklyn.location.MachineProvisioningLocation;
-import brooklyn.location.basic.SshMachineLocation;
-import brooklyn.management.ManagementContext;
-
-public class SaltLiveTestSupport extends BrooklynAppLiveTestSupport {
-
- private static final Logger log = LoggerFactory.getLogger(SaltLiveTestSupport.class);
-
- protected MachineProvisioningLocation<? extends SshMachineLocation> targetLocation;
-
- @Override
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- super.setUp();
-
- targetLocation = createLocation();
- }
-
- protected MachineProvisioningLocation<? extends SshMachineLocation> createLocation() {
- return createLocation(mgmt);
- }
-
- /**
- * Convenience for setting up a pre-built or fixed IP machine.
- * <p>
- * Useful if you are unable to set up Salt on localhost,
- * and for ensuring tests against Salt always use the same
- * configured location.
- */
- @SuppressWarnings("unchecked")
- public static MachineProvisioningLocation<? extends SshMachineLocation> createLocation(ManagementContext mgmt) {
- Location bestLocation = mgmt.getLocationRegistry().resolveIfPossible("named:SaltTests");
- if (bestLocation==null) {
- log.info("using AWS for salt tests because named:SaltTests does not exist");
- bestLocation = mgmt.getLocationRegistry().resolveIfPossible("jclouds:aws-ec2:us-east-1");
- }
- if (bestLocation==null) {
- throw new IllegalStateException("Need a location called named:SaltTests or AWS configured for these tests");
- }
- return (MachineProvisioningLocation<? extends SshMachineLocation>)bestLocation;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/test/java/org/apache/brooklyn/entity/database/postgresql/PostgreSqlSaltLiveTest.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/test/java/org/apache/brooklyn/entity/database/postgresql/PostgreSqlSaltLiveTest.java b/sandbox/extra/src/test/java/org/apache/brooklyn/entity/database/postgresql/PostgreSqlSaltLiveTest.java
new file mode 100644
index 0000000..250cc03
--- /dev/null
+++ b/sandbox/extra/src/test/java/org/apache/brooklyn/entity/database/postgresql/PostgreSqlSaltLiveTest.java
@@ -0,0 +1,112 @@
+/*
+ * 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.database.postgresql;
+
+import java.util.Random;
+
+import org.apache.brooklyn.entity.database.postgresql.PostgreSqlNodeSaltImpl;
+import org.apache.brooklyn.entity.salt.SaltConfig;
+import org.apache.brooklyn.entity.salt.SaltLiveTestSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.database.VogellaExampleAccess;
+import brooklyn.entity.database.postgresql.PostgreSqlIntegrationTest;
+import brooklyn.entity.database.postgresql.PostgreSqlNode;
+import brooklyn.entity.effector.EffectorTasks;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.software.SshEffectorTasks;
+import brooklyn.location.PortRange;
+import brooklyn.location.basic.PortRanges;
+import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.util.task.system.ProcessTaskWrapper;
+import brooklyn.util.time.Duration;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Tests Salt installation of {@link PostgreSqlNode} entity.
+ */
+public class PostgreSqlSaltLiveTest extends SaltLiveTestSupport {
+
+ private static final Logger log = LoggerFactory.getLogger(PostgreSqlSaltLiveTest.class);
+
+ private PostgreSqlNode psql;
+
+ @Override
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ try {
+ if (psql != null) psql.stop();
+ } finally {
+ super.tearDown();
+ }
+ }
+
+ @Test(groups="Live")
+ public void testPostgresStartsAndStops() throws Exception {
+ psql = app.createAndManageChild(EntitySpec.create(PostgreSqlNode.class, PostgreSqlNodeSaltImpl.class)
+ .configure(SaltConfig.MASTERLESS_MODE, true));
+
+ app.start(ImmutableList.of(targetLocation));
+
+ Entities.submit(psql, SshEffectorTasks.ssh("ps aux | grep [p]ostgres").requiringExitCodeZero());
+ SshMachineLocation targetMachine = EffectorTasks.getSshMachine(psql);
+
+ psql.stop();
+
+ try {
+ // if host is still contactable ensure postgres is not running
+ ProcessTaskWrapper<Integer> t = Entities.submit(app, SshEffectorTasks.ssh("ps aux | grep [p]ostgres").machine(targetMachine).allowingNonZeroExitCode());
+ t.getTask().blockUntilEnded(Duration.TEN_SECONDS);
+ if (!t.isDone()) {
+ Assert.fail("Task not finished yet: "+t.getTask());
+ }
+ Assert.assertNotEquals(t.get(), (Integer)0, "Task ended with code "+t.get()+"; output: "+t.getStdout() );
+ } catch (Exception e) {
+ // host has been killed, that is fine
+ log.info("Machine "+targetMachine+" destroyed on stop (expected - "+e+")");
+ }
+ }
+
+ @Test(groups="Live")
+ public void testPostgresScriptAndAccess() throws Exception {
+ SaltLiveTestSupport.createLocation(mgmt);
+ PortRange randomPort = PortRanges.fromString(""+(5420+new Random().nextInt(10))+"+");
+ psql = app.createAndManageChild(EntitySpec.create(PostgreSqlNode.class, PostgreSqlNodeSaltImpl.class)
+ .configure(SaltConfig.MASTERLESS_MODE, true)
+ .configure(PostgreSqlNode.CREATION_SCRIPT_CONTENTS, PostgreSqlIntegrationTest.CREATION_SCRIPT)
+ .configure(PostgreSqlNode.POSTGRESQL_PORT, randomPort));
+
+ app.start(ImmutableList.of(targetLocation));
+
+ String url = psql.getAttribute(PostgreSqlNode.DATASTORE_URL);
+ log.info("Trying to connect to "+psql+" at "+url);
+ Assert.assertNotNull(url);
+ Assert.assertTrue(url.contains("542"));
+
+ new VogellaExampleAccess("org.postgresql.Driver", url).readModifyAndRevertDataBase();
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/test/java/org/apache/brooklyn/entity/salt/SaltConfigsTest.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/test/java/org/apache/brooklyn/entity/salt/SaltConfigsTest.java b/sandbox/extra/src/test/java/org/apache/brooklyn/entity/salt/SaltConfigsTest.java
new file mode 100644
index 0000000..cf1a800
--- /dev/null
+++ b/sandbox/extra/src/test/java/org/apache/brooklyn/entity/salt/SaltConfigsTest.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 org.apache.brooklyn.entity.salt;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.entity.salt.SaltConfig;
+import org.apache.brooklyn.entity.salt.SaltConfigs;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.basic.Entities;
+import brooklyn.test.entity.TestApplication;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+public class SaltConfigsTest {
+
+ private TestApplication app = null;
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() {
+ if (app!=null) Entities.destroyAll(app.getManagementContext());
+ app = null;
+ }
+
+ @Test
+ public void testAddToRunList() {
+ app = ApplicationBuilder.newManagedApp(TestApplication.class);
+ SaltConfigs.addToRunList(app, "a", "b");
+ Set<? extends String> runs = app.getConfig(SaltConfig.SALT_RUN_LIST);
+ Assert.assertEquals(runs, ImmutableSet.of("a", "b"));
+ }
+
+ @Test
+ public void testAddToFormulas() {
+ app = ApplicationBuilder.newManagedApp(TestApplication.class);
+ SaltConfigs.addToFormulas(app, "k1", "v1");
+ SaltConfigs.addToFormulas(app, "k2", "v2");
+ Map<String, String> formulas = app.getConfig(SaltConfig.SALT_FORMULAS);
+ Assert.assertEquals(formulas, ImmutableMap.of("k1", "v1", "k2", "v2"));
+ }
+
+ @Test
+ public void testAddLaunchAttributes() {
+ app = ApplicationBuilder.newManagedApp(TestApplication.class);
+ SaltConfigs.addLaunchAttributes(app, ImmutableMap.of("k1", "v1"));
+ Map<String, Object> attribs = app.getConfig(SaltConfig.SALT_LAUNCH_ATTRIBUTES);
+ Assert.assertEquals(attribs, ImmutableMap.of("k1", "v1"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/test/java/org/apache/brooklyn/entity/salt/SaltLiveTestSupport.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/test/java/org/apache/brooklyn/entity/salt/SaltLiveTestSupport.java b/sandbox/extra/src/test/java/org/apache/brooklyn/entity/salt/SaltLiveTestSupport.java
new file mode 100644
index 0000000..8fbc14f
--- /dev/null
+++ b/sandbox/extra/src/test/java/org/apache/brooklyn/entity/salt/SaltLiveTestSupport.java
@@ -0,0 +1,68 @@
+/*
+ * 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.salt;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeMethod;
+
+import brooklyn.entity.BrooklynAppLiveTestSupport;
+import brooklyn.location.Location;
+import brooklyn.location.MachineProvisioningLocation;
+import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.management.ManagementContext;
+
+public class SaltLiveTestSupport extends BrooklynAppLiveTestSupport {
+
+ private static final Logger log = LoggerFactory.getLogger(SaltLiveTestSupport.class);
+
+ protected MachineProvisioningLocation<? extends SshMachineLocation> targetLocation;
+
+ @Override
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ super.setUp();
+
+ targetLocation = createLocation();
+ }
+
+ protected MachineProvisioningLocation<? extends SshMachineLocation> createLocation() {
+ return createLocation(mgmt);
+ }
+
+ /**
+ * Convenience for setting up a pre-built or fixed IP machine.
+ * <p>
+ * Useful if you are unable to set up Salt on localhost,
+ * and for ensuring tests against Salt always use the same
+ * configured location.
+ */
+ @SuppressWarnings("unchecked")
+ public static MachineProvisioningLocation<? extends SshMachineLocation> createLocation(ManagementContext mgmt) {
+ Location bestLocation = mgmt.getLocationRegistry().resolveIfPossible("named:SaltTests");
+ if (bestLocation==null) {
+ log.info("using AWS for salt tests because named:SaltTests does not exist");
+ bestLocation = mgmt.getLocationRegistry().resolveIfPossible("jclouds:aws-ec2:us-east-1");
+ }
+ if (bestLocation==null) {
+ throw new IllegalStateException("Need a location called named:SaltTests or AWS configured for these tests");
+ }
+ return (MachineProvisioningLocation<? extends SshMachineLocation>)bestLocation;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixFeed.java
----------------------------------------------------------------------
diff --git a/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixFeed.java b/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixFeed.java
deleted file mode 100644
index 5fe96cd..0000000
--- a/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixFeed.java
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.monitoring.zabbix;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.net.URI;
-import java.net.URL;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.http.client.HttpClient;
-import org.apache.http.impl.NoConnectionReuseStrategy;
-import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.Entity;
-import brooklyn.entity.basic.Attributes;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.EntityFunctions;
-import brooklyn.entity.basic.EntityLocal;
-import brooklyn.event.feed.AbstractFeed;
-import brooklyn.event.feed.AttributePollHandler;
-import brooklyn.event.feed.PollHandler;
-import brooklyn.event.feed.Poller;
-import brooklyn.event.feed.http.HttpValueFunctions;
-import brooklyn.location.Location;
-import brooklyn.location.MachineLocation;
-import brooklyn.location.access.BrooklynAccessUtils;
-import brooklyn.location.basic.SupportsPortForwarding;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
-import brooklyn.util.net.Cidr;
-
-import com.google.common.base.Function;
-import com.google.common.base.Functions;
-import com.google.common.base.Objects;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicates;
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import com.google.common.net.HostAndPort;
-import com.google.common.reflect.TypeToken;
-import com.google.gson.JsonObject;
-
-public class ZabbixFeed extends AbstractFeed {
-
- public static final Logger log = LoggerFactory.getLogger(ZabbixFeed.class);
-
- public static final String JSON_ITEM_GET =
- "{ \"jsonrpc\":\"2.0\",\"method\":\"item.get\"," +
- "\"params\":{\"output\":\"extend\"," +
- "\"filter\":{\"hostid\":[\"{{hostId}}\"],\"key_\":\"{{itemKey}}\"}}," +
- "\"auth\":\"{{token}}\",\"id\":{{id}}}";
- public static final String JSON_USER_LOGIN =
- "{ \"jsonrpc\":\"2.0\",\"method\":\"user.login\"," +
- "\"params\":{\"user\":\"{{username}}\",\"password\":\"{{password}}\"}," +
- "\"id\":0 }";
- public static final String JSON_HOST_CREATE =
- "{ \"jsonrpc\":\"2.0\",\"method\":\"host.create\"," +
- "\"params\":{\"host\":\"{{host}}\"," +
- "\"interfaces\":[{\"type\":1,\"main\":1,\"useip\":1,\"ip\":\"{{ip}}\",\"dns\":\"\",\"port\":\"{{port}}\"}]," +
- "\"groups\":[{\"groupid\":\"{{groupId}}\"}]," +
- "\"templates\":[{\"templateid\":\"{{templateId}}\"}]}," +
- "\"auth\":\"{{token}}\",\"id\":{{id}}}";
-
- private static final AtomicInteger id = new AtomicInteger(0);
-
- @SuppressWarnings("serial")
- public static final ConfigKey<Set<ZabbixPollConfig<?>>> POLLS = ConfigKeys.newConfigKey(
- new TypeToken<Set<ZabbixPollConfig<?>>>() {},
- "polls");
-
- @SuppressWarnings("serial")
- public static final ConfigKey<Supplier<URI>> BASE_URI_PROVIDER = ConfigKeys.newConfigKey(
- new TypeToken<Supplier<URI>>() {},
- "baseUriProvider");
-
- public static final ConfigKey<Integer> GROUP_ID = ConfigKeys.newIntegerConfigKey("groupId");
-
- public static final ConfigKey<Integer> TEMPLATE_ID = ConfigKeys.newIntegerConfigKey("templateId");
-
- @SuppressWarnings("serial")
- public static final ConfigKey<Function<? super EntityLocal, String>> UNIQUE_HOSTNAME_GENERATOR = ConfigKeys.newConfigKey(
- new TypeToken<Function<? super EntityLocal, String>>() {},
- "uniqueHostnameGenerator");
-
- public static Builder<ZabbixFeed, ?> builder() {
- return new ConcreteBuilder();
- }
-
- private static class ConcreteBuilder extends Builder<ZabbixFeed, ConcreteBuilder> {
- }
-
- public static class Builder<T extends ZabbixFeed, B extends Builder<T,B>> {
- private EntityLocal entity;
- private Supplier<URI> baseUriProvider;
- private long period = 500;
- private TimeUnit periodUnits = TimeUnit.MILLISECONDS;
- private List<ZabbixPollConfig<?>> polls = Lists.newArrayList();
- private URI baseUri;
- private boolean suspended = false;
- private volatile boolean built;
- private ZabbixServer server;
- private String username;
- private String password;
- private Integer sessionTimeout;
- private Integer groupId;
- private Integer templateId;
- private Function<? super EntityLocal, String> uniqueHostnameGenerator = Functions.compose(
- EntityFunctions.id(),
- EntityFunctions.locationMatching(Predicates.instanceOf(MachineLocation.class)));
- private String uniqueTag;
-
- @SuppressWarnings("unchecked")
- protected B self() {
- return (B) this;
- }
-
- public B entity(EntityLocal val) {
- this.entity = val;
- return self();
- }
- public B baseUri(Supplier<URI> val) {
- if (baseUri!=null && val!=null)
- throw new IllegalStateException("Builder cannot take both a URI and a URI Provider");
- this.baseUriProvider = val;
- return self();
- }
- public B baseUri(URI val) {
- if (baseUriProvider!=null && val!=null)
- throw new IllegalStateException("Builder cannot take both a URI and a URI Provider");
- this.baseUri = val;
- return self();
- }
- public B baseUrl(URL val) {
- return baseUri(URI.create(val.toString()));
- }
- public B baseUri(String val) {
- return baseUri(URI.create(val));
- }
- public B period(long millis) {
- return period(millis, TimeUnit.MILLISECONDS);
- }
- public B period(long val, TimeUnit units) {
- this.period = val;
- this.periodUnits = units;
- return self();
- }
- public B poll(ZabbixPollConfig<?> config) {
- polls.add(config);
- return self();
- }
- public B suspended() {
- return suspended(true);
- }
- public B suspended(boolean startsSuspended) {
- this.suspended = startsSuspended;
- return self();
- }
-
- public B server(final ZabbixServer server) {
- this.server = server;
- baseUri(URI.create(server.getConfig(ZabbixServer.ZABBIX_SERVER_API_URL)));
- username(server.getConfig(ZabbixServer.ZABBIX_SERVER_USERNAME));
- password(server.getConfig(ZabbixServer.ZABBIX_SERVER_PASSWORD));
- sessionTimeout(server.getConfig(ZabbixServer.ZABBIX_SESSION_TIMEOUT));
- return self();
- }
- public B username(String username) {
- this.username = username;
- return self();
- }
- public B password(String password) {
- this.password = password;
- return self();
- }
- public B sessionTimeout(Integer sessionTimeout) {
- this.sessionTimeout = sessionTimeout;
- return self();
- }
- public B groupId(Integer groupId) {
- this.groupId = groupId;
- return self();
- }
- public B templateId(Integer templateId) {
- this.templateId = templateId;
- return self();
- }
- public B register(Integer groupId, Integer templateId) {
- this.groupId = groupId;
- this.templateId = templateId;
- return self();
- }
- /**
- * For generating the name to be used when registering the zabbix agent with the zabbix server.
- * When called, guarantees that the entity will have a {@link MachineLocation} (see {@link Entity#getLocations()}).
- * Must return a non-empty string that will be unique across all machines where zabbix agents are installed.
- */
- public B uniqueHostnameGenerator(Function<? super EntityLocal, String> val) {
- this.uniqueHostnameGenerator = checkNotNull(val, "uniqueHostnameGenerator");
- return self();
- }
-
- public Builder uniqueTag(String uniqueTag) {
- this.uniqueTag = uniqueTag;
- return this;
- }
-
- @SuppressWarnings("unchecked")
- public T build() {
- // If server not set and other config not available, try to obtain from entity config
- if (server == null
- && (baseUri == null || baseUriProvider == null)
- && username == null && password == null && sessionTimeout == null) {
- ZabbixServer server = Preconditions.checkNotNull(entity.getConfig(ZabbixMonitored.ZABBIX_SERVER), "The ZABBIX_SERVER config key must be set on the entity");
- server(server);
- }
- // Now create feed
- T result = (T) new ZabbixFeed(this);
- result.setEntity(checkNotNull(entity, "entity"));
- built = true;
- if (suspended) result.suspend();
- result.start();
- return result;
- }
- @Override
- protected void finalize() {
- if (!built) log.warn("ZabbixFeed.Builder created, but build() never called");
- }
- }
-
- protected static class ZabbixPollIdentifier {
- final String itemName;
-
- protected ZabbixPollIdentifier(String itemName) {
- this.itemName = checkNotNull(itemName, "itemName");
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(itemName);
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof ZabbixPollIdentifier)) {
- return false;
- }
- ZabbixPollIdentifier o = (ZabbixPollIdentifier) other;
- return Objects.equal(itemName, o.itemName);
- }
- }
-
- // Flag set when the Zabbix agent is registered for a host
- protected final AtomicBoolean registered = new AtomicBoolean(false);
-
- /**
- * For rebind; do not call directly; use builder
- */
- public ZabbixFeed() {
- }
-
- protected ZabbixFeed(final Builder<? extends ZabbixFeed, ?> builder) {
- setConfig(BASE_URI_PROVIDER, builder.baseUriProvider);
- if (builder.baseUri != null) {
- if (builder.baseUriProvider != null) {
- throw new IllegalStateException("Not permitted to supply baseUri and baseUriProvider");
- }
- setConfig(BASE_URI_PROVIDER, Suppliers.ofInstance(builder.baseUri));
- } else {
- setConfig(BASE_URI_PROVIDER, checkNotNull(builder.baseUriProvider, "baseUriProvider and baseUri"));
- }
-
- setConfig(GROUP_ID, checkNotNull(builder.groupId, "Zabbix groupId must be set"));
- setConfig(TEMPLATE_ID, checkNotNull(builder.templateId, "Zabbix templateId must be set"));
- setConfig(UNIQUE_HOSTNAME_GENERATOR, checkNotNull(builder.uniqueHostnameGenerator, "uniqueHostnameGenerator"));
-
- Set<ZabbixPollConfig<?>> polls = Sets.newLinkedHashSet();
- for (ZabbixPollConfig<?> config : builder.polls) {
- @SuppressWarnings({ "unchecked", "rawtypes" })
- ZabbixPollConfig<?> configCopy = new ZabbixPollConfig(config);
- if (configCopy.getPeriod() < 0) configCopy.period(builder.period, builder.periodUnits);
- polls.add(configCopy);
- }
- setConfig(POLLS, polls);
- initUniqueTag(builder.uniqueTag, polls);
- }
-
- @Override
- protected void preStart() {
- final Supplier<URI> baseUriProvider = getConfig(BASE_URI_PROVIDER);
- final Function<? super EntityLocal, String> uniqueHostnameGenerator = getConfig(UNIQUE_HOSTNAME_GENERATOR);
- final Integer groupId = getConfig(GROUP_ID);
- final Integer templateId = getConfig(TEMPLATE_ID);
- final Set<ZabbixPollConfig<?>> polls = getConfig(POLLS);
-
- log.info("starting zabbix feed for {}", entity);
-
- // TODO if supplier returns null, we may wish to defer initialization until url available?
- // TODO for https should we really trust all?
- final HttpClient httpClient = HttpTool.httpClientBuilder()
- .trustAll()
- .clientConnectionManager(new ThreadSafeClientConnManager())
- .reuseStrategy(new NoConnectionReuseStrategy())
- .uri(baseUriProvider.get())
- .build();
-
- // Registration job, calls Zabbix host.create API
- final Callable<HttpToolResponse> registerJob = new Callable<HttpToolResponse>() {
- @Override
- public HttpToolResponse call() throws Exception {
- if (!registered.get()) {
- // Find the first machine, if available
- Optional<Location> location = Iterables.tryFind(entity.getLocations(), Predicates.instanceOf(MachineLocation.class));
- if (!location.isPresent()) {
- return null; // Do nothing until location is present
- }
- MachineLocation machine = (MachineLocation) location.get();
-
- String host = uniqueHostnameGenerator.apply(entity);
-
- // Select address and port using port-forwarding if available
- String address = entity.getAttribute(Attributes.ADDRESS);
- Integer port = entity.getAttribute(ZabbixMonitored.ZABBIX_AGENT_PORT);
- if (machine instanceof SupportsPortForwarding) {
- Cidr management = entity.getConfig(BrooklynAccessUtils.MANAGEMENT_ACCESS_CIDR);
- HostAndPort forwarded = ((SupportsPortForwarding) machine).getSocketEndpointFor(management, port);
- address = forwarded.getHostText();
- port = forwarded.getPort();
- }
-
- // Fill in the JSON template and POST it
- byte[] body = JSON_HOST_CREATE
- .replace("{{token}}", entity.getConfig(ZabbixMonitored.ZABBIX_SERVER).getAttribute(ZabbixServer.ZABBIX_TOKEN))
- .replace("{{host}}", host)
- .replace("{{ip}}", address)
- .replace("{{port}}", Integer.toString(port))
- .replace("{{groupId}}", Integer.toString(groupId))
- .replace("{{templateId}}", Integer.toString(templateId))
- .replace("{{id}}", Integer.toString(id.incrementAndGet()))
- .getBytes();
-
- return HttpTool.httpPost(httpClient, baseUriProvider.get(), ImmutableMap.of("Content-Type", "application/json"), body);
- }
- return null;
- }
- };
-
- // The handler for the registration job
- PollHandler<? super HttpToolResponse> registrationHandler = new PollHandler<HttpToolResponse>() {
- @Override
- public void onSuccess(HttpToolResponse val) {
- if (registered.get() || val == null) {
- return; // Skip if we are registered already or no data from job
- }
- JsonObject response = HttpValueFunctions.jsonContents().apply(val).getAsJsonObject();
- if (response.has("error")) {
- // Parse the JSON error object and log the message
- JsonObject error = response.get("error").getAsJsonObject();
- String message = error.get("message").getAsString();
- String data = error.get("data").getAsString();
- log.warn("zabbix failed registering host - {}: {}", message, data);
- } else if (response.has("result")) {
- // Parse the JSON result object and save the hostId
- JsonObject result = response.get("result").getAsJsonObject();
- String hostId = result.get("hostids").getAsJsonArray().get(0).getAsString();
- // Update the registered status if not set
- if (registered.compareAndSet(false, true)) {
- entity.setAttribute(ZabbixMonitored.ZABBIX_AGENT_HOSTID, hostId);
- log.info("zabbix registered host as id {}", hostId);
- }
- } else {
- throw new IllegalStateException(String.format("zabbix host registration returned invalid result: %s", response.toString()));
- }
- }
- @Override
- public boolean checkSuccess(HttpToolResponse val) {
- return (val.getResponseCode() == 200);
- }
- @Override
- public void onFailure(HttpToolResponse val) {
- log.warn("zabbix sever returned failure code: {}", val.getResponseCode());
- }
- @Override
- public void onException(Exception exception) {
- log.warn("zabbix exception registering host", exception);
- }
- @Override
- public String toString() {
- return super.toString()+"["+getDescription()+"]";
- }
- @Override
- public String getDescription() {
- return "Zabbix rest poll";
- }
- };
-
- // Schedule registration attempt once per second
- getPoller().scheduleAtFixedRate(registerJob, registrationHandler, 1000l); // TODO make configurable
-
- // Create a polling job for each Zabbix metric
- for (final ZabbixPollConfig<?> config : polls) {
- Callable<HttpToolResponse> pollJob = new Callable<HttpToolResponse>() {
- @Override
- public HttpToolResponse call() throws Exception {
- if (registered.get()) {
- if (log.isTraceEnabled()) log.trace("zabbix polling {} for {}", entity, config);
- byte[] body = JSON_ITEM_GET
- .replace("{{token}}", entity.getConfig(ZabbixMonitored.ZABBIX_SERVER).getAttribute(ZabbixServer.ZABBIX_TOKEN))
- .replace("{{hostId}}", entity.getAttribute(ZabbixMonitored.ZABBIX_AGENT_HOSTID))
- .replace("{{itemKey}}", config.getItemKey())
- .replace("{{id}}", Integer.toString(id.incrementAndGet()))
- .getBytes();
-
- return HttpTool.httpPost(httpClient, baseUriProvider.get(), ImmutableMap.of("Content-Type", "application/json"), body);
- } else {
- throw new IllegalStateException("zabbix agent not yet registered");
- }
- }
- };
-
- // Schedule the Zabbix polling job
- AttributePollHandler<? super HttpToolResponse> pollHandler = new AttributePollHandler<HttpToolResponse>(config, entity, this);
- long minPeriod = Integer.MAX_VALUE; // TODO make configurable
- if (config.getPeriod() > 0) minPeriod = Math.min(minPeriod, config.getPeriod());
- getPoller().scheduleAtFixedRate(pollJob, pollHandler, minPeriod);
- }
-
- }
-
- @SuppressWarnings("unchecked")
- protected Poller<HttpToolResponse> getPoller() {
- return (Poller<HttpToolResponse>) super.getPoller();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixMonitored.java
----------------------------------------------------------------------
diff --git a/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixMonitored.java b/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixMonitored.java
deleted file mode 100644
index fbaab5d..0000000
--- a/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixMonitored.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.monitoring.zabbix;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.event.AttributeSensor;
-import brooklyn.event.basic.BasicAttributeSensor;
-import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
-import brooklyn.util.flags.SetFromFlag;
-
-public interface ZabbixMonitored {
-
- /** The entity representing the Zabbix server monitoring an entity. */
- @SetFromFlag("zabbixServer")
- ConfigKey<ZabbixServer> ZABBIX_SERVER = new BasicConfigKey<ZabbixServer>(ZabbixServer.class, "zabbix.server.entity", "Zabbix server for this entity");
-
- PortAttributeSensorAndConfigKey ZABBIX_AGENT_PORT = new PortAttributeSensorAndConfigKey("zabbix.agent.port", "The port the Zabbix agent is listening on", "10050+");
-
- AttributeSensor<String> ZABBIX_AGENT_HOSTID = new BasicAttributeSensor<String>(String.class, "zabbix.agent.hostid", "The hostId for a Zabbix monitored agent");
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixPollConfig.java
----------------------------------------------------------------------
diff --git a/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixPollConfig.java b/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixPollConfig.java
deleted file mode 100644
index 743df8b..0000000
--- a/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixPollConfig.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.monitoring.zabbix;
-
-import javax.annotation.Nullable;
-
-import brooklyn.event.AttributeSensor;
-import brooklyn.event.feed.PollConfig;
-import brooklyn.event.feed.http.HttpValueFunctions;
-import brooklyn.event.feed.http.JsonFunctions;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.http.HttpToolResponse;
-
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.gson.JsonElement;
-
-public class ZabbixPollConfig<T> extends PollConfig<HttpToolResponse, T, ZabbixPollConfig<T>> {
-
- private String itemKey;
-
- public ZabbixPollConfig(AttributeSensor<T> sensor) {
- super(sensor);
- // Add onSuccess method to extract the last value of the item
- // FIXME Fix generics
- onSuccess((Function)HttpValueFunctions.chain(
- HttpValueFunctions.jsonContents(),
- new Function<JsonElement, JsonElement>() {
- @Override
- public JsonElement apply(@Nullable JsonElement input) {
- Preconditions.checkNotNull(input, "JSON input");
- return input.getAsJsonObject().get("result")
- .getAsJsonArray().get(0)
- .getAsJsonObject().get("lastvalue");
- }
- },
- JsonFunctions.cast(getSensor().getType())));
- }
-
- public ZabbixPollConfig(ZabbixPollConfig<T> other) {
- super(other);
- this.itemKey = other.getItemKey();
- }
-
- public String getItemKey() {
- return itemKey;
- }
-
- public ZabbixPollConfig<T> itemKey(String val) {
- this.itemKey = val;
- return this;
- }
-
- @Override
- protected MutableList<Object> equalsFields() {
- return super.equalsFields().appendIfNotNull(itemKey);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixServer.java
----------------------------------------------------------------------
diff --git a/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixServer.java b/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixServer.java
deleted file mode 100644
index b5987c5..0000000
--- a/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixServer.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.monitoring.zabbix;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.Entity;
-import brooklyn.entity.proxying.ImplementedBy;
-import brooklyn.event.AttributeSensor;
-import brooklyn.event.basic.BasicAttributeSensor;
-import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.util.flags.SetFromFlag;
-
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-
-@ImplementedBy(ZabbixServerImpl.class)
-public interface ZabbixServer extends Entity {
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- @SetFromFlag("filter")
- ConfigKey<Predicate<? super Entity>> ENTITY_FILTER = new BasicConfigKey(Predicate.class, "zabbix.server.filter", "Filter for entities which will automatically be monitored", Predicates.instanceOf(ZabbixMonitored.class));
-
- @SetFromFlag("serverApiUrl")
- ConfigKey<String> ZABBIX_SERVER_API_URL = new BasicConfigKey<String>(String.class, "zabbix.server.apiUrl", "Main Zabbix server API URL");
-
- @SetFromFlag("username")
- ConfigKey<String> ZABBIX_SERVER_USERNAME = new BasicConfigKey<String>(String.class, "zabbix.server.username", "Zabbix server API login user");
-
- @SetFromFlag("password")
- ConfigKey<String> ZABBIX_SERVER_PASSWORD = new BasicConfigKey<String>(String.class, "zabbix.server.password", "Zabbix server API login password");
-
- ConfigKey<Integer> ZABBIX_SESSION_TIMEOUT = new BasicConfigKey<Integer>(Integer.class, "zabbix.server.sessionTimeout", "Zabbix server API session timeout period (seconds)", 3600);
-
- AttributeSensor<String> ZABBIX_TOKEN = new BasicAttributeSensor<String>(String.class, "zabbix.server.token", "Zabbix server API authentication token");
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixServerImpl.java
----------------------------------------------------------------------
diff --git a/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixServerImpl.java b/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixServerImpl.java
deleted file mode 100644
index 43d5f64..0000000
--- a/sandbox/monitoring/src/main/java/brooklyn/entity/monitoring/zabbix/ZabbixServerImpl.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.monitoring.zabbix;
-
-import java.util.List;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.Entity;
-import brooklyn.entity.basic.AbstractEntity;
-import brooklyn.entity.basic.DynamicGroup;
-import brooklyn.entity.group.AbstractMembershipTrackingPolicy;
-import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.entity.trait.Startable;
-import brooklyn.event.feed.http.HttpFeed;
-import brooklyn.event.feed.http.HttpPollConfig;
-import brooklyn.event.feed.http.HttpValueFunctions;
-import brooklyn.location.Location;
-import brooklyn.location.basic.SshMachineLocation;
-import brooklyn.policy.PolicySpec;
-
-import com.google.common.base.Functions;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Multimap;
-
-public class ZabbixServerImpl extends AbstractEntity implements ZabbixServer {
-
- private static final Logger log = LoggerFactory.getLogger(ZabbixServerImpl.class);
-
- private Object[] mutex = new Object[0];
- private DynamicGroup monitoredEntities;
- private AgentTrackingPolicy policy;
- private Multimap<Location, Entity> entityLocations = HashMultimap.create();
-
- private transient HttpFeed login;
-
- @Override
- public void init() {
- super.init();
- Predicate<? super Entity> filter = getConfig(ENTITY_FILTER);
- monitoredEntities = addChild(EntitySpec.create(DynamicGroup.class)
- .configure(DynamicGroup.ENTITY_FILTER, filter)
- .displayName("agents"));
- }
-
- @Override
- public void onManagementStarted() {
- final byte[] jsonData = ZabbixFeed.JSON_USER_LOGIN
- .replace("{{username}}", getConfig(ZABBIX_SERVER_USERNAME))
- .replace("{{password}}", getConfig(ZABBIX_SERVER_PASSWORD))
- .getBytes();
- login = HttpFeed.builder()
- .entity(this)
- .baseUri(getConfig(ZABBIX_SERVER_API_URL))
- .headers(ImmutableMap.of("Content-Type", "application/json"))
- .poll(new HttpPollConfig<String>(ZABBIX_TOKEN)
- .method("POST")
- .body(jsonData)
- .onFailure(Functions.constant(""))
- .onSuccess(HttpValueFunctions.jsonContents("result", String.class)))
- .build();
-
- policy = addPolicy(PolicySpec.create(AgentTrackingPolicy.class)
- .displayName("Zabbix Agent Tracker")
- .configure("group", monitoredEntities));
-
- for (Entity each : monitoredEntities.getMembers()) {
- added(each);
- }
-
- setAttribute(Startable.SERVICE_UP, true);
- }
-
- public static class AgentTrackingPolicy extends AbstractMembershipTrackingPolicy {
- @Override
- protected void onEntityChange(Entity member) {
- ((ZabbixServerImpl)entity).added(member); }
- @Override
- protected void onEntityAdded(Entity member) {
- } // Ignore
- @Override
- protected void onEntityRemoved(Entity member) {
- ((ZabbixServerImpl)entity).removed(member);
- }
- }
-
- public void added(Entity member) {
- synchronized (mutex) {
- Optional<Location> location = Iterables.tryFind(member.getLocations(), Predicates.instanceOf(SshMachineLocation.class));
- if (location.isPresent() && member.getAttribute(Startable.SERVICE_UP)) {
- SshMachineLocation machine = (SshMachineLocation) location.get();
- if (!entityLocations.containsKey(machine)) {
- entityLocations.put(machine, member);
- // Configure the Zabbix agent
- List<String> commands = ImmutableList.<String>builder()
- .add("sed -i.bk 's/\\$HOSTNAME/" + machine.getDisplayName() + "/' /etc/zabbix/zabbix_agentd.conf")
- .add("zabbix_agentd")
- .build();
- int result = machine.execCommands("configuring zabbix_agentd", commands);
- if (result == 0) {
- log.info("zabbix_agentd configured on {} at {}", member, machine);
- } else {
- log.warn("failed to configure zabbix_agentd on {}, status {}", machine, result);
- }
- }
- } else {
- log.warn("zabbix added({}) called but no location or service not started", member);
- }
- }
- }
-
- public void removed(Entity member) {
- synchronized (mutex) {
- for (Location location : member.getLocations()) {
- entityLocations.remove(location, member);
- }
- }
- }
-
-}
[6/6] incubator-brooklyn git commit: This closes #802
Posted by ha...@apache.org.
This closes #802
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/7154cc9e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/7154cc9e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/7154cc9e
Branch: refs/heads/master
Commit: 7154cc9ec5d729641aef56857a76c2473317330f
Parents: fc42b17 070b5ca
Author: Hadrian Zbarcea <ha...@apache.org>
Authored: Thu Aug 6 19:48:10 2015 -0400
Committer: Hadrian Zbarcea <ha...@apache.org>
Committed: Thu Aug 6 19:48:10 2015 -0400
----------------------------------------------------------------------
.../customsnitch/MultiCloudSnitch.java | 222 ---------
.../customsnitch/MultiCloudSnitch.java | 222 +++++++++
.../brooklyn/entity/database/Database.groovy | 53 ---
.../entity/database/derby/DerbyDatabase.java | 172 -------
.../database/derby/DerbyDatabaseDriver.java | 25 -
.../database/derby/DerbyDatabaseSshDriver.java | 116 -----
.../entity/database/derby/DerbySchema.java | 147 ------
.../brooklyn/entity/database/Database.groovy | 53 +++
.../entity/database/derby/DerbyDatabase.java | 172 +++++++
.../database/derby/DerbyDatabaseDriver.java | 25 +
.../database/derby/DerbyDatabaseSshDriver.java | 116 +++++
.../entity/database/derby/DerbySchema.java | 148 ++++++
.../entity/database/PlaceholderTest.java | 26 --
.../entity/database/PlaceholderTest.java | 26 ++
.../postgresql/PostgreSqlNodeSaltImpl.java | 177 -------
.../brooklyn/entity/salt/SaltBashCommands.java | 92 ----
.../java/brooklyn/entity/salt/SaltConfig.java | 100 ----
.../java/brooklyn/entity/salt/SaltConfigs.java | 89 ----
.../entity/salt/SaltLifecycleEffectorTasks.java | 220 ---------
.../brooklyn/entity/salt/SaltStackMaster.java | 70 ---
.../entity/salt/SaltStackMasterDriver.java | 25 -
.../entity/salt/SaltStackMasterImpl.java | 56 ---
.../entity/salt/SaltStackMasterSshDriver.java | 95 ----
.../java/brooklyn/entity/salt/SaltTasks.java | 145 ------
.../postgresql/PostgreSqlNodeSaltImpl.java | 179 +++++++
.../brooklyn/entity/salt/SaltBashCommands.java | 92 ++++
.../apache/brooklyn/entity/salt/SaltConfig.java | 100 ++++
.../brooklyn/entity/salt/SaltConfigs.java | 89 ++++
.../entity/salt/SaltLifecycleEffectorTasks.java | 220 +++++++++
.../brooklyn/entity/salt/SaltStackMaster.java | 70 +++
.../entity/salt/SaltStackMasterDriver.java | 25 +
.../entity/salt/SaltStackMasterImpl.java | 56 +++
.../entity/salt/SaltStackMasterSshDriver.java | 95 ++++
.../apache/brooklyn/entity/salt/SaltTasks.java | 145 ++++++
.../main/resources/brooklyn/entity/salt/master | 65 ---
.../resources/brooklyn/entity/salt/masterless | 53 ---
.../main/resources/brooklyn/entity/salt/minion | 52 ---
.../org/apache/brooklyn/entity/salt/master | 65 +++
.../org/apache/brooklyn/entity/salt/masterless | 53 +++
.../org/apache/brooklyn/entity/salt/minion | 52 +++
.../postgresql/PostgreSqlSaltLiveTest.java | 109 -----
.../brooklyn/entity/salt/SaltConfigsTest.java | 69 ---
.../entity/salt/SaltLiveTestSupport.java | 68 ---
.../postgresql/PostgreSqlSaltLiveTest.java | 112 +++++
.../brooklyn/entity/salt/SaltConfigsTest.java | 71 +++
.../entity/salt/SaltLiveTestSupport.java | 68 +++
.../entity/monitoring/zabbix/ZabbixFeed.java | 463 -------------------
.../monitoring/zabbix/ZabbixMonitored.java | 38 --
.../monitoring/zabbix/ZabbixPollConfig.java | 75 ---
.../entity/monitoring/zabbix/ZabbixServer.java | 52 ---
.../monitoring/zabbix/ZabbixServerImpl.java | 143 ------
.../entity/monitoring/zabbix/ZabbixFeed.java | 463 +++++++++++++++++++
.../monitoring/zabbix/ZabbixMonitored.java | 38 ++
.../monitoring/zabbix/ZabbixPollConfig.java | 75 +++
.../entity/monitoring/zabbix/ZabbixServer.java | 52 +++
.../monitoring/zabbix/ZabbixServerImpl.java | 143 ++++++
sandbox/nosql/pom.xml | 2 +-
.../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/infinispan/Infinispan5Driver.java | 23 -
.../nosql/infinispan/Infinispan5Server.java | 88 ----
.../nosql/infinispan/Infinispan5SshDriver.java | 124 -----
.../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/infinispan/Infinispan5Driver.java | 23 +
.../nosql/infinispan/Infinispan5Server.java | 88 ++++
.../nosql/infinispan/Infinispan5SshDriver.java | 124 +++++
.../nosql/hazelcast/hazelcast-brooklyn.xml | 65 ---
.../nosql/hazelcast/hazelcast-brooklyn.xml | 65 +++
.../hazelcast/HazelcastClusterEc2LiveTest.java | 71 ---
.../HazelcastClusterSoftlayerLiveTest.java | 71 ---
.../Infinispan5ServerIntegrationTest.groovy | 102 ----
.../hazelcast/HazelcastClusterEc2LiveTest.java | 73 +++
.../HazelcastClusterSoftlayerLiveTest.java | 73 +++
.../Infinispan5ServerIntegrationTest.groovy | 103 +++++
83 files changed, 4187 insertions(+), 4174 deletions(-)
----------------------------------------------------------------------
[2/6] incubator-brooklyn git commit: package rename to
org.apache.brooklyn: sandbox
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixFeed.java
----------------------------------------------------------------------
diff --git a/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixFeed.java b/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixFeed.java
new file mode 100644
index 0000000..08fba87
--- /dev/null
+++ b/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixFeed.java
@@ -0,0 +1,463 @@
+/*
+ * 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.monitoring.zabbix;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.impl.NoConnectionReuseStrategy;
+import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.EntityFunctions;
+import brooklyn.entity.basic.EntityLocal;
+import brooklyn.event.feed.AbstractFeed;
+import brooklyn.event.feed.AttributePollHandler;
+import brooklyn.event.feed.PollHandler;
+import brooklyn.event.feed.Poller;
+import brooklyn.event.feed.http.HttpValueFunctions;
+import brooklyn.location.Location;
+import brooklyn.location.MachineLocation;
+import brooklyn.location.access.BrooklynAccessUtils;
+import brooklyn.location.basic.SupportsPortForwarding;
+import brooklyn.util.http.HttpTool;
+import brooklyn.util.http.HttpToolResponse;
+import brooklyn.util.net.Cidr;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.common.net.HostAndPort;
+import com.google.common.reflect.TypeToken;
+import com.google.gson.JsonObject;
+
+public class ZabbixFeed extends AbstractFeed {
+
+ public static final Logger log = LoggerFactory.getLogger(ZabbixFeed.class);
+
+ public static final String JSON_ITEM_GET =
+ "{ \"jsonrpc\":\"2.0\",\"method\":\"item.get\"," +
+ "\"params\":{\"output\":\"extend\"," +
+ "\"filter\":{\"hostid\":[\"{{hostId}}\"],\"key_\":\"{{itemKey}}\"}}," +
+ "\"auth\":\"{{token}}\",\"id\":{{id}}}";
+ public static final String JSON_USER_LOGIN =
+ "{ \"jsonrpc\":\"2.0\",\"method\":\"user.login\"," +
+ "\"params\":{\"user\":\"{{username}}\",\"password\":\"{{password}}\"}," +
+ "\"id\":0 }";
+ public static final String JSON_HOST_CREATE =
+ "{ \"jsonrpc\":\"2.0\",\"method\":\"host.create\"," +
+ "\"params\":{\"host\":\"{{host}}\"," +
+ "\"interfaces\":[{\"type\":1,\"main\":1,\"useip\":1,\"ip\":\"{{ip}}\",\"dns\":\"\",\"port\":\"{{port}}\"}]," +
+ "\"groups\":[{\"groupid\":\"{{groupId}}\"}]," +
+ "\"templates\":[{\"templateid\":\"{{templateId}}\"}]}," +
+ "\"auth\":\"{{token}}\",\"id\":{{id}}}";
+
+ private static final AtomicInteger id = new AtomicInteger(0);
+
+ @SuppressWarnings("serial")
+ public static final ConfigKey<Set<ZabbixPollConfig<?>>> POLLS = ConfigKeys.newConfigKey(
+ new TypeToken<Set<ZabbixPollConfig<?>>>() {},
+ "polls");
+
+ @SuppressWarnings("serial")
+ public static final ConfigKey<Supplier<URI>> BASE_URI_PROVIDER = ConfigKeys.newConfigKey(
+ new TypeToken<Supplier<URI>>() {},
+ "baseUriProvider");
+
+ public static final ConfigKey<Integer> GROUP_ID = ConfigKeys.newIntegerConfigKey("groupId");
+
+ public static final ConfigKey<Integer> TEMPLATE_ID = ConfigKeys.newIntegerConfigKey("templateId");
+
+ @SuppressWarnings("serial")
+ public static final ConfigKey<Function<? super EntityLocal, String>> UNIQUE_HOSTNAME_GENERATOR = ConfigKeys.newConfigKey(
+ new TypeToken<Function<? super EntityLocal, String>>() {},
+ "uniqueHostnameGenerator");
+
+ public static Builder<ZabbixFeed, ?> builder() {
+ return new ConcreteBuilder();
+ }
+
+ private static class ConcreteBuilder extends Builder<ZabbixFeed, ConcreteBuilder> {
+ }
+
+ public static class Builder<T extends ZabbixFeed, B extends Builder<T,B>> {
+ private EntityLocal entity;
+ private Supplier<URI> baseUriProvider;
+ private long period = 500;
+ private TimeUnit periodUnits = TimeUnit.MILLISECONDS;
+ private List<ZabbixPollConfig<?>> polls = Lists.newArrayList();
+ private URI baseUri;
+ private boolean suspended = false;
+ private volatile boolean built;
+ private ZabbixServer server;
+ private String username;
+ private String password;
+ private Integer sessionTimeout;
+ private Integer groupId;
+ private Integer templateId;
+ private Function<? super EntityLocal, String> uniqueHostnameGenerator = Functions.compose(
+ EntityFunctions.id(),
+ EntityFunctions.locationMatching(Predicates.instanceOf(MachineLocation.class)));
+ private String uniqueTag;
+
+ @SuppressWarnings("unchecked")
+ protected B self() {
+ return (B) this;
+ }
+
+ public B entity(EntityLocal val) {
+ this.entity = val;
+ return self();
+ }
+ public B baseUri(Supplier<URI> val) {
+ if (baseUri!=null && val!=null)
+ throw new IllegalStateException("Builder cannot take both a URI and a URI Provider");
+ this.baseUriProvider = val;
+ return self();
+ }
+ public B baseUri(URI val) {
+ if (baseUriProvider!=null && val!=null)
+ throw new IllegalStateException("Builder cannot take both a URI and a URI Provider");
+ this.baseUri = val;
+ return self();
+ }
+ public B baseUrl(URL val) {
+ return baseUri(URI.create(val.toString()));
+ }
+ public B baseUri(String val) {
+ return baseUri(URI.create(val));
+ }
+ public B period(long millis) {
+ return period(millis, TimeUnit.MILLISECONDS);
+ }
+ public B period(long val, TimeUnit units) {
+ this.period = val;
+ this.periodUnits = units;
+ return self();
+ }
+ public B poll(ZabbixPollConfig<?> config) {
+ polls.add(config);
+ return self();
+ }
+ public B suspended() {
+ return suspended(true);
+ }
+ public B suspended(boolean startsSuspended) {
+ this.suspended = startsSuspended;
+ return self();
+ }
+
+ public B server(final ZabbixServer server) {
+ this.server = server;
+ baseUri(URI.create(server.getConfig(ZabbixServer.ZABBIX_SERVER_API_URL)));
+ username(server.getConfig(ZabbixServer.ZABBIX_SERVER_USERNAME));
+ password(server.getConfig(ZabbixServer.ZABBIX_SERVER_PASSWORD));
+ sessionTimeout(server.getConfig(ZabbixServer.ZABBIX_SESSION_TIMEOUT));
+ return self();
+ }
+ public B username(String username) {
+ this.username = username;
+ return self();
+ }
+ public B password(String password) {
+ this.password = password;
+ return self();
+ }
+ public B sessionTimeout(Integer sessionTimeout) {
+ this.sessionTimeout = sessionTimeout;
+ return self();
+ }
+ public B groupId(Integer groupId) {
+ this.groupId = groupId;
+ return self();
+ }
+ public B templateId(Integer templateId) {
+ this.templateId = templateId;
+ return self();
+ }
+ public B register(Integer groupId, Integer templateId) {
+ this.groupId = groupId;
+ this.templateId = templateId;
+ return self();
+ }
+ /**
+ * For generating the name to be used when registering the zabbix agent with the zabbix server.
+ * When called, guarantees that the entity will have a {@link MachineLocation} (see {@link Entity#getLocations()}).
+ * Must return a non-empty string that will be unique across all machines where zabbix agents are installed.
+ */
+ public B uniqueHostnameGenerator(Function<? super EntityLocal, String> val) {
+ this.uniqueHostnameGenerator = checkNotNull(val, "uniqueHostnameGenerator");
+ return self();
+ }
+
+ public Builder uniqueTag(String uniqueTag) {
+ this.uniqueTag = uniqueTag;
+ return this;
+ }
+
+ @SuppressWarnings("unchecked")
+ public T build() {
+ // If server not set and other config not available, try to obtain from entity config
+ if (server == null
+ && (baseUri == null || baseUriProvider == null)
+ && username == null && password == null && sessionTimeout == null) {
+ ZabbixServer server = Preconditions.checkNotNull(entity.getConfig(ZabbixMonitored.ZABBIX_SERVER), "The ZABBIX_SERVER config key must be set on the entity");
+ server(server);
+ }
+ // Now create feed
+ T result = (T) new ZabbixFeed(this);
+ result.setEntity(checkNotNull(entity, "entity"));
+ built = true;
+ if (suspended) result.suspend();
+ result.start();
+ return result;
+ }
+ @Override
+ protected void finalize() {
+ if (!built) log.warn("ZabbixFeed.Builder created, but build() never called");
+ }
+ }
+
+ protected static class ZabbixPollIdentifier {
+ final String itemName;
+
+ protected ZabbixPollIdentifier(String itemName) {
+ this.itemName = checkNotNull(itemName, "itemName");
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(itemName);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof ZabbixPollIdentifier)) {
+ return false;
+ }
+ ZabbixPollIdentifier o = (ZabbixPollIdentifier) other;
+ return Objects.equal(itemName, o.itemName);
+ }
+ }
+
+ // Flag set when the Zabbix agent is registered for a host
+ protected final AtomicBoolean registered = new AtomicBoolean(false);
+
+ /**
+ * For rebind; do not call directly; use builder
+ */
+ public ZabbixFeed() {
+ }
+
+ protected ZabbixFeed(final Builder<? extends ZabbixFeed, ?> builder) {
+ setConfig(BASE_URI_PROVIDER, builder.baseUriProvider);
+ if (builder.baseUri != null) {
+ if (builder.baseUriProvider != null) {
+ throw new IllegalStateException("Not permitted to supply baseUri and baseUriProvider");
+ }
+ setConfig(BASE_URI_PROVIDER, Suppliers.ofInstance(builder.baseUri));
+ } else {
+ setConfig(BASE_URI_PROVIDER, checkNotNull(builder.baseUriProvider, "baseUriProvider and baseUri"));
+ }
+
+ setConfig(GROUP_ID, checkNotNull(builder.groupId, "Zabbix groupId must be set"));
+ setConfig(TEMPLATE_ID, checkNotNull(builder.templateId, "Zabbix templateId must be set"));
+ setConfig(UNIQUE_HOSTNAME_GENERATOR, checkNotNull(builder.uniqueHostnameGenerator, "uniqueHostnameGenerator"));
+
+ Set<ZabbixPollConfig<?>> polls = Sets.newLinkedHashSet();
+ for (ZabbixPollConfig<?> config : builder.polls) {
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ ZabbixPollConfig<?> configCopy = new ZabbixPollConfig(config);
+ if (configCopy.getPeriod() < 0) configCopy.period(builder.period, builder.periodUnits);
+ polls.add(configCopy);
+ }
+ setConfig(POLLS, polls);
+ initUniqueTag(builder.uniqueTag, polls);
+ }
+
+ @Override
+ protected void preStart() {
+ final Supplier<URI> baseUriProvider = getConfig(BASE_URI_PROVIDER);
+ final Function<? super EntityLocal, String> uniqueHostnameGenerator = getConfig(UNIQUE_HOSTNAME_GENERATOR);
+ final Integer groupId = getConfig(GROUP_ID);
+ final Integer templateId = getConfig(TEMPLATE_ID);
+ final Set<ZabbixPollConfig<?>> polls = getConfig(POLLS);
+
+ log.info("starting zabbix feed for {}", entity);
+
+ // TODO if supplier returns null, we may wish to defer initialization until url available?
+ // TODO for https should we really trust all?
+ final HttpClient httpClient = HttpTool.httpClientBuilder()
+ .trustAll()
+ .clientConnectionManager(new ThreadSafeClientConnManager())
+ .reuseStrategy(new NoConnectionReuseStrategy())
+ .uri(baseUriProvider.get())
+ .build();
+
+ // Registration job, calls Zabbix host.create API
+ final Callable<HttpToolResponse> registerJob = new Callable<HttpToolResponse>() {
+ @Override
+ public HttpToolResponse call() throws Exception {
+ if (!registered.get()) {
+ // Find the first machine, if available
+ Optional<Location> location = Iterables.tryFind(entity.getLocations(), Predicates.instanceOf(MachineLocation.class));
+ if (!location.isPresent()) {
+ return null; // Do nothing until location is present
+ }
+ MachineLocation machine = (MachineLocation) location.get();
+
+ String host = uniqueHostnameGenerator.apply(entity);
+
+ // Select address and port using port-forwarding if available
+ String address = entity.getAttribute(Attributes.ADDRESS);
+ Integer port = entity.getAttribute(ZabbixMonitored.ZABBIX_AGENT_PORT);
+ if (machine instanceof SupportsPortForwarding) {
+ Cidr management = entity.getConfig(BrooklynAccessUtils.MANAGEMENT_ACCESS_CIDR);
+ HostAndPort forwarded = ((SupportsPortForwarding) machine).getSocketEndpointFor(management, port);
+ address = forwarded.getHostText();
+ port = forwarded.getPort();
+ }
+
+ // Fill in the JSON template and POST it
+ byte[] body = JSON_HOST_CREATE
+ .replace("{{token}}", entity.getConfig(ZabbixMonitored.ZABBIX_SERVER).getAttribute(ZabbixServer.ZABBIX_TOKEN))
+ .replace("{{host}}", host)
+ .replace("{{ip}}", address)
+ .replace("{{port}}", Integer.toString(port))
+ .replace("{{groupId}}", Integer.toString(groupId))
+ .replace("{{templateId}}", Integer.toString(templateId))
+ .replace("{{id}}", Integer.toString(id.incrementAndGet()))
+ .getBytes();
+
+ return HttpTool.httpPost(httpClient, baseUriProvider.get(), ImmutableMap.of("Content-Type", "application/json"), body);
+ }
+ return null;
+ }
+ };
+
+ // The handler for the registration job
+ PollHandler<? super HttpToolResponse> registrationHandler = new PollHandler<HttpToolResponse>() {
+ @Override
+ public void onSuccess(HttpToolResponse val) {
+ if (registered.get() || val == null) {
+ return; // Skip if we are registered already or no data from job
+ }
+ JsonObject response = HttpValueFunctions.jsonContents().apply(val).getAsJsonObject();
+ if (response.has("error")) {
+ // Parse the JSON error object and log the message
+ JsonObject error = response.get("error").getAsJsonObject();
+ String message = error.get("message").getAsString();
+ String data = error.get("data").getAsString();
+ log.warn("zabbix failed registering host - {}: {}", message, data);
+ } else if (response.has("result")) {
+ // Parse the JSON result object and save the hostId
+ JsonObject result = response.get("result").getAsJsonObject();
+ String hostId = result.get("hostids").getAsJsonArray().get(0).getAsString();
+ // Update the registered status if not set
+ if (registered.compareAndSet(false, true)) {
+ entity.setAttribute(ZabbixMonitored.ZABBIX_AGENT_HOSTID, hostId);
+ log.info("zabbix registered host as id {}", hostId);
+ }
+ } else {
+ throw new IllegalStateException(String.format("zabbix host registration returned invalid result: %s", response.toString()));
+ }
+ }
+ @Override
+ public boolean checkSuccess(HttpToolResponse val) {
+ return (val.getResponseCode() == 200);
+ }
+ @Override
+ public void onFailure(HttpToolResponse val) {
+ log.warn("zabbix sever returned failure code: {}", val.getResponseCode());
+ }
+ @Override
+ public void onException(Exception exception) {
+ log.warn("zabbix exception registering host", exception);
+ }
+ @Override
+ public String toString() {
+ return super.toString()+"["+getDescription()+"]";
+ }
+ @Override
+ public String getDescription() {
+ return "Zabbix rest poll";
+ }
+ };
+
+ // Schedule registration attempt once per second
+ getPoller().scheduleAtFixedRate(registerJob, registrationHandler, 1000l); // TODO make configurable
+
+ // Create a polling job for each Zabbix metric
+ for (final ZabbixPollConfig<?> config : polls) {
+ Callable<HttpToolResponse> pollJob = new Callable<HttpToolResponse>() {
+ @Override
+ public HttpToolResponse call() throws Exception {
+ if (registered.get()) {
+ if (log.isTraceEnabled()) log.trace("zabbix polling {} for {}", entity, config);
+ byte[] body = JSON_ITEM_GET
+ .replace("{{token}}", entity.getConfig(ZabbixMonitored.ZABBIX_SERVER).getAttribute(ZabbixServer.ZABBIX_TOKEN))
+ .replace("{{hostId}}", entity.getAttribute(ZabbixMonitored.ZABBIX_AGENT_HOSTID))
+ .replace("{{itemKey}}", config.getItemKey())
+ .replace("{{id}}", Integer.toString(id.incrementAndGet()))
+ .getBytes();
+
+ return HttpTool.httpPost(httpClient, baseUriProvider.get(), ImmutableMap.of("Content-Type", "application/json"), body);
+ } else {
+ throw new IllegalStateException("zabbix agent not yet registered");
+ }
+ }
+ };
+
+ // Schedule the Zabbix polling job
+ AttributePollHandler<? super HttpToolResponse> pollHandler = new AttributePollHandler<HttpToolResponse>(config, entity, this);
+ long minPeriod = Integer.MAX_VALUE; // TODO make configurable
+ if (config.getPeriod() > 0) minPeriod = Math.min(minPeriod, config.getPeriod());
+ getPoller().scheduleAtFixedRate(pollJob, pollHandler, minPeriod);
+ }
+
+ }
+
+ @SuppressWarnings("unchecked")
+ protected Poller<HttpToolResponse> getPoller() {
+ return (Poller<HttpToolResponse>) super.getPoller();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixMonitored.java
----------------------------------------------------------------------
diff --git a/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixMonitored.java b/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixMonitored.java
new file mode 100644
index 0000000..78e9dfd
--- /dev/null
+++ b/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixMonitored.java
@@ -0,0 +1,38 @@
+/*
+ * 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.monitoring.zabbix;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.event.AttributeSensor;
+import brooklyn.event.basic.BasicAttributeSensor;
+import brooklyn.event.basic.BasicConfigKey;
+import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
+import brooklyn.util.flags.SetFromFlag;
+
+public interface ZabbixMonitored {
+
+ /** The entity representing the Zabbix server monitoring an entity. */
+ @SetFromFlag("zabbixServer")
+ ConfigKey<ZabbixServer> ZABBIX_SERVER = new BasicConfigKey<ZabbixServer>(ZabbixServer.class, "zabbix.server.entity", "Zabbix server for this entity");
+
+ PortAttributeSensorAndConfigKey ZABBIX_AGENT_PORT = new PortAttributeSensorAndConfigKey("zabbix.agent.port", "The port the Zabbix agent is listening on", "10050+");
+
+ AttributeSensor<String> ZABBIX_AGENT_HOSTID = new BasicAttributeSensor<String>(String.class, "zabbix.agent.hostid", "The hostId for a Zabbix monitored agent");
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixPollConfig.java
----------------------------------------------------------------------
diff --git a/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixPollConfig.java b/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixPollConfig.java
new file mode 100644
index 0000000..a215133
--- /dev/null
+++ b/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixPollConfig.java
@@ -0,0 +1,75 @@
+/*
+ * 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.monitoring.zabbix;
+
+import javax.annotation.Nullable;
+
+import brooklyn.event.AttributeSensor;
+import brooklyn.event.feed.PollConfig;
+import brooklyn.event.feed.http.HttpValueFunctions;
+import brooklyn.event.feed.http.JsonFunctions;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.http.HttpToolResponse;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.gson.JsonElement;
+
+public class ZabbixPollConfig<T> extends PollConfig<HttpToolResponse, T, ZabbixPollConfig<T>> {
+
+ private String itemKey;
+
+ public ZabbixPollConfig(AttributeSensor<T> sensor) {
+ super(sensor);
+ // Add onSuccess method to extract the last value of the item
+ // FIXME Fix generics
+ onSuccess((Function)HttpValueFunctions.chain(
+ HttpValueFunctions.jsonContents(),
+ new Function<JsonElement, JsonElement>() {
+ @Override
+ public JsonElement apply(@Nullable JsonElement input) {
+ Preconditions.checkNotNull(input, "JSON input");
+ return input.getAsJsonObject().get("result")
+ .getAsJsonArray().get(0)
+ .getAsJsonObject().get("lastvalue");
+ }
+ },
+ JsonFunctions.cast(getSensor().getType())));
+ }
+
+ public ZabbixPollConfig(ZabbixPollConfig<T> other) {
+ super(other);
+ this.itemKey = other.getItemKey();
+ }
+
+ public String getItemKey() {
+ return itemKey;
+ }
+
+ public ZabbixPollConfig<T> itemKey(String val) {
+ this.itemKey = val;
+ return this;
+ }
+
+ @Override
+ protected MutableList<Object> equalsFields() {
+ return super.equalsFields().appendIfNotNull(itemKey);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixServer.java
----------------------------------------------------------------------
diff --git a/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixServer.java b/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixServer.java
new file mode 100644
index 0000000..db287e8
--- /dev/null
+++ b/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixServer.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.monitoring.zabbix;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.Entity;
+import brooklyn.entity.proxying.ImplementedBy;
+import brooklyn.event.AttributeSensor;
+import brooklyn.event.basic.BasicAttributeSensor;
+import brooklyn.event.basic.BasicConfigKey;
+import brooklyn.util.flags.SetFromFlag;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+
+@ImplementedBy(ZabbixServerImpl.class)
+public interface ZabbixServer extends Entity {
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @SetFromFlag("filter")
+ ConfigKey<Predicate<? super Entity>> ENTITY_FILTER = new BasicConfigKey(Predicate.class, "zabbix.server.filter", "Filter for entities which will automatically be monitored", Predicates.instanceOf(ZabbixMonitored.class));
+
+ @SetFromFlag("serverApiUrl")
+ ConfigKey<String> ZABBIX_SERVER_API_URL = new BasicConfigKey<String>(String.class, "zabbix.server.apiUrl", "Main Zabbix server API URL");
+
+ @SetFromFlag("username")
+ ConfigKey<String> ZABBIX_SERVER_USERNAME = new BasicConfigKey<String>(String.class, "zabbix.server.username", "Zabbix server API login user");
+
+ @SetFromFlag("password")
+ ConfigKey<String> ZABBIX_SERVER_PASSWORD = new BasicConfigKey<String>(String.class, "zabbix.server.password", "Zabbix server API login password");
+
+ ConfigKey<Integer> ZABBIX_SESSION_TIMEOUT = new BasicConfigKey<Integer>(Integer.class, "zabbix.server.sessionTimeout", "Zabbix server API session timeout period (seconds)", 3600);
+
+ AttributeSensor<String> ZABBIX_TOKEN = new BasicAttributeSensor<String>(String.class, "zabbix.server.token", "Zabbix server API authentication token");
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixServerImpl.java
----------------------------------------------------------------------
diff --git a/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixServerImpl.java b/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixServerImpl.java
new file mode 100644
index 0000000..9ad8ac0
--- /dev/null
+++ b/sandbox/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/zabbix/ZabbixServerImpl.java
@@ -0,0 +1,143 @@
+/*
+ * 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.monitoring.zabbix;
+
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.AbstractEntity;
+import brooklyn.entity.basic.DynamicGroup;
+import brooklyn.entity.group.AbstractMembershipTrackingPolicy;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.trait.Startable;
+import brooklyn.event.feed.http.HttpFeed;
+import brooklyn.event.feed.http.HttpPollConfig;
+import brooklyn.event.feed.http.HttpValueFunctions;
+import brooklyn.location.Location;
+import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.policy.PolicySpec;
+
+import com.google.common.base.Functions;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+
+public class ZabbixServerImpl extends AbstractEntity implements ZabbixServer {
+
+ private static final Logger log = LoggerFactory.getLogger(ZabbixServerImpl.class);
+
+ private Object[] mutex = new Object[0];
+ private DynamicGroup monitoredEntities;
+ private AgentTrackingPolicy policy;
+ private Multimap<Location, Entity> entityLocations = HashMultimap.create();
+
+ private transient HttpFeed login;
+
+ @Override
+ public void init() {
+ super.init();
+ Predicate<? super Entity> filter = getConfig(ENTITY_FILTER);
+ monitoredEntities = addChild(EntitySpec.create(DynamicGroup.class)
+ .configure(DynamicGroup.ENTITY_FILTER, filter)
+ .displayName("agents"));
+ }
+
+ @Override
+ public void onManagementStarted() {
+ final byte[] jsonData = ZabbixFeed.JSON_USER_LOGIN
+ .replace("{{username}}", getConfig(ZABBIX_SERVER_USERNAME))
+ .replace("{{password}}", getConfig(ZABBIX_SERVER_PASSWORD))
+ .getBytes();
+ login = HttpFeed.builder()
+ .entity(this)
+ .baseUri(getConfig(ZABBIX_SERVER_API_URL))
+ .headers(ImmutableMap.of("Content-Type", "application/json"))
+ .poll(new HttpPollConfig<String>(ZABBIX_TOKEN)
+ .method("POST")
+ .body(jsonData)
+ .onFailure(Functions.constant(""))
+ .onSuccess(HttpValueFunctions.jsonContents("result", String.class)))
+ .build();
+
+ policy = addPolicy(PolicySpec.create(AgentTrackingPolicy.class)
+ .displayName("Zabbix Agent Tracker")
+ .configure("group", monitoredEntities));
+
+ for (Entity each : monitoredEntities.getMembers()) {
+ added(each);
+ }
+
+ setAttribute(Startable.SERVICE_UP, true);
+ }
+
+ public static class AgentTrackingPolicy extends AbstractMembershipTrackingPolicy {
+ @Override
+ protected void onEntityChange(Entity member) {
+ ((ZabbixServerImpl)entity).added(member); }
+ @Override
+ protected void onEntityAdded(Entity member) {
+ } // Ignore
+ @Override
+ protected void onEntityRemoved(Entity member) {
+ ((ZabbixServerImpl)entity).removed(member);
+ }
+ }
+
+ public void added(Entity member) {
+ synchronized (mutex) {
+ Optional<Location> location = Iterables.tryFind(member.getLocations(), Predicates.instanceOf(SshMachineLocation.class));
+ if (location.isPresent() && member.getAttribute(Startable.SERVICE_UP)) {
+ SshMachineLocation machine = (SshMachineLocation) location.get();
+ if (!entityLocations.containsKey(machine)) {
+ entityLocations.put(machine, member);
+ // Configure the Zabbix agent
+ List<String> commands = ImmutableList.<String>builder()
+ .add("sed -i.bk 's/\\$HOSTNAME/" + machine.getDisplayName() + "/' /etc/zabbix/zabbix_agentd.conf")
+ .add("zabbix_agentd")
+ .build();
+ int result = machine.execCommands("configuring zabbix_agentd", commands);
+ if (result == 0) {
+ log.info("zabbix_agentd configured on {} at {}", member, machine);
+ } else {
+ log.warn("failed to configure zabbix_agentd on {}, status {}", machine, result);
+ }
+ }
+ } else {
+ log.warn("zabbix added({}) called but no location or service not started", member);
+ }
+ }
+ }
+
+ public void removed(Entity member) {
+ synchronized (mutex) {
+ for (Location location : member.getLocations()) {
+ entityLocations.remove(location, member);
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/nosql/pom.xml
----------------------------------------------------------------------
diff --git a/sandbox/nosql/pom.xml b/sandbox/nosql/pom.xml
index af576d0..ccf1487 100644
--- a/sandbox/nosql/pom.xml
+++ b/sandbox/nosql/pom.xml
@@ -101,7 +101,7 @@
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>
+ <exclude>src/main/resources/org/apache/brooklyn/entity/nosql/hazelcast/hazelcast-brooklyn.xml</exclude>
</excludes>
</configuration>
</plugin>
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/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
deleted file mode 100644
index c91b78c..0000000
--- a/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastCluster.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.nosql.hazelcast;
-
-import java.util.List;
-
-import com.google.common.reflect.TypeToken;
-
-import org.apache.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/070b5ca7/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
deleted file mode 100644
index e911318..0000000
--- a/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastClusterImpl.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.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/070b5ca7/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
deleted file mode 100644
index 40aa330..0000000
--- a/sandbox/nosql/src/main/java/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 brooklyn.entity.nosql.hazelcast;
-
-import org.apache.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/070b5ca7/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
deleted file mode 100644
index 4e53add..0000000
--- a/sandbox/nosql/src/main/java/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 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/070b5ca7/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
deleted file mode 100644
index 0369934..0000000
--- a/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastNodeImpl.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.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/070b5ca7/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
deleted file mode 100644
index 5527a69..0000000
--- a/sandbox/nosql/src/main/java/brooklyn/entity/nosql/hazelcast/HazelcastNodeSshDriver.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.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/070b5ca7/sandbox/nosql/src/main/java/brooklyn/entity/nosql/infinispan/Infinispan5Driver.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/brooklyn/entity/nosql/infinispan/Infinispan5Driver.java b/sandbox/nosql/src/main/java/brooklyn/entity/nosql/infinispan/Infinispan5Driver.java
deleted file mode 100644
index ebd5fb8..0000000
--- a/sandbox/nosql/src/main/java/brooklyn/entity/nosql/infinispan/Infinispan5Driver.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.nosql.infinispan;
-
-public interface Infinispan5Driver {
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/nosql/src/main/java/brooklyn/entity/nosql/infinispan/Infinispan5Server.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/brooklyn/entity/nosql/infinispan/Infinispan5Server.java b/sandbox/nosql/src/main/java/brooklyn/entity/nosql/infinispan/Infinispan5Server.java
deleted file mode 100644
index e029cf1..0000000
--- a/sandbox/nosql/src/main/java/brooklyn/entity/nosql/infinispan/Infinispan5Server.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.nosql.infinispan;
-
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.Entity;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.SoftwareProcess;
-import brooklyn.entity.basic.SoftwareProcessImpl;
-import brooklyn.entity.java.UsesJmx;
-import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
-import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.SetFromFlag;
-
-/**
- * An {@link brooklyn.entity.Entity} that represents an Infinispan service
- */
-public class Infinispan5Server extends SoftwareProcessImpl implements UsesJmx {
- private static final Logger log = LoggerFactory.getLogger(Infinispan5Server.class);
-
- public static final BasicAttributeSensorAndConfigKey<String> PROTOCOL = new BasicAttributeSensorAndConfigKey<String>(
- String.class, "infinispan.server.protocol",
- "Infinispan protocol (e.g. memcached, hotrod, or websocket)", "memcached");
-
- public static final PortAttributeSensorAndConfigKey PORT = new PortAttributeSensorAndConfigKey(
- "infinispan.server.port", "TCP port number to listen on");
-
- @SetFromFlag("version")
- public static final ConfigKey<String> SUGGESTED_VERSION =
- ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION, "5.0.0.CR8");
-
- // Default filename is "infinispan-${version}-all.zip"
- @SetFromFlag("downloadUrl")
- public static final BasicAttributeSensorAndConfigKey<String> DOWNLOAD_URL = new BasicAttributeSensorAndConfigKey<String>(
- SoftwareProcess.DOWNLOAD_URL, "http://sourceforge.net/projects/infinispan/files/infinispan/${version}/infinispan-${version}-all.zip/download");
-
- public Infinispan5Server() {
- this(MutableMap.of(), null);
- }
- public Infinispan5Server(Map properties) {
- this(properties, null);
- }
- public Infinispan5Server(Entity parent) {
- this(MutableMap.of(), parent);
- }
- public Infinispan5Server(Map properties, Entity parent) {
- super(properties, parent);
- }
-
- @Override
- public Class getDriverInterface() {
- return Infinispan5Driver.class;
- }
-
- @Override
- protected void connectSensors() {
- super.connectSensors();
- super.connectServiceUpIsRunning();
- }
-
- @Override
- protected void disconnectSensors() {
- super.disconnectServiceUpIsRunning();
- super.disconnectSensors();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/nosql/src/main/java/brooklyn/entity/nosql/infinispan/Infinispan5SshDriver.java
----------------------------------------------------------------------
diff --git a/sandbox/nosql/src/main/java/brooklyn/entity/nosql/infinispan/Infinispan5SshDriver.java b/sandbox/nosql/src/main/java/brooklyn/entity/nosql/infinispan/Infinispan5SshDriver.java
deleted file mode 100644
index 361a6ab..0000000
--- a/sandbox/nosql/src/main/java/brooklyn/entity/nosql/infinispan/Infinispan5SshDriver.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.nosql.infinispan;
-
-import static java.lang.String.format;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import brooklyn.entity.java.JavaSoftwareProcessSshDriver;
-import brooklyn.location.Location;
-import brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.net.Networking;
-import brooklyn.util.ssh.BashCommands;
-
-import com.google.common.collect.ImmutableList;
-
-/**
- * Start a {@link TomcatServer} in a {@link Location} accessible over ssh.
- */
-public class Infinispan5SshDriver extends JavaSoftwareProcessSshDriver implements Infinispan5Driver {
-
- public Infinispan5SshDriver(Infinispan5Server entity, SshMachineLocation machine) {
- super(entity, machine);
- }
-
- @Override
- protected String getLogFileLocation() {
- throw new UnsupportedOperationException("Work in progress");
- }
-
- protected String getProtocol() {
- return entity.getAttribute(Infinispan5Server.PROTOCOL);
- }
-
- protected Integer getPort() {
- return entity.getAttribute(Infinispan5Server.PORT);
- }
-
- @Override
- public void install() {
- List<String> urls = resolver.getTargets();
- String saveAs = resolver.getFilename();
-
- List<String> commands = ImmutableList.<String>builder()
- .addAll(BashCommands.commandsToDownloadUrlsAs(urls, saveAs))
- .add(BashCommands.INSTALL_ZIP)
- .add("unzip " + saveAs)
- .build();
-
- newScript(INSTALLING).
- failOnNonZeroResultCode().
- body.append(commands).execute();
- }
-
- @Override
- public void customize() {
- // TODO create and reference a conf.xml? And start with --cache_config <path>
- Map ports = MutableMap.of("port", getPort(), "jmxPort", getJmxPort());
- Networking.checkPortsValid(ports);
-
- newScript(CUSTOMIZING)
- .body.append()
- .execute();
- }
-
- @Override
- public void launch() {
- // FIXME Do we want to redirect stdout/stderr: >> %s/console 2>&1 </dev/null &", getRunDir())
- newScript(MutableMap.of("usePidFile", true), LAUNCHING).
- body.append(
- format("%s/bin/startServer.sh --protocol %s "
- +(getPort() != null ? " --port %s" : "")+" &",
- getExpandedInstallDir(), getProtocol(), getPort()))
- .execute();
- }
-
-
- @Override
- public boolean isRunning() {
- Map flags = MutableMap.of("usePidFile", true);
- return newScript(flags, CHECK_RUNNING).execute() == 0;
- }
-
- @Override
- public void stop() {
- Map flags = MutableMap.of("usePidFile", true);
- newScript(flags, STOPPING).execute();
- }
-
- @Override
- public void kill() {
- Map flags = MutableMap.of("usePidFile", true);
- newScript(flags, KILLING).execute();
- }
-
- @Override
- protected List<String> getCustomJavaConfigOptions() {
- List<String> options = new LinkedList<String>();
- options.addAll(super.getCustomJavaConfigOptions());
- options.add("-Xms200m");
- options.add("-Xmx800m");
- options.add("-XX:MaxPermSize=400m");
- return options;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/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
new file mode 100644
index 0000000..ef4894f
--- /dev/null
+++ b/sandbox/nosql/src/main/java/org/apache/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 org.apache.brooklyn.entity.nosql.hazelcast;
+
+import java.util.List;
+
+import com.google.common.reflect.TypeToken;
+
+import org.apache.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/070b5ca7/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
new file mode 100644
index 0000000..4f837d7
--- /dev/null
+++ b/sandbox/nosql/src/main/java/org/apache/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 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 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/070b5ca7/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
new file mode 100644
index 0000000..8f3521c
--- /dev/null
+++ b/sandbox/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.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/070b5ca7/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
new file mode 100644
index 0000000..e5aa759
--- /dev/null
+++ b/sandbox/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 brooklyn.entity.basic.SoftwareProcessDriver;
+
+public interface HazelcastNodeDriver extends SoftwareProcessDriver {
+
+}
[5/6] incubator-brooklyn git commit: package rename to
org.apache.brooklyn: sandbox
Posted by ha...@apache.org.
package rename to org.apache.brooklyn: 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/070b5ca7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/070b5ca7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/070b5ca7
Branch: refs/heads/master
Commit: 070b5ca7c85ec8819c2208c5fa7802af783edf1e
Parents: 08662a7
Author: Aled Sage <al...@gmail.com>
Authored: Thu Aug 6 11:43:58 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Thu Aug 6 17:17:54 2015 +0100
----------------------------------------------------------------------
.../customsnitch/MultiCloudSnitch.java | 222 ---------
.../customsnitch/MultiCloudSnitch.java | 222 +++++++++
.../brooklyn/entity/database/Database.groovy | 53 ---
.../entity/database/derby/DerbyDatabase.java | 172 -------
.../database/derby/DerbyDatabaseDriver.java | 25 -
.../database/derby/DerbyDatabaseSshDriver.java | 116 -----
.../entity/database/derby/DerbySchema.java | 147 ------
.../brooklyn/entity/database/Database.groovy | 53 +++
.../entity/database/derby/DerbyDatabase.java | 172 +++++++
.../database/derby/DerbyDatabaseDriver.java | 25 +
.../database/derby/DerbyDatabaseSshDriver.java | 116 +++++
.../entity/database/derby/DerbySchema.java | 148 ++++++
.../entity/database/PlaceholderTest.java | 26 --
.../entity/database/PlaceholderTest.java | 26 ++
.../postgresql/PostgreSqlNodeSaltImpl.java | 177 -------
.../brooklyn/entity/salt/SaltBashCommands.java | 92 ----
.../java/brooklyn/entity/salt/SaltConfig.java | 100 ----
.../java/brooklyn/entity/salt/SaltConfigs.java | 89 ----
.../entity/salt/SaltLifecycleEffectorTasks.java | 220 ---------
.../brooklyn/entity/salt/SaltStackMaster.java | 70 ---
.../entity/salt/SaltStackMasterDriver.java | 25 -
.../entity/salt/SaltStackMasterImpl.java | 56 ---
.../entity/salt/SaltStackMasterSshDriver.java | 95 ----
.../java/brooklyn/entity/salt/SaltTasks.java | 145 ------
.../postgresql/PostgreSqlNodeSaltImpl.java | 179 +++++++
.../brooklyn/entity/salt/SaltBashCommands.java | 92 ++++
.../apache/brooklyn/entity/salt/SaltConfig.java | 100 ++++
.../brooklyn/entity/salt/SaltConfigs.java | 89 ++++
.../entity/salt/SaltLifecycleEffectorTasks.java | 220 +++++++++
.../brooklyn/entity/salt/SaltStackMaster.java | 70 +++
.../entity/salt/SaltStackMasterDriver.java | 25 +
.../entity/salt/SaltStackMasterImpl.java | 56 +++
.../entity/salt/SaltStackMasterSshDriver.java | 95 ++++
.../apache/brooklyn/entity/salt/SaltTasks.java | 145 ++++++
.../main/resources/brooklyn/entity/salt/master | 65 ---
.../resources/brooklyn/entity/salt/masterless | 53 ---
.../main/resources/brooklyn/entity/salt/minion | 52 ---
.../org/apache/brooklyn/entity/salt/master | 65 +++
.../org/apache/brooklyn/entity/salt/masterless | 53 +++
.../org/apache/brooklyn/entity/salt/minion | 52 +++
.../postgresql/PostgreSqlSaltLiveTest.java | 109 -----
.../brooklyn/entity/salt/SaltConfigsTest.java | 69 ---
.../entity/salt/SaltLiveTestSupport.java | 68 ---
.../postgresql/PostgreSqlSaltLiveTest.java | 112 +++++
.../brooklyn/entity/salt/SaltConfigsTest.java | 71 +++
.../entity/salt/SaltLiveTestSupport.java | 68 +++
.../entity/monitoring/zabbix/ZabbixFeed.java | 463 -------------------
.../monitoring/zabbix/ZabbixMonitored.java | 38 --
.../monitoring/zabbix/ZabbixPollConfig.java | 75 ---
.../entity/monitoring/zabbix/ZabbixServer.java | 52 ---
.../monitoring/zabbix/ZabbixServerImpl.java | 143 ------
.../entity/monitoring/zabbix/ZabbixFeed.java | 463 +++++++++++++++++++
.../monitoring/zabbix/ZabbixMonitored.java | 38 ++
.../monitoring/zabbix/ZabbixPollConfig.java | 75 +++
.../entity/monitoring/zabbix/ZabbixServer.java | 52 +++
.../monitoring/zabbix/ZabbixServerImpl.java | 143 ++++++
sandbox/nosql/pom.xml | 2 +-
.../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/infinispan/Infinispan5Driver.java | 23 -
.../nosql/infinispan/Infinispan5Server.java | 88 ----
.../nosql/infinispan/Infinispan5SshDriver.java | 124 -----
.../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/infinispan/Infinispan5Driver.java | 23 +
.../nosql/infinispan/Infinispan5Server.java | 88 ++++
.../nosql/infinispan/Infinispan5SshDriver.java | 124 +++++
.../nosql/hazelcast/hazelcast-brooklyn.xml | 65 ---
.../nosql/hazelcast/hazelcast-brooklyn.xml | 65 +++
.../hazelcast/HazelcastClusterEc2LiveTest.java | 71 ---
.../HazelcastClusterSoftlayerLiveTest.java | 71 ---
.../Infinispan5ServerIntegrationTest.groovy | 102 ----
.../hazelcast/HazelcastClusterEc2LiveTest.java | 73 +++
.../HazelcastClusterSoftlayerLiveTest.java | 73 +++
.../Infinispan5ServerIntegrationTest.groovy | 103 +++++
83 files changed, 4187 insertions(+), 4174 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/cassandra-multicloud-snitch/src/main/java/brooklyn/entity/nosql/cassandra/customsnitch/MultiCloudSnitch.java
----------------------------------------------------------------------
diff --git a/sandbox/cassandra-multicloud-snitch/src/main/java/brooklyn/entity/nosql/cassandra/customsnitch/MultiCloudSnitch.java b/sandbox/cassandra-multicloud-snitch/src/main/java/brooklyn/entity/nosql/cassandra/customsnitch/MultiCloudSnitch.java
deleted file mode 100644
index ada56e2..0000000
--- a/sandbox/cassandra-multicloud-snitch/src/main/java/brooklyn/entity/nosql/cassandra/customsnitch/MultiCloudSnitch.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.nosql.cassandra.customsnitch;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.InputStream;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.HashMap;
-import java.util.Properties;
-
-import org.apache.cassandra.exceptions.ConfigurationException;
-import org.apache.cassandra.gms.ApplicationState;
-import org.apache.cassandra.gms.EndpointState;
-import org.apache.cassandra.gms.Gossiper;
-import org.apache.cassandra.gms.IEndpointStateChangeSubscriber;
-import org.apache.cassandra.gms.VersionedValue;
-import org.apache.cassandra.io.util.FileUtils;
-import org.apache.cassandra.locator.AbstractNetworkTopologySnitch;
-import org.apache.cassandra.net.MessagingService;
-import org.apache.cassandra.service.StorageService;
-import org.apache.cassandra.utils.FBUtilities;
-import org.apache.cassandra.utils.ResourceWatcher;
-import org.apache.cassandra.utils.WrappedRunnable;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A snitch that can be configured to work across clouds. It uses and
- * extends the cassandra-rackdc.properties (which is used by the
- * GossipingPropertyFileSnitch) to add a publicip and privateip
- * configuration.
- * <p>
- * The code is very similar to Ec2MultiRegionSnitch, except that it uses
- * the the config file rather than querying EC2 to get the IPs.
- * <p>
- * If two nodes are in the same datacenter, they will attempt to communicate
- * using the privateip. If they are in different datacenters, they will use
- * the publicip.
- */
-public class MultiCloudSnitch extends AbstractNetworkTopologySnitch implements IEndpointStateChangeSubscriber
-{
- // FIXME Need to submit a pull request to Cassandra (1.2.x branch) for this snitch.
- // Or could enhance GossipingPropertyFileSnitch instead, and submit PR for that.
-
- protected static final Logger logger = LoggerFactory.getLogger(MultiCloudSnitch.class);
-
- public static final String SNITCH_PROPERTIES_FILENAME = "cassandra-rackdc.properties";
-
- private static final String DEFAULT_DC = "UNKNOWN-DC";
- private static final String DEFAULT_RACK = "UNKNOWN-RACK";
-
- protected String rack;
- protected String datacenter;
- protected InetAddress public_ip;
- protected String private_ip;
-
- private volatile boolean gossipStarted;
-
- public MultiCloudSnitch() throws ConfigurationException
- {
- reloadConfiguration();
- logger.info("CustomSnitch using datacenter: " + datacenter + ", rack: " + rack + ", publicip: " + public_ip + ", privateip: " + private_ip);
-
- try
- {
- FBUtilities.resourceToFile(SNITCH_PROPERTIES_FILENAME);
- Runnable runnable = new WrappedRunnable()
- {
- protected void runMayThrow() throws ConfigurationException
- {
- reloadConfiguration();
- }
- };
- ResourceWatcher.watch(SNITCH_PROPERTIES_FILENAME, runnable, 60 * 1000);
- }
- catch (ConfigurationException ex)
- {
- logger.debug(SNITCH_PROPERTIES_FILENAME + " found, but does not look like a plain file. Will not watch it for changes");
- }
- }
-
- public void reloadConfiguration() throws ConfigurationException
- {
- HashMap<InetAddress, String[]> reloadedMap = new HashMap<InetAddress, String[]>();
- String DC_PROPERTY = "dc";
- String RACK_PROPERTY = "rack";
- String PUBLIC_IP_PROPERTY = "publicip";
- String PRIVATE_IP_PROPERTY = "privateip";
-
- Properties properties = new Properties();
- InputStream stream = null;
- try
- {
- stream = getClass().getClassLoader().getResourceAsStream(SNITCH_PROPERTIES_FILENAME);
- properties.load(stream);
- }
- catch (Exception e)
- {
- throw new ConfigurationException("Unable to read " + SNITCH_PROPERTIES_FILENAME, e);
- }
- finally
- {
- FileUtils.closeQuietly(stream);
- }
-
- datacenter = properties.getProperty(DC_PROPERTY);
- rack = properties.getProperty(RACK_PROPERTY);
- private_ip = checkNotNull(properties.getProperty(PRIVATE_IP_PROPERTY), "%s in %s", PRIVATE_IP_PROPERTY, SNITCH_PROPERTIES_FILENAME);
- String public_ip_str = checkNotNull(properties.getProperty(PUBLIC_IP_PROPERTY), "%s in %s", PUBLIC_IP_PROPERTY, SNITCH_PROPERTIES_FILENAME);
- try {
- public_ip = InetAddress.getByName(public_ip_str);
- }
- catch (UnknownHostException e)
- {
- throw new ConfigurationException("Unknown host " + public_ip_str, e);
- }
-
- logger.debug("CustomSnitch reloaded, using datacenter: " + datacenter + ", rack: " + rack + ", publicip: " + public_ip + ", privateip: " + private_ip);
-
- if (StorageService.instance != null) // null check tolerates circular dependency; see CASSANDRA-4145
- StorageService.instance.getTokenMetadata().invalidateCaches();
-
- if (gossipStarted)
- StorageService.instance.gossipSnitchInfo();
- }
-
-
- public String getRack(InetAddress endpoint)
- {
- if (endpoint.equals(FBUtilities.getBroadcastAddress()))
- return rack;
- EndpointState state = Gossiper.instance.getEndpointStateForEndpoint(endpoint);
- if (state == null || state.getApplicationState(ApplicationState.RACK) == null)
- return DEFAULT_RACK;
- return state.getApplicationState(ApplicationState.RACK).value;
- }
-
- public String getDatacenter(InetAddress endpoint)
- {
- if (endpoint.equals(FBUtilities.getBroadcastAddress()))
- return datacenter;
- EndpointState state = Gossiper.instance.getEndpointStateForEndpoint(endpoint);
- if (state == null || state.getApplicationState(ApplicationState.DC) == null)
- return DEFAULT_DC;
- return state.getApplicationState(ApplicationState.DC).value;
- }
-
- public void onJoin(InetAddress endpoint, EndpointState epState)
- {
- if (epState.getApplicationState(ApplicationState.INTERNAL_IP) != null)
- reConnect(endpoint, epState.getApplicationState(ApplicationState.INTERNAL_IP));
- }
-
- public void onChange(InetAddress endpoint, ApplicationState state, VersionedValue value)
- {
- if (state == ApplicationState.INTERNAL_IP)
- reConnect(endpoint, value);
- }
-
- public void onAlive(InetAddress endpoint, EndpointState state)
- {
- if (state.getApplicationState(ApplicationState.INTERNAL_IP) != null)
- reConnect(endpoint, state.getApplicationState(ApplicationState.INTERNAL_IP));
- }
-
- public void onDead(InetAddress endpoint, EndpointState state)
- {
- // do nothing
- }
-
- public void onRestart(InetAddress endpoint, EndpointState state)
- {
- // do nothing
- }
-
- public void onRemove(InetAddress endpoint)
- {
- // do nothing.
- }
-
- private void reConnect(InetAddress endpoint, VersionedValue versionedValue)
- {
- if (!getDatacenter(endpoint).equals(getDatacenter(public_ip)))
- return; // do nothing return back...
-
- try
- {
- InetAddress remoteIP = InetAddress.getByName(versionedValue.value);
- MessagingService.instance().getConnectionPool(endpoint).reset(remoteIP);
- logger.debug(String.format("Intiated reconnect to an Internal IP %s for the %s", remoteIP, endpoint));
- } catch (UnknownHostException e)
- {
- logger.error("Error in getting the IP address resolved: ", e);
- }
- }
-
- @Override
- public void gossiperStarting()
- {
- super.gossiperStarting();
- Gossiper.instance.addLocalApplicationState(ApplicationState.INTERNAL_IP, StorageService.instance.valueFactory.internalIP(private_ip));
- Gossiper.instance.register(this);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/cassandra-multicloud-snitch/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/customsnitch/MultiCloudSnitch.java
----------------------------------------------------------------------
diff --git a/sandbox/cassandra-multicloud-snitch/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/customsnitch/MultiCloudSnitch.java b/sandbox/cassandra-multicloud-snitch/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/customsnitch/MultiCloudSnitch.java
new file mode 100644
index 0000000..0199290
--- /dev/null
+++ b/sandbox/cassandra-multicloud-snitch/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/customsnitch/MultiCloudSnitch.java
@@ -0,0 +1,222 @@
+/*
+ * 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.cassandra.customsnitch;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Properties;
+
+import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.gms.ApplicationState;
+import org.apache.cassandra.gms.EndpointState;
+import org.apache.cassandra.gms.Gossiper;
+import org.apache.cassandra.gms.IEndpointStateChangeSubscriber;
+import org.apache.cassandra.gms.VersionedValue;
+import org.apache.cassandra.io.util.FileUtils;
+import org.apache.cassandra.locator.AbstractNetworkTopologySnitch;
+import org.apache.cassandra.net.MessagingService;
+import org.apache.cassandra.service.StorageService;
+import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.ResourceWatcher;
+import org.apache.cassandra.utils.WrappedRunnable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A snitch that can be configured to work across clouds. It uses and
+ * extends the cassandra-rackdc.properties (which is used by the
+ * GossipingPropertyFileSnitch) to add a publicip and privateip
+ * configuration.
+ * <p>
+ * The code is very similar to Ec2MultiRegionSnitch, except that it uses
+ * the the config file rather than querying EC2 to get the IPs.
+ * <p>
+ * If two nodes are in the same datacenter, they will attempt to communicate
+ * using the privateip. If they are in different datacenters, they will use
+ * the publicip.
+ */
+public class MultiCloudSnitch extends AbstractNetworkTopologySnitch implements IEndpointStateChangeSubscriber
+{
+ // FIXME Need to submit a pull request to Cassandra (1.2.x branch) for this snitch.
+ // Or could enhance GossipingPropertyFileSnitch instead, and submit PR for that.
+
+ protected static final Logger logger = LoggerFactory.getLogger(MultiCloudSnitch.class);
+
+ public static final String SNITCH_PROPERTIES_FILENAME = "cassandra-rackdc.properties";
+
+ private static final String DEFAULT_DC = "UNKNOWN-DC";
+ private static final String DEFAULT_RACK = "UNKNOWN-RACK";
+
+ protected String rack;
+ protected String datacenter;
+ protected InetAddress public_ip;
+ protected String private_ip;
+
+ private volatile boolean gossipStarted;
+
+ public MultiCloudSnitch() throws ConfigurationException
+ {
+ reloadConfiguration();
+ logger.info("CustomSnitch using datacenter: " + datacenter + ", rack: " + rack + ", publicip: " + public_ip + ", privateip: " + private_ip);
+
+ try
+ {
+ FBUtilities.resourceToFile(SNITCH_PROPERTIES_FILENAME);
+ Runnable runnable = new WrappedRunnable()
+ {
+ protected void runMayThrow() throws ConfigurationException
+ {
+ reloadConfiguration();
+ }
+ };
+ ResourceWatcher.watch(SNITCH_PROPERTIES_FILENAME, runnable, 60 * 1000);
+ }
+ catch (ConfigurationException ex)
+ {
+ logger.debug(SNITCH_PROPERTIES_FILENAME + " found, but does not look like a plain file. Will not watch it for changes");
+ }
+ }
+
+ public void reloadConfiguration() throws ConfigurationException
+ {
+ HashMap<InetAddress, String[]> reloadedMap = new HashMap<InetAddress, String[]>();
+ String DC_PROPERTY = "dc";
+ String RACK_PROPERTY = "rack";
+ String PUBLIC_IP_PROPERTY = "publicip";
+ String PRIVATE_IP_PROPERTY = "privateip";
+
+ Properties properties = new Properties();
+ InputStream stream = null;
+ try
+ {
+ stream = getClass().getClassLoader().getResourceAsStream(SNITCH_PROPERTIES_FILENAME);
+ properties.load(stream);
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationException("Unable to read " + SNITCH_PROPERTIES_FILENAME, e);
+ }
+ finally
+ {
+ FileUtils.closeQuietly(stream);
+ }
+
+ datacenter = properties.getProperty(DC_PROPERTY);
+ rack = properties.getProperty(RACK_PROPERTY);
+ private_ip = checkNotNull(properties.getProperty(PRIVATE_IP_PROPERTY), "%s in %s", PRIVATE_IP_PROPERTY, SNITCH_PROPERTIES_FILENAME);
+ String public_ip_str = checkNotNull(properties.getProperty(PUBLIC_IP_PROPERTY), "%s in %s", PUBLIC_IP_PROPERTY, SNITCH_PROPERTIES_FILENAME);
+ try {
+ public_ip = InetAddress.getByName(public_ip_str);
+ }
+ catch (UnknownHostException e)
+ {
+ throw new ConfigurationException("Unknown host " + public_ip_str, e);
+ }
+
+ logger.debug("CustomSnitch reloaded, using datacenter: " + datacenter + ", rack: " + rack + ", publicip: " + public_ip + ", privateip: " + private_ip);
+
+ if (StorageService.instance != null) // null check tolerates circular dependency; see CASSANDRA-4145
+ StorageService.instance.getTokenMetadata().invalidateCaches();
+
+ if (gossipStarted)
+ StorageService.instance.gossipSnitchInfo();
+ }
+
+
+ public String getRack(InetAddress endpoint)
+ {
+ if (endpoint.equals(FBUtilities.getBroadcastAddress()))
+ return rack;
+ EndpointState state = Gossiper.instance.getEndpointStateForEndpoint(endpoint);
+ if (state == null || state.getApplicationState(ApplicationState.RACK) == null)
+ return DEFAULT_RACK;
+ return state.getApplicationState(ApplicationState.RACK).value;
+ }
+
+ public String getDatacenter(InetAddress endpoint)
+ {
+ if (endpoint.equals(FBUtilities.getBroadcastAddress()))
+ return datacenter;
+ EndpointState state = Gossiper.instance.getEndpointStateForEndpoint(endpoint);
+ if (state == null || state.getApplicationState(ApplicationState.DC) == null)
+ return DEFAULT_DC;
+ return state.getApplicationState(ApplicationState.DC).value;
+ }
+
+ public void onJoin(InetAddress endpoint, EndpointState epState)
+ {
+ if (epState.getApplicationState(ApplicationState.INTERNAL_IP) != null)
+ reConnect(endpoint, epState.getApplicationState(ApplicationState.INTERNAL_IP));
+ }
+
+ public void onChange(InetAddress endpoint, ApplicationState state, VersionedValue value)
+ {
+ if (state == ApplicationState.INTERNAL_IP)
+ reConnect(endpoint, value);
+ }
+
+ public void onAlive(InetAddress endpoint, EndpointState state)
+ {
+ if (state.getApplicationState(ApplicationState.INTERNAL_IP) != null)
+ reConnect(endpoint, state.getApplicationState(ApplicationState.INTERNAL_IP));
+ }
+
+ public void onDead(InetAddress endpoint, EndpointState state)
+ {
+ // do nothing
+ }
+
+ public void onRestart(InetAddress endpoint, EndpointState state)
+ {
+ // do nothing
+ }
+
+ public void onRemove(InetAddress endpoint)
+ {
+ // do nothing.
+ }
+
+ private void reConnect(InetAddress endpoint, VersionedValue versionedValue)
+ {
+ if (!getDatacenter(endpoint).equals(getDatacenter(public_ip)))
+ return; // do nothing return back...
+
+ try
+ {
+ InetAddress remoteIP = InetAddress.getByName(versionedValue.value);
+ MessagingService.instance().getConnectionPool(endpoint).reset(remoteIP);
+ logger.debug(String.format("Intiated reconnect to an Internal IP %s for the %s", remoteIP, endpoint));
+ } catch (UnknownHostException e)
+ {
+ logger.error("Error in getting the IP address resolved: ", e);
+ }
+ }
+
+ @Override
+ public void gossiperStarting()
+ {
+ super.gossiperStarting();
+ Gossiper.instance.addLocalApplicationState(ApplicationState.INTERNAL_IP, StorageService.instance.valueFactory.internalIP(private_ip));
+ Gossiper.instance.register(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/database/src/main/java/brooklyn/entity/database/Database.groovy
----------------------------------------------------------------------
diff --git a/sandbox/database/src/main/java/brooklyn/entity/database/Database.groovy b/sandbox/database/src/main/java/brooklyn/entity/database/Database.groovy
deleted file mode 100644
index a86c862..0000000
--- a/sandbox/database/src/main/java/brooklyn/entity/database/Database.groovy
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.database
-
-import brooklyn.event.basic.BasicConfigKey
-
-/**
- * Intended to represent a SQL relational database service.
- *
- * TODO work in progress
- */
-public interface Database {
- BasicConfigKey<String> SQL_VERSION = [ String, "database.sql.version", "SQL version" ]
-
- Collection<Schema> getSchemas();
-
- void createSchema(String name, Map properties);
-
- void addSchema(Schema schema);
-
- void removeSchema(String schemaName);
-}
-
-/**
- * Intended to represent a SQL database schema.
- *
- * TODO work in progress
- */
-public interface Schema {
- BasicConfigKey<String> SCHEMA_NAME = [ String, "database.schema", "Database schema name" ]
-
- void create();
-
- void remove();
-
- String getName();
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/database/src/main/java/brooklyn/entity/database/derby/DerbyDatabase.java
----------------------------------------------------------------------
diff --git a/sandbox/database/src/main/java/brooklyn/entity/database/derby/DerbyDatabase.java b/sandbox/database/src/main/java/brooklyn/entity/database/derby/DerbyDatabase.java
deleted file mode 100644
index aad881f..0000000
--- a/sandbox/database/src/main/java/brooklyn/entity/database/derby/DerbyDatabase.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.database.derby;
-
-import java.util.Collection;
-import java.util.Map;
-
-import javax.management.ObjectName;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.Entity;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.SoftwareProcess;
-import brooklyn.entity.basic.SoftwareProcessImpl;
-import brooklyn.entity.database.Database;
-import brooklyn.entity.database.Schema;
-import brooklyn.entity.java.UsesJava;
-import brooklyn.entity.java.UsesJmx;
-import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
-import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
-import brooklyn.event.feed.jmx.JmxHelper;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.SetFromFlag;
-
-import com.google.common.base.Objects.ToStringHelper;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-/**
- * An {@link Entity} that represents a single Derby SQL database server instance.
- *
- * TODO work in progress
- */
-public class DerbyDatabase extends SoftwareProcessImpl implements Database, UsesJava, UsesJmx {
- private static final Logger log = LoggerFactory.getLogger(DerbyDatabase.class);
-
- @SetFromFlag("version")
- public static final ConfigKey<String> SUGGESTED_VERSION =
- ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION, "10.8.1.2");
-
- public static final PortAttributeSensorAndConfigKey JDBC_PORT = new PortAttributeSensorAndConfigKey(
- "derby.jdbcPort", "Suggested JDBC port");
-
- public static final ConfigKey<String> VIRTUAL_HOST_NAME = new BasicConfigKey<String>(
- String.class, "derby.virtualHost", "Derby virtual host name", "localhost");
-
- public static final BasicAttributeSensorAndConfigKey<String> JMX_USER = new BasicAttributeSensorAndConfigKey<String>(
- UsesJmx.JMX_USER, "admin");
-
- public static final BasicAttributeSensorAndConfigKey<String> JMX_PASSWORD = new BasicAttributeSensorAndConfigKey<String>(
- UsesJmx.JMX_PASSWORD, "admin");
-
- @SetFromFlag
- protected Collection<String> schemaNames;
-
- @SetFromFlag
- protected Map<String, DerbySchema> schemas;
-
- protected transient JmxHelper jmxHelper;
-
- public DerbyDatabase() {
- this(MutableMap.of(), null);
- }
- public DerbyDatabase(Map properties) {
- this(properties, null);
- }
- public DerbyDatabase(Entity parent) {
- this(MutableMap.of(), parent);
- }
- public DerbyDatabase(Map properties, Entity parent) {
- super(properties, parent);
-
- if (schemaNames == null) schemaNames = Lists.newArrayList();
- if (schemas == null) schemas = Maps.newLinkedHashMap();
- }
-
- @Override
- public Class<? extends DerbyDatabaseDriver> getDriverInterface() {
- return DerbyDatabaseDriver.class;
- }
-
- @Override
- public void connectSensors() {
- super.connectSensors();
- connectServiceUpIsRunning();
- }
-
- @Override
- public void disconnectSensors() {
- super.disconnectSensors();
- disconnectServiceUpIsRunning();
- }
-
- @Override
- public void postStart() {
- super.postStart();
- for (String name : schemaNames) {
- createSchema(name);
- }
- }
-
- @Override
- public void preStop() {
- super.preStop();
- for (DerbySchema schema : schemas.values()) {
- schema.destroy();
- }
- if (jmxHelper != null) jmxHelper.terminate();
- }
-
- public void createSchema(String name) {
- createSchema(name, ImmutableMap.of());
- }
-
- public void createSchema(String name, Map properties) {
- Map allprops = MutableMap.builder().putAll(properties).put("name", name).build();
- DerbySchema schema = new DerbySchema(allprops);
- schema.init();
- schema.create();
- schemas.put(name, schema);
- }
-
- public Collection<Schema> getSchemas() {
- return ImmutableList.<Schema>copyOf(schemas.values());
- }
-
- public void addSchema(Schema schema) {
- schemas.put(schema.getName(), (DerbySchema) schema);
- }
-
- public void removeSchema(String schemaName) {
- schemas.remove(schemaName);
- }
-
- @Override
- protected ToStringHelper toStringHelper() {
- return super.toStringHelper().add("jdbcPort", getAttribute(JDBC_PORT));
- }
-
- protected boolean computeNodeUp() {
- // FIXME Use the JmxAdapter.reachable() stuff instead of getAttribute
- try {
- ObjectName serverInfoObjectName = ObjectName.getInstance("org.apache.derby:type=ServerInformation,name=ServerInformation");
- String productVersion = (String) jmxHelper.getAttribute(serverInfoObjectName, "ProductVersion");
- return (productVersion != null);
- } catch (Exception e) {
- return false;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/database/src/main/java/brooklyn/entity/database/derby/DerbyDatabaseDriver.java
----------------------------------------------------------------------
diff --git a/sandbox/database/src/main/java/brooklyn/entity/database/derby/DerbyDatabaseDriver.java b/sandbox/database/src/main/java/brooklyn/entity/database/derby/DerbyDatabaseDriver.java
deleted file mode 100644
index ed76e78..0000000
--- a/sandbox/database/src/main/java/brooklyn/entity/database/derby/DerbyDatabaseDriver.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 brooklyn.entity.database.derby;
-
-import brooklyn.entity.java.JavaSoftwareProcessDriver;
-
-public interface DerbyDatabaseDriver extends JavaSoftwareProcessDriver {
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/database/src/main/java/brooklyn/entity/database/derby/DerbyDatabaseSshDriver.java
----------------------------------------------------------------------
diff --git a/sandbox/database/src/main/java/brooklyn/entity/database/derby/DerbyDatabaseSshDriver.java b/sandbox/database/src/main/java/brooklyn/entity/database/derby/DerbyDatabaseSshDriver.java
deleted file mode 100644
index 172f823..0000000
--- a/sandbox/database/src/main/java/brooklyn/entity/database/derby/DerbyDatabaseSshDriver.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.database.derby;
-
-import static java.lang.String.format;
-
-import java.util.List;
-import java.util.Map;
-
-import brooklyn.entity.java.JavaSoftwareProcessSshDriver;
-import brooklyn.location.Location;
-import brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.ssh.BashCommands;
-
-import com.google.common.collect.ImmutableList;
-
-/**
- * Start a {@link DerbyDatabase} in a {@link Location} accessible over ssh.
- *
- * TODO work in progress
- */
-public class DerbyDatabaseSshDriver extends JavaSoftwareProcessSshDriver implements DerbyDatabaseDriver {
-
- // TOD Previous comment said "JMX is configured using command line switch"; how should that be set here?
-
- public DerbyDatabaseSshDriver(DerbyDatabase entity, SshMachineLocation machine) {
- super(entity, machine);
- }
-
- public String getPidFile() { return "derby.pid"; }
-
- @Override
- protected String getLogFileLocation() {
- throw new UnsupportedOperationException("Work in progress");
- }
-
- @Override
- public void install() {
- String url = format("http://www.mirrorservice.org/sites/ftp.apache.org/db/derby/db-derby-%s/db-derby-%s-lib.tar.gz", getVersion(), getVersion());
- String saveAs = format("db-derby-%s-lib.tar.gz", getVersion());
-
- List<String> commands = ImmutableList.<String>builder()
- .add(BashCommands.commandToDownloadUrlAs(url, saveAs))
- .add(BashCommands.INSTALL_TAR)
- .add("tar xzfv " + saveAs)
- .build();
-
- newScript(INSTALLING)
- .failOnNonZeroResultCode()
- .body.append(commands).execute();
- }
-
- @Override
- public void customize() {
- newScript(CUSTOMIZING)
- .failOnNonZeroResultCode()
- .body.append(
- format("cp -R %s/derby-broker-%s/{bin,etc,lib} .", getInstallDir(), getVersion()),
- "make install PREFIX="+getRunDir())
- .execute();
- }
-
- @Override
- public void launch() {
- // TODO Should we redirect stdout/stderr: format(" >> %s/console 2>&1 </dev/null &", getRunDir())
- newScript(MutableMap.of("usePidFile", getPidFile()), LAUNCHING)
- .failOnNonZeroResultCode()
- .body.append("nohup ./bin/derby &")
- .execute();
- }
-
-
- @Override
- public boolean isRunning() {
- return newScript(MutableMap.of("usePidFile", getPidFile()), CHECK_RUNNING)
- .execute() == 0;
- }
-
- /**
- * Restarts redis with the current configuration.
- */
- @Override
- public void stop() {
- newScript(MutableMap.of("usePidFile", getPidFile()), STOPPING)
- .execute();
- }
-
- @Override
- public Map<String, String> getShellEnvironment() {
- Map<String, String> orig = super.getShellEnvironment();
-
- return MutableMap.<String, String>builder()
- .putAll(orig)
- .put("DERBY_HOME", getRunDir())
- .put("DERBY_WORK", getRunDir())
- .putIfNotNull("DERBY_OPTS", orig.get("JAVA_OPTS"))
- .build();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/database/src/main/java/brooklyn/entity/database/derby/DerbySchema.java
----------------------------------------------------------------------
diff --git a/sandbox/database/src/main/java/brooklyn/entity/database/derby/DerbySchema.java b/sandbox/database/src/main/java/brooklyn/entity/database/derby/DerbySchema.java
deleted file mode 100644
index 9ea26b5..0000000
--- a/sandbox/database/src/main/java/brooklyn/entity/database/derby/DerbySchema.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 brooklyn.entity.database.derby;
-
-import static java.lang.String.format;
-
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-import javax.management.ObjectName;
-
-import brooklyn.entity.Entity;
-import brooklyn.entity.basic.AbstractEntity;
-import brooklyn.entity.basic.EntityLocal;
-import brooklyn.entity.database.Schema;
-import brooklyn.entity.java.UsesJmx;
-import brooklyn.event.AttributeSensor;
-import brooklyn.event.basic.BasicAttributeSensor;
-import brooklyn.event.feed.jmx.JmxAttributePollConfig;
-import brooklyn.event.feed.jmx.JmxFeed;
-import brooklyn.event.feed.jmx.JmxHelper;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.SetFromFlag;
-
-import com.google.common.base.Objects.ToStringHelper;
-
-public class DerbySchema extends AbstractEntity implements Schema {
-
- // FIXME Needs reviewed and implemented properly; while fixing compilation errors
- // I added enough for it to look mostly plausible but it's completely untested.
- // And I have not looked up the derby docs to check that the attributes etc are valid.
-
- // TODO Somehow share jmx connection with DerbyDatabase instance
-
- // TODO Declare effectors
-
- public static AttributeSensor<Integer> SCHEMA_DEPTH = new BasicAttributeSensor<Integer>(
- Integer.class, "derby.schema.depth", "schema depth");
-
- public static AttributeSensor<Integer> MESSAGE_COUNT = new BasicAttributeSensor<Integer>(
- Integer.class, "derby.schema.messageCount", "message count");
-
- @SetFromFlag(defaultVal="localhost")
- String virtualHost;
-
- @SetFromFlag(nullable=false)
- String name;
-
- protected ObjectName virtualHostManager;
- protected ObjectName exchange;
-
- transient JmxHelper jmxHelper;
- transient JmxFeed jmxFeed;
-
- public DerbySchema() {
- super(MutableMap.of(), null);
- }
- public DerbySchema(Map properties) {
- super(properties, null);
- }
- public DerbySchema(Entity parent) {
- this(MutableMap.of(), parent);
- }
- public DerbySchema(Map properties, Entity parent) {
- super(properties, parent);
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public DerbyDatabase getParent() {
- return (DerbyDatabase) super.getParent();
- }
-
- /**
- * Return the JDBC connection URL for the schema.
- */
- public String getConnectionUrl() { return String.format("jdbc:derby:%s", name); }
-
- public void init() {
- try {
- virtualHostManager = new ObjectName(format("org.apache.derby:type=VirtualHost.VirtualHostManager,VirtualHost=\"%s\"", virtualHost));
- exchange = new ObjectName(format("org.apache.derby:type=VirtualHost.Exchange,VirtualHost=\"%s\",name=\"amq.direct\",ExchangeType=direct", virtualHost));
- create();
-
- jmxHelper = new JmxHelper((EntityLocal)getParent());
-
- ObjectName schemaMBeanName = new ObjectName(format("org.apache.derby:type=VirtualHost.Schema,VirtualHost=\"%s\",name=\"%s\"", virtualHost, name));
-
- jmxFeed = JmxFeed.builder()
- .entity(this)
- .helper(jmxHelper)
- .period(500, TimeUnit.MILLISECONDS)
- .pollAttribute(new JmxAttributePollConfig<Integer>(SCHEMA_DEPTH)
- .objectName(schemaMBeanName)
- .attributeName("SchemaDepth"))
- .pollAttribute(new JmxAttributePollConfig<Integer>(MESSAGE_COUNT)
- .objectName(schemaMBeanName)
- .attributeName("MessageCount"))
- .build();
-
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- }
-
- public void create() {
- jmxHelper.operation(virtualHostManager, "createNewSchema", name, getParent().getAttribute(UsesJmx.JMX_USER), true);
- jmxHelper.operation(exchange, "createNewBinding", name, name);
- }
-
- public void remove() {
- jmxHelper.operation(exchange, "removeBinding", name, name);
- jmxHelper.operation(virtualHostManager, "deleteSchema", name);
- }
-
- @Override
- public void destroy() {
- if (jmxFeed != null) jmxFeed.stop();
- super.destroy();
- }
-
- @Override
- protected ToStringHelper toStringHelper() {
- return super.toStringHelper().add("name", name);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/Database.groovy
----------------------------------------------------------------------
diff --git a/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/Database.groovy b/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/Database.groovy
new file mode 100644
index 0000000..5118dd0
--- /dev/null
+++ b/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/Database.groovy
@@ -0,0 +1,53 @@
+/*
+ * 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.database
+
+import brooklyn.event.basic.BasicConfigKey
+
+/**
+ * Intended to represent a SQL relational database service.
+ *
+ * TODO work in progress
+ */
+public interface Database {
+ BasicConfigKey<String> SQL_VERSION = [ String, "database.sql.version", "SQL version" ]
+
+ Collection<Schema> getSchemas();
+
+ void createSchema(String name, Map properties);
+
+ void addSchema(Schema schema);
+
+ void removeSchema(String schemaName);
+}
+
+/**
+ * Intended to represent a SQL database schema.
+ *
+ * TODO work in progress
+ */
+public interface Schema {
+ BasicConfigKey<String> SCHEMA_NAME = [ String, "database.schema", "Database schema name" ]
+
+ void create();
+
+ void remove();
+
+ String getName();
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbyDatabase.java
----------------------------------------------------------------------
diff --git a/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbyDatabase.java b/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbyDatabase.java
new file mode 100644
index 0000000..00b0ab2
--- /dev/null
+++ b/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbyDatabase.java
@@ -0,0 +1,172 @@
+/*
+ * 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.database.derby;
+
+import java.util.Collection;
+import java.util.Map;
+
+import javax.management.ObjectName;
+
+import org.apache.brooklyn.entity.database.Database;
+import org.apache.brooklyn.entity.database.Schema;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.basic.SoftwareProcessImpl;
+import brooklyn.entity.java.UsesJava;
+import brooklyn.entity.java.UsesJmx;
+import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
+import brooklyn.event.basic.BasicConfigKey;
+import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
+import brooklyn.event.feed.jmx.JmxHelper;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.flags.SetFromFlag;
+
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+/**
+ * An {@link Entity} that represents a single Derby SQL database server instance.
+ *
+ * TODO work in progress
+ */
+public class DerbyDatabase extends SoftwareProcessImpl implements Database, UsesJava, UsesJmx {
+ private static final Logger log = LoggerFactory.getLogger(DerbyDatabase.class);
+
+ @SetFromFlag("version")
+ public static final ConfigKey<String> SUGGESTED_VERSION =
+ ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION, "10.8.1.2");
+
+ public static final PortAttributeSensorAndConfigKey JDBC_PORT = new PortAttributeSensorAndConfigKey(
+ "derby.jdbcPort", "Suggested JDBC port");
+
+ public static final ConfigKey<String> VIRTUAL_HOST_NAME = new BasicConfigKey<String>(
+ String.class, "derby.virtualHost", "Derby virtual host name", "localhost");
+
+ public static final BasicAttributeSensorAndConfigKey<String> JMX_USER = new BasicAttributeSensorAndConfigKey<String>(
+ UsesJmx.JMX_USER, "admin");
+
+ public static final BasicAttributeSensorAndConfigKey<String> JMX_PASSWORD = new BasicAttributeSensorAndConfigKey<String>(
+ UsesJmx.JMX_PASSWORD, "admin");
+
+ @SetFromFlag
+ protected Collection<String> schemaNames;
+
+ @SetFromFlag
+ protected Map<String, DerbySchema> schemas;
+
+ protected transient JmxHelper jmxHelper;
+
+ public DerbyDatabase() {
+ this(MutableMap.of(), null);
+ }
+ public DerbyDatabase(Map properties) {
+ this(properties, null);
+ }
+ public DerbyDatabase(Entity parent) {
+ this(MutableMap.of(), parent);
+ }
+ public DerbyDatabase(Map properties, Entity parent) {
+ super(properties, parent);
+
+ if (schemaNames == null) schemaNames = Lists.newArrayList();
+ if (schemas == null) schemas = Maps.newLinkedHashMap();
+ }
+
+ @Override
+ public Class<? extends DerbyDatabaseDriver> getDriverInterface() {
+ return DerbyDatabaseDriver.class;
+ }
+
+ @Override
+ public void connectSensors() {
+ super.connectSensors();
+ connectServiceUpIsRunning();
+ }
+
+ @Override
+ public void disconnectSensors() {
+ super.disconnectSensors();
+ disconnectServiceUpIsRunning();
+ }
+
+ @Override
+ public void postStart() {
+ super.postStart();
+ for (String name : schemaNames) {
+ createSchema(name);
+ }
+ }
+
+ @Override
+ public void preStop() {
+ super.preStop();
+ for (DerbySchema schema : schemas.values()) {
+ schema.destroy();
+ }
+ if (jmxHelper != null) jmxHelper.terminate();
+ }
+
+ public void createSchema(String name) {
+ createSchema(name, ImmutableMap.of());
+ }
+
+ public void createSchema(String name, Map properties) {
+ Map allprops = MutableMap.builder().putAll(properties).put("name", name).build();
+ DerbySchema schema = new DerbySchema(allprops);
+ schema.init();
+ schema.create();
+ schemas.put(name, schema);
+ }
+
+ public Collection<Schema> getSchemas() {
+ return ImmutableList.<Schema>copyOf(schemas.values());
+ }
+
+ public void addSchema(Schema schema) {
+ schemas.put(schema.getName(), (DerbySchema) schema);
+ }
+
+ public void removeSchema(String schemaName) {
+ schemas.remove(schemaName);
+ }
+
+ @Override
+ protected ToStringHelper toStringHelper() {
+ return super.toStringHelper().add("jdbcPort", getAttribute(JDBC_PORT));
+ }
+
+ protected boolean computeNodeUp() {
+ // FIXME Use the JmxAdapter.reachable() stuff instead of getAttribute
+ try {
+ ObjectName serverInfoObjectName = ObjectName.getInstance("org.apache.derby:type=ServerInformation,name=ServerInformation");
+ String productVersion = (String) jmxHelper.getAttribute(serverInfoObjectName, "ProductVersion");
+ return (productVersion != null);
+ } catch (Exception e) {
+ return false;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbyDatabaseDriver.java
----------------------------------------------------------------------
diff --git a/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbyDatabaseDriver.java b/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbyDatabaseDriver.java
new file mode 100644
index 0000000..832c2b0
--- /dev/null
+++ b/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbyDatabaseDriver.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.database.derby;
+
+import brooklyn.entity.java.JavaSoftwareProcessDriver;
+
+public interface DerbyDatabaseDriver extends JavaSoftwareProcessDriver {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbyDatabaseSshDriver.java
----------------------------------------------------------------------
diff --git a/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbyDatabaseSshDriver.java b/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbyDatabaseSshDriver.java
new file mode 100644
index 0000000..32bc58c
--- /dev/null
+++ b/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbyDatabaseSshDriver.java
@@ -0,0 +1,116 @@
+/*
+ * 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.database.derby;
+
+import static java.lang.String.format;
+
+import java.util.List;
+import java.util.Map;
+
+import brooklyn.entity.java.JavaSoftwareProcessSshDriver;
+import brooklyn.location.Location;
+import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.ssh.BashCommands;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Start a {@link DerbyDatabase} in a {@link Location} accessible over ssh.
+ *
+ * TODO work in progress
+ */
+public class DerbyDatabaseSshDriver extends JavaSoftwareProcessSshDriver implements DerbyDatabaseDriver {
+
+ // TOD Previous comment said "JMX is configured using command line switch"; how should that be set here?
+
+ public DerbyDatabaseSshDriver(DerbyDatabase entity, SshMachineLocation machine) {
+ super(entity, machine);
+ }
+
+ public String getPidFile() { return "derby.pid"; }
+
+ @Override
+ protected String getLogFileLocation() {
+ throw new UnsupportedOperationException("Work in progress");
+ }
+
+ @Override
+ public void install() {
+ String url = format("http://www.mirrorservice.org/sites/ftp.apache.org/db/derby/db-derby-%s/db-derby-%s-lib.tar.gz", getVersion(), getVersion());
+ String saveAs = format("db-derby-%s-lib.tar.gz", getVersion());
+
+ List<String> commands = ImmutableList.<String>builder()
+ .add(BashCommands.commandToDownloadUrlAs(url, saveAs))
+ .add(BashCommands.INSTALL_TAR)
+ .add("tar xzfv " + saveAs)
+ .build();
+
+ newScript(INSTALLING)
+ .failOnNonZeroResultCode()
+ .body.append(commands).execute();
+ }
+
+ @Override
+ public void customize() {
+ newScript(CUSTOMIZING)
+ .failOnNonZeroResultCode()
+ .body.append(
+ format("cp -R %s/derby-broker-%s/{bin,etc,lib} .", getInstallDir(), getVersion()),
+ "make install PREFIX="+getRunDir())
+ .execute();
+ }
+
+ @Override
+ public void launch() {
+ // TODO Should we redirect stdout/stderr: format(" >> %s/console 2>&1 </dev/null &", getRunDir())
+ newScript(MutableMap.of("usePidFile", getPidFile()), LAUNCHING)
+ .failOnNonZeroResultCode()
+ .body.append("nohup ./bin/derby &")
+ .execute();
+ }
+
+
+ @Override
+ public boolean isRunning() {
+ return newScript(MutableMap.of("usePidFile", getPidFile()), CHECK_RUNNING)
+ .execute() == 0;
+ }
+
+ /**
+ * Restarts redis with the current configuration.
+ */
+ @Override
+ public void stop() {
+ newScript(MutableMap.of("usePidFile", getPidFile()), STOPPING)
+ .execute();
+ }
+
+ @Override
+ public Map<String, String> getShellEnvironment() {
+ Map<String, String> orig = super.getShellEnvironment();
+
+ return MutableMap.<String, String>builder()
+ .putAll(orig)
+ .put("DERBY_HOME", getRunDir())
+ .put("DERBY_WORK", getRunDir())
+ .putIfNotNull("DERBY_OPTS", orig.get("JAVA_OPTS"))
+ .build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbySchema.java
----------------------------------------------------------------------
diff --git a/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbySchema.java b/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbySchema.java
new file mode 100644
index 0000000..c4fb2b1
--- /dev/null
+++ b/sandbox/database/src/main/java/org/apache/brooklyn/entity/database/derby/DerbySchema.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 org.apache.brooklyn.entity.database.derby;
+
+import static java.lang.String.format;
+
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import javax.management.ObjectName;
+
+import org.apache.brooklyn.entity.database.Schema;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.AbstractEntity;
+import brooklyn.entity.basic.EntityLocal;
+import brooklyn.entity.java.UsesJmx;
+import brooklyn.event.AttributeSensor;
+import brooklyn.event.basic.BasicAttributeSensor;
+import brooklyn.event.feed.jmx.JmxAttributePollConfig;
+import brooklyn.event.feed.jmx.JmxFeed;
+import brooklyn.event.feed.jmx.JmxHelper;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.flags.SetFromFlag;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+public class DerbySchema extends AbstractEntity implements Schema {
+
+ // FIXME Needs reviewed and implemented properly; while fixing compilation errors
+ // I added enough for it to look mostly plausible but it's completely untested.
+ // And I have not looked up the derby docs to check that the attributes etc are valid.
+
+ // TODO Somehow share jmx connection with DerbyDatabase instance
+
+ // TODO Declare effectors
+
+ public static AttributeSensor<Integer> SCHEMA_DEPTH = new BasicAttributeSensor<Integer>(
+ Integer.class, "derby.schema.depth", "schema depth");
+
+ public static AttributeSensor<Integer> MESSAGE_COUNT = new BasicAttributeSensor<Integer>(
+ Integer.class, "derby.schema.messageCount", "message count");
+
+ @SetFromFlag(defaultVal="localhost")
+ String virtualHost;
+
+ @SetFromFlag(nullable=false)
+ String name;
+
+ protected ObjectName virtualHostManager;
+ protected ObjectName exchange;
+
+ transient JmxHelper jmxHelper;
+ transient JmxFeed jmxFeed;
+
+ public DerbySchema() {
+ super(MutableMap.of(), null);
+ }
+ public DerbySchema(Map properties) {
+ super(properties, null);
+ }
+ public DerbySchema(Entity parent) {
+ this(MutableMap.of(), parent);
+ }
+ public DerbySchema(Map properties, Entity parent) {
+ super(properties, parent);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public DerbyDatabase getParent() {
+ return (DerbyDatabase) super.getParent();
+ }
+
+ /**
+ * Return the JDBC connection URL for the schema.
+ */
+ public String getConnectionUrl() { return String.format("jdbc:derby:%s", name); }
+
+ public void init() {
+ try {
+ virtualHostManager = new ObjectName(format("org.apache.derby:type=VirtualHost.VirtualHostManager,VirtualHost=\"%s\"", virtualHost));
+ exchange = new ObjectName(format("org.apache.derby:type=VirtualHost.Exchange,VirtualHost=\"%s\",name=\"amq.direct\",ExchangeType=direct", virtualHost));
+ create();
+
+ jmxHelper = new JmxHelper((EntityLocal)getParent());
+
+ ObjectName schemaMBeanName = new ObjectName(format("org.apache.derby:type=VirtualHost.Schema,VirtualHost=\"%s\",name=\"%s\"", virtualHost, name));
+
+ jmxFeed = JmxFeed.builder()
+ .entity(this)
+ .helper(jmxHelper)
+ .period(500, TimeUnit.MILLISECONDS)
+ .pollAttribute(new JmxAttributePollConfig<Integer>(SCHEMA_DEPTH)
+ .objectName(schemaMBeanName)
+ .attributeName("SchemaDepth"))
+ .pollAttribute(new JmxAttributePollConfig<Integer>(MESSAGE_COUNT)
+ .objectName(schemaMBeanName)
+ .attributeName("MessageCount"))
+ .build();
+
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ public void create() {
+ jmxHelper.operation(virtualHostManager, "createNewSchema", name, getParent().getAttribute(UsesJmx.JMX_USER), true);
+ jmxHelper.operation(exchange, "createNewBinding", name, name);
+ }
+
+ public void remove() {
+ jmxHelper.operation(exchange, "removeBinding", name, name);
+ jmxHelper.operation(virtualHostManager, "deleteSchema", name);
+ }
+
+ @Override
+ public void destroy() {
+ if (jmxFeed != null) jmxFeed.stop();
+ super.destroy();
+ }
+
+ @Override
+ protected ToStringHelper toStringHelper() {
+ return super.toStringHelper().add("name", name);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/database/src/test/java/brooklyn/entity/database/PlaceholderTest.java
----------------------------------------------------------------------
diff --git a/sandbox/database/src/test/java/brooklyn/entity/database/PlaceholderTest.java b/sandbox/database/src/test/java/brooklyn/entity/database/PlaceholderTest.java
deleted file mode 100644
index 55b5d22..0000000
--- a/sandbox/database/src/test/java/brooklyn/entity/database/PlaceholderTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.database;
-
-import org.testng.annotations.Test;
-
-public class PlaceholderTest {
- @Test
- public void noop() {}
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/database/src/test/java/org/apache/brooklyn/entity/database/PlaceholderTest.java
----------------------------------------------------------------------
diff --git a/sandbox/database/src/test/java/org/apache/brooklyn/entity/database/PlaceholderTest.java b/sandbox/database/src/test/java/org/apache/brooklyn/entity/database/PlaceholderTest.java
new file mode 100644
index 0000000..564249d1
--- /dev/null
+++ b/sandbox/database/src/test/java/org/apache/brooklyn/entity/database/PlaceholderTest.java
@@ -0,0 +1,26 @@
+/*
+ * 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.database;
+
+import org.testng.annotations.Test;
+
+public class PlaceholderTest {
+ @Test
+ public void noop() {}
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNodeSaltImpl.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNodeSaltImpl.java b/sandbox/extra/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNodeSaltImpl.java
deleted file mode 100644
index af0845f..0000000
--- a/sandbox/extra/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNodeSaltImpl.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.database.postgresql;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.Effector;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.EffectorStartableImpl;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.basic.SoftwareProcess;
-import brooklyn.entity.effector.EffectorBody;
-import brooklyn.entity.effector.Effectors;
-import brooklyn.entity.salt.SaltConfig;
-import brooklyn.entity.salt.SaltConfigs;
-import brooklyn.entity.salt.SaltLifecycleEffectorTasks;
-import brooklyn.entity.software.SshEffectorTasks;
-import brooklyn.event.basic.DependentConfiguration;
-import brooklyn.event.feed.ssh.SshFeed;
-import brooklyn.event.feed.ssh.SshPollConfig;
-import brooklyn.location.Location;
-import brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.DynamicTasks;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-
-public class PostgreSqlNodeSaltImpl extends EffectorStartableImpl implements PostgreSqlNode, SoftwareProcess {
-
- private static final Logger LOG = LoggerFactory.getLogger(PostgreSqlNodeSaltImpl.class);
-
- public static final Effector<String> EXECUTE_SCRIPT = Effectors.effector(String.class, "executeScript")
- .description("invokes a script")
- .parameter(ExecuteScriptEffectorBody.SCRIPT)
- .impl(new ExecuteScriptEffectorBody())
- .build();
-
- private SshFeed feed;
-
- @Override
- public void init() {
- super.init();
- new SaltPostgreSqlLifecycle().attachLifecycleEffectors(this);
- }
-
- public static class SaltPostgreSqlLifecycle extends SaltLifecycleEffectorTasks {
- public SaltPostgreSqlLifecycle() {
- usePidFile("/var/run/postgresql/*.pid");
- useService("postgresql");
- }
-
- @Override
- protected void startMinionAsync() {
- Entities.warnOnIgnoringConfig(entity(), SaltConfig.SALT_FORMULAS);
- Entities.warnOnIgnoringConfig(entity(), SaltConfig.SALT_RUN_LIST);
- Entities.warnOnIgnoringConfig(entity(), SaltConfig.SALT_LAUNCH_ATTRIBUTES);
-
- // TODO Set these as defaults, rather than replacing user's value!?
- SaltConfigs.addToFormulas(entity(), "postgres", "https://github.com/saltstack-formulas/postgres-formula/archive/master.tar.gz");
- SaltConfigs.addToRunList(entity(), "postgres");
- SaltConfigs.addLaunchAttributes(entity(), ImmutableMap.<String,Object>builder()
- .put("port", DependentConfiguration.attributeWhenReady(entity(), PostgreSqlNode.POSTGRESQL_PORT))
- .put("listen_addresses", "*")
- .put("pg_hba.type", "host")
- .put("pg_hba.db", "all")
- .put("pg_hba.user", "all")
- .put("pg_hba.addr", "0.0.0.0/0")
- .put("pg_hba.method", "md5")
- .build());
-
- super.startMinionAsync();
- }
-
- @Override
- protected void postStartCustom() {
- super.postStartCustom();
-
- // now run the creation script
- String creationScriptUrl = entity().getConfig(PostgreSqlNode.CREATION_SCRIPT_URL);
- String creationScript;
- if (creationScriptUrl != null) {
- creationScript = new ResourceUtils(entity()).getResourceAsString(creationScriptUrl);
- } else {
- creationScript = entity().getConfig(PostgreSqlNode.CREATION_SCRIPT_CONTENTS);
- }
- entity().invoke(PostgreSqlNodeSaltImpl.EXECUTE_SCRIPT,
- ConfigBag.newInstance().configure(ExecuteScriptEffectorBody.SCRIPT, creationScript).getAllConfig()).getUnchecked();
-
- // and finally connect sensors
- ((PostgreSqlNodeSaltImpl) entity()).connectSensors();
- }
-
- @Override
- protected void preStopCustom() {
- ((PostgreSqlNodeSaltImpl) entity()).disconnectSensors();
- super.preStopCustom();
- }
- }
-
- public static class ExecuteScriptEffectorBody extends EffectorBody<String> {
- public static final ConfigKey<String> SCRIPT = ConfigKeys.newStringConfigKey("script", "contents of script to run");
-
- @Override
- public String call(ConfigBag parameters) {
- return DynamicTasks.queue(SshEffectorTasks.ssh(
- BashCommands.pipeTextTo(
- parameters.get(SCRIPT),
- BashCommands.sudoAsUser("postgres", "psql --file -")))
- .requiringExitCodeZero()).getStdout();
- }
- }
-
- protected void connectSensors() {
- setAttribute(DATASTORE_URL, String.format("postgresql://%s:%s/", getAttribute(HOSTNAME), getAttribute(POSTGRESQL_PORT)));
-
- Location machine = Iterables.get(getLocations(), 0, null);
-
- if (machine instanceof SshMachineLocation) {
- feed = SshFeed.builder()
- .entity(this)
- .machine((SshMachineLocation)machine)
- .poll(new SshPollConfig<Boolean>(SERVICE_UP)
- .command("ps -ef | grep [p]ostgres")
- .setOnSuccess(true)
- .setOnFailureOrException(false))
- .build();
- } else {
- LOG.warn("Location(s) %s not an ssh-machine location, so not polling for status; setting serviceUp immediately", getLocations());
- }
- }
-
- protected void disconnectSensors() {
- if (feed != null) feed.stop();
- }
-
- @Override
- public Integer getPostgreSqlPort() { return getAttribute(POSTGRESQL_PORT); }
-
- @Override
- public String getSharedMemory() { return getConfig(SHARED_MEMORY); }
-
- @Override
- public Integer getMaxConnections() { return getConfig(MAX_CONNECTIONS); }
-
- @Override
- public String getShortName() {
- return "PostgreSQL";
- }
-
- @Override
- public String executeScript(String commands) {
- return Entities.invokeEffector(this, this, EXECUTE_SCRIPT,
- ConfigBag.newInstance().configure(ExecuteScriptEffectorBody.SCRIPT, commands).getAllConfig()).getUnchecked();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltBashCommands.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltBashCommands.java b/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltBashCommands.java
deleted file mode 100644
index 70379f7..0000000
--- a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltBashCommands.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.salt;
-
-import static brooklyn.util.ssh.BashCommands.downloadToStdout;
-
-import javax.annotation.Nullable;
-
-import org.apache.commons.io.FilenameUtils;
-
-import brooklyn.entity.chef.ChefBashCommands;
-import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.text.Identifiers;
-import brooklyn.util.text.Strings;
-
-import com.google.common.annotations.Beta;
-import com.google.common.io.Files;
-
-/**
- * BASH commands useful for setting up SaltStack.
- */
-@Beta
-public class SaltBashCommands {
-
- /**
- * SaltStack formulas can be found at {@code https://github.com/saltstack-formulas} as repositories.
- * <p>
- * This assumes the download is an archive containing a single directory on the root which will
- * be renamed to {@code formulaName}. if that directory already has the correct name {@code formulaName}
- * can be null, but if taking from a GitHub tarball it will typically be of the form {@code formulaName-master/}
- * hence the renaming.
- */
- // TODO support installing from classpath, and using the repository (tie in with those methods)
- public static final String downloadAndExpandFormula(String source, @Nullable String formulaName, boolean force) {
- String dl = downloadAndExpandFormula(source);
- if (formulaName==null) return dl;
- String tmpName = "tmp-"+Strings.makeValidFilename(formulaName)+"-"+Identifiers.makeRandomId(4);
- String installCmd = BashCommands.chain("mkdir "+tmpName, "cd "+tmpName, dl,
- BashCommands.requireTest("`ls | wc -w` -eq 1", "The archive must contain exactly one directory"),
- "FORMULA_EXPANDED_DIR=`ls`",
- "mv $FORMULA_EXPANDED_DIR '../"+formulaName+"'",
- "cd ..",
- "rm -rf "+tmpName);
- if (!force) return BashCommands.alternatives("ls "+formulaName, installCmd);
- else return BashCommands.alternatives("rm -rf "+formulaName, installCmd);
- }
-
- /**
- * Same as {@link #downloadAndExpandFormula(String, String)} with no formula name.
- * <p>
- * Equivalent to the following command, but substituting the given {@code sourceUrl}.
- * <pre>{@code
- * curl -f -L https://github.com/saltstack-formulas/nginx-formula/archive/master.tar.gz | tar xvz
- * }</pre>
- */
- public static final String downloadAndExpandFormula(String sourceUrl) {
- String ext = Files.getFileExtension(sourceUrl);
- if ("tar".equalsIgnoreCase(ext))
- return downloadToStdout(sourceUrl) + " | tar xv";
- if ("tgz".equalsIgnoreCase(ext) || sourceUrl.toLowerCase().endsWith(".tar.gz"))
- return downloadToStdout(sourceUrl) + " | tar xvz";
-
- String target = FilenameUtils.getName(sourceUrl);
- if (target==null) target = ""; else target = target.trim();
- target += "_"+Strings.makeRandomId(4);
-
- if ("zip".equalsIgnoreCase(ext) || "tar.gz".equalsIgnoreCase(ext))
- return BashCommands.chain(
- BashCommands.commandToDownloadUrlAs(sourceUrl, target),
- "unzip "+target,
- "rm "+target);
-
- throw new UnsupportedOperationException("No way to expand "+sourceUrl+" (yet)");
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltConfig.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltConfig.java b/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltConfig.java
deleted file mode 100644
index b14ba98..0000000
--- a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltConfig.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.salt;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.Entity;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.event.AttributeSensor;
-import brooklyn.event.basic.BasicAttributeSensor;
-import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.event.basic.MapConfigKey;
-import brooklyn.event.basic.SetConfigKey;
-import brooklyn.management.TaskAdaptable;
-import brooklyn.management.TaskFactory;
-import brooklyn.util.flags.SetFromFlag;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Function;
-import com.google.common.base.Functions;
-import com.google.common.reflect.TypeToken;
-
-/**
- * {@link ConfigKey}s used to configure Salt entities.
- *
- * @see SaltConfigs
- * @see SaltLifecycleEffectorTasks
- */
-@Beta
-public interface SaltConfig {
-
- MapConfigKey<String> SALT_FORMULAS = new MapConfigKey<String>(String.class,
- "salt.formulaUrls", "Map of Salt formula URLs (normally GutHub repository archives from the salt-formulas user)");
- SetConfigKey<String> SALT_RUN_LIST = new SetConfigKey<String>(String.class,
- "salt.runList", "Set of Salt states to install from the formula URLs");
- MapConfigKey<Object> SALT_LAUNCH_ATTRIBUTES = new MapConfigKey<Object>(Object.class, "salt.launch.attributes", "TODO");
-
- @SetFromFlag("master")
- ConfigKey<SaltStackMaster> MASTER = ConfigKeys.newConfigKey(SaltStackMaster.class,
- "salt.master.entity", "The Salt master server");
-
- AttributeSensor<String> MINION_ID = new BasicAttributeSensor<String>(String.class,
- "salt.minionId", "The ID for a Salt minion");
-
- @SetFromFlag("masterless")
- ConfigKey<Boolean> MASTERLESS_MODE = ConfigKeys.newBooleanConfigKey(
- "salt.masterless", "Salt masterless, minion only configuration (default uses master and minion)",
- Boolean.FALSE);
-
- @SetFromFlag("masterConfigUrl")
- ConfigKey<String> MASTER_CONFIGURATION_URL = ConfigKeys.newStringConfigKey(
- "salt.master.templateUrl", "The Salt master configuration file template URL",
- "classpath://brooklyn/entity/salt/master");
-
- @SetFromFlag("minionConfigUrl")
- ConfigKey<String> MINION_CONFIGURATION_URL = ConfigKeys.newStringConfigKey(
- "salt.minion.templateUrl", "The Salt minion configuration file template URL",
- "classpath://brooklyn/entity/salt/minion");
-
- @SetFromFlag("masterlessConfigUrl")
- ConfigKey<String> MASTERLESS_CONFIGURATION_URL = ConfigKeys.newStringConfigKey(
- "salt.masterless.templateUrl", "The Salt minion masterless configuration file template URL",
- "classpath://brooklyn/entity/salt/masterless");
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- @SetFromFlag("minionIdFunction")
- ConfigKey<Function<Entity, String>> MINION_ID_FUNCTION = new BasicConfigKey(Function.class,
- "salt.minionId.function", "Function to generate the ID of a Salt minion for an entity", Functions.toStringFunction());
-
- @SuppressWarnings("serial")
- ConfigKey<TaskFactory<? extends TaskAdaptable<Boolean>>> IS_RUNNING_TASK = ConfigKeys.newConfigKey(
- new TypeToken<TaskFactory<? extends TaskAdaptable<Boolean>>>() {},
- "salt.driver.isRunningTask");
-
- @SuppressWarnings("serial")
- ConfigKey<TaskFactory<?>> STOP_TASK = ConfigKeys.newConfigKey(
- new TypeToken<TaskFactory<?>>() {},
- "salt.driver.stopTask");
-
- /**
- * The {@link SaltStackMaster master} entity.
- */
- SaltStackMaster getMaster();
-
-}
[4/6] incubator-brooklyn git commit: package rename to
org.apache.brooklyn: sandbox
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltConfigs.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltConfigs.java b/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltConfigs.java
deleted file mode 100644
index 2de0e5d..0000000
--- a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltConfigs.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.salt;
-
-import java.util.Map;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.Entity;
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.event.basic.MapConfigKey.MapModifications;
-import brooklyn.event.basic.SetConfigKey.SetModifications;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Preconditions;
-
-/**
- * Conveniences for configuring brooklyn Salt entities
- *
- * @since 0.6.0
- */
-@Beta
-public class SaltConfigs {
-
- public static void addToRunList(EntitySpec<?> entity, String...states) {
- for (String state : states) {
- entity.configure(SaltConfig.SALT_RUN_LIST, SetModifications.addItem(state));
- }
- }
-
- public static void addToRunList(EntityInternal entity, String...states) {
- for (String state : states) {
- entity.setConfig(SaltConfig.SALT_RUN_LIST, SetModifications.addItem(state));
- }
- }
-
- public static void addToFormuals(EntitySpec<?> entity, String formulaName, String formulaUrl) {
- entity.configure(SaltConfig.SALT_FORMULAS.subKey(formulaName), formulaUrl);
- }
-
- public static void addToFormulas(EntityInternal entity, String formulaName, String formulaUrl) {
- entity.setConfig(SaltConfig.SALT_FORMULAS.subKey(formulaName), formulaUrl);
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public static void addLaunchAttributes(EntitySpec<?> entity, Map<? extends Object,? extends Object> attributesMap) {
- entity.configure(SaltConfig.SALT_LAUNCH_ATTRIBUTES, MapModifications.add((Map)attributesMap));
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public static void addLaunchAttributes(EntityInternal entity, Map<? extends Object,? extends Object> attributesMap) {
- entity.setConfig(SaltConfig.SALT_LAUNCH_ATTRIBUTES, MapModifications.add((Map)attributesMap));
- }
-
- /** replaces the attributes underneath the rootAttribute parameter with the given value;
- * see {@link #addLaunchAttributesMap(EntitySpec, Map)} for richer functionality */
- public static void setLaunchAttribute(EntitySpec<?> entity, String rootAttribute, Object value) {
- entity.configure(SaltConfig.SALT_LAUNCH_ATTRIBUTES.subKey(rootAttribute), value);
- }
-
- /** replaces the attributes underneath the rootAttribute parameter with the given value;
- * see {@link #addLaunchAttributesMap(EntitySpec, Map)} for richer functionality */
- public static void setLaunchAttribute(EntityInternal entity, String rootAttribute, Object value) {
- entity.setConfig(SaltConfig.SALT_LAUNCH_ATTRIBUTES.subKey(rootAttribute), value);
- }
-
- public static <T> T getRequiredConfig(Entity entity, ConfigKey<T> key) {
- return Preconditions.checkNotNull(
- Preconditions.checkNotNull(entity, "Entity must be supplied").getConfig(key),
- "Key "+key+" is required on "+entity);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltLifecycleEffectorTasks.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltLifecycleEffectorTasks.java b/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltLifecycleEffectorTasks.java
deleted file mode 100644
index 82e1b17..0000000
--- a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltLifecycleEffectorTasks.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.salt;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.BrooklynServerConfig;
-import brooklyn.entity.Entity;
-import brooklyn.entity.basic.Attributes;
-import brooklyn.entity.basic.Lifecycle;
-import brooklyn.entity.software.MachineLifecycleEffectorTasks;
-import brooklyn.entity.software.SshEffectorTasks;
-import brooklyn.location.MachineLocation;
-import brooklyn.util.net.Urls;
-import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Supplier;
-
-/**
- * Creates effectors to start, restart, and stop processes using SaltStack.
- * <p>
- * Instances of this should use the {@link SaltConfig} config attributes to configure startup,
- * and invoke {@link #usePidFile(String)} or {@link #useService(String)} to determine check-running and stop behaviour.
- * Alternatively this can be subclassed and {@link #postStartCustom()} and {@link #stopProcessesAtMachine()} overridden.
- *
- * @since 0.6.0
- */
-@Beta
-public class SaltLifecycleEffectorTasks extends MachineLifecycleEffectorTasks implements SaltConfig {
-
- private static final Logger log = LoggerFactory.getLogger(SaltLifecycleEffectorTasks.class);
-
- protected SaltStackMaster master = null;
- protected String pidFile, serviceName, windowsServiceName;
-
- public SaltLifecycleEffectorTasks() {
- }
-
- public SaltLifecycleEffectorTasks usePidFile(String pidFile) {
- this.pidFile = pidFile;
- return this;
- }
- public SaltLifecycleEffectorTasks useService(String serviceName) {
- this.serviceName = serviceName;
- return this;
- }
- public SaltLifecycleEffectorTasks useWindowsService(String serviceName) {
- this.windowsServiceName = serviceName;
- return this;
- }
- public SaltLifecycleEffectorTasks master(SaltStackMaster master) {
- this.master = master;
- return this;
- }
-
- @Override
- public void attachLifecycleEffectors(Entity entity) {
- if (pidFile==null && serviceName==null && getClass().equals(SaltLifecycleEffectorTasks.class)) {
- // warn on incorrect usage
- log.warn("Uses of "+getClass()+" must define a PID file or a service name (or subclass and override {start,stop} methods as per javadoc) " +
- "in order for check-running and stop to work");
- }
-
- super.attachLifecycleEffectors(entity);
- }
-
- @Override
- protected String startProcessesAtMachine(Supplier<MachineLocation> machineS) {
- startMinionAsync();
- return "salt start tasks submitted";
- }
-
- protected void startMinionAsync() {
- // TODO make directories more configurable (both for ssh-drivers and for this)
- String installDir = Urls.mergePaths(BrooklynServerConfig.getMgmtBaseDir(entity().getManagementContext()), "salt-install");
- String runDir = Urls.mergePaths(BrooklynServerConfig.getMgmtBaseDir(entity().getManagementContext()),
- "apps/"+entity().getApplicationId()+"/salt-entities/"+entity().getId());
-
- Boolean masterless = entity().getConfig(SaltConfig.MASTERLESS_MODE);
- if (masterless) {
- DynamicTasks.queue(
- SaltTasks.installFormulas(installDir, SaltConfigs.getRequiredConfig(entity(), SALT_FORMULAS), false),
- SaltTasks.buildSaltFile(runDir,
- SaltConfigs.getRequiredConfig(entity(), SALT_RUN_LIST),
- entity().getConfig(SALT_LAUNCH_ATTRIBUTES)),
- SaltTasks.installSaltMinion(entity(), runDir, installDir, false),
- SaltTasks.runSalt(runDir));
- } else {
- throw new UnsupportedOperationException("Salt master mode not yet supported for minions");
- }
- }
-
- @Override
- protected void postStartCustom() {
- boolean result = false;
- result |= tryCheckStartPid();
- result |= tryCheckStartService();
- result |= tryCheckStartWindowsService();
- if (!result) {
- throw new IllegalStateException("The process for "+entity()+" appears not to be running (no way to check!)");
- }
- }
-
- protected boolean tryCheckStartPid() {
- if (pidFile==null) return false;
-
- // if it's still up after 5s assume we are good (default behaviour)
- Time.sleep(Duration.FIVE_SECONDS);
- if (!DynamicTasks.queue(SshEffectorTasks.isPidFromFileRunning(pidFile).runAsRoot()).get()) {
- throw new IllegalStateException("The process for "+entity()+" appears not to be running (pid file "+pidFile+")");
- }
-
- // and set the PID
- entity().setAttribute(Attributes.PID,
- Integer.parseInt(DynamicTasks.queue(SshEffectorTasks.ssh("cat "+pidFile).runAsRoot()).block().getStdout().trim()));
- return true;
- }
-
- protected boolean tryCheckStartService() {
- if (serviceName==null) return false;
-
- // if it's still up after 5s assume we are good (default behaviour)
- Time.sleep(Duration.FIVE_SECONDS);
- if (!((Integer)0).equals(DynamicTasks.queue(SshEffectorTasks.ssh("/etc/init.d/"+serviceName+" status").runAsRoot()).get())) {
- throw new IllegalStateException("The process for "+entity()+" appears not to be running (service "+serviceName+")");
- }
-
- return true;
- }
-
- protected boolean tryCheckStartWindowsService() {
- if (windowsServiceName==null) return false;
-
- // if it's still up after 5s assume we are good (default behaviour)
- Time.sleep(Duration.FIVE_SECONDS);
- if (!((Integer)0).equals(DynamicTasks.queue(SshEffectorTasks.ssh("sc query \""+serviceName+"\" | find \"RUNNING\"").runAsCommand()).get())) {
- throw new IllegalStateException("The process for "+entity()+" appears not to be running (windowsService "+windowsServiceName+")");
- }
-
- return true;
- }
-
- @Override
- protected String stopProcessesAtMachine() {
- boolean result = false;
- result |= tryStopService();
- result |= tryStopPid();
- if (!result) {
- throw new IllegalStateException("The process for "+entity()+" appears could not be stopped (no impl!)");
- }
- return "stopped";
- }
-
- protected boolean tryStopService() {
- if (serviceName==null) return false;
- int result = DynamicTasks.queue(SshEffectorTasks.ssh("/etc/init.d/"+serviceName+" stop").runAsRoot()).get();
- if (0==result) return true;
- if (entity().getAttribute(Attributes.SERVICE_STATE)!=Lifecycle.RUNNING)
- return true;
-
- throw new IllegalStateException("The process for "+entity()+" appears could not be stopped (exit code "+result+" to service stop)");
- }
-
- protected boolean tryStopPid() {
- Integer pid = entity().getAttribute(Attributes.PID);
- if (pid==null) {
- if (entity().getAttribute(Attributes.SERVICE_STATE)==Lifecycle.RUNNING && pidFile==null)
- log.warn("No PID recorded for "+entity()+" when running, with PID file "+pidFile+"; skipping kill in "+Tasks.current());
- else
- if (log.isDebugEnabled())
- log.debug("No PID recorded for "+entity()+"; skipping ("+entity().getAttribute(Attributes.SERVICE_STATE)+" / "+pidFile+")");
- return false;
- }
-
- // allow non-zero exit as process may have already been killed
- DynamicTasks.queue(SshEffectorTasks.ssh(
- "kill "+pid, "sleep 5", BashCommands.ok("kill -9 "+pid)).allowingNonZeroExitCode().runAsRoot()).block();
-
- if (DynamicTasks.queue(SshEffectorTasks.isPidRunning(pid).runAsRoot()).get()) {
- throw new IllegalStateException("Process for "+entity()+" in "+pid+" still running after kill");
- }
- entity().setAttribute(Attributes.PID, null);
- return true;
- }
-
- /**
- * {@inheritDoc}
- *
- * @return the Salt master entity if it exists.
- * @see #master(SaltStackMaster)
- * @see SaltConfig#MASTERLESS_MODE
- */
- @Override
- public SaltStackMaster getMaster() {
- return master;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltStackMaster.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltStackMaster.java b/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltStackMaster.java
deleted file mode 100644
index 0db1841..0000000
--- a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltStackMaster.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.salt;
-
-import java.util.List;
-
-import org.apache.brooklyn.catalog.Catalog;
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.BrooklynConfigKeys;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.SoftwareProcess;
-import brooklyn.entity.proxying.ImplementedBy;
-import brooklyn.event.AttributeSensor;
-import brooklyn.event.basic.BasicAttributeSensor;
-import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
-import brooklyn.util.flags.SetFromFlag;
-
-import com.google.common.reflect.TypeToken;
-
-@ImplementedBy(SaltStackMasterImpl.class)
-@Catalog(name="SaltStack Master", description="The Salt master server")
-public interface SaltStackMaster extends SoftwareProcess {
-
- @SetFromFlag("version")
- ConfigKey<String> SUGGESTED_VERSION = ConfigKeys.newConfigKeyWithDefault(BrooklynConfigKeys.SUGGESTED_VERSION, "stable");
-
- @SetFromFlag("bootstrapUrl")
- ConfigKey<String> BOOTSTRAP_URL = ConfigKeys.newStringConfigKey(
- "salt.bootstrap.url", "The URL that returns the Salt boostrap commands",
- "http://bootstrap.saltstack.org/");
-
- @SetFromFlag("masterUser")
- ConfigKey<String> MASTER_USER = ConfigKeys.newStringConfigKey(
- "salt.master.user", "The user that runs the Salt master daemon process",
- "root");
-
- @SetFromFlag("masterConfigTemplate")
- ConfigKey<String> MASTER_CONFIG_TEMPLATE_URL = ConfigKeys.newStringConfigKey(
- "salt.master.config.templateUrl", "The template for the Salt master configuration (URL)",
- "classpath:///brooklyn/entity/salt/master");
-
- @SetFromFlag("saltPort")
- PortAttributeSensorAndConfigKey SALT_PORT = new PortAttributeSensorAndConfigKey(
- "salt.port", "Port used for communication between Salt master and minion processes", "4506+");
-
- @SetFromFlag("publishPort")
- PortAttributeSensorAndConfigKey PUBLISH_PORT = new PortAttributeSensorAndConfigKey(
- "salt.publish.port", "Port used by the Salt master publisher", "4505+");
-
- @SuppressWarnings("serial")
- AttributeSensor<List<String>> MINION_IDS = new BasicAttributeSensor<List<String>>(new TypeToken<List<String>>() {},
- "salt.minions", "List of Salt minion IDs");
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltStackMasterDriver.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltStackMasterDriver.java b/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltStackMasterDriver.java
deleted file mode 100644
index 55d46da..0000000
--- a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltStackMasterDriver.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 brooklyn.entity.salt;
-
-import brooklyn.entity.basic.SoftwareProcessDriver;
-
-public interface SaltStackMasterDriver extends SoftwareProcessDriver {
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltStackMasterImpl.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltStackMasterImpl.java b/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltStackMasterImpl.java
deleted file mode 100644
index 2a6815c..0000000
--- a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltStackMasterImpl.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.salt;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.basic.SoftwareProcessImpl;
-import brooklyn.event.feed.ConfigToAttributes;
-
-public class SaltStackMasterImpl extends SoftwareProcessImpl implements SaltStackMaster {
-
- private static final Logger log = LoggerFactory.getLogger(SaltStackMasterImpl.class);
-
- public SaltStackMasterImpl() {
- super();
- }
-
- @Override
- public Class getDriverInterface() {
- return SaltStackMasterDriver.class;
- }
-
- @Override
- protected void connectSensors() {
- super.connectSensors();
-
- // TODO what sensors should we poll?
- ConfigToAttributes.apply(this);
-
- connectServiceUpIsRunning();
- }
-
- @Override
- protected void disconnectSensors() {
- disconnectServiceUpIsRunning();
-
- super.disconnectSensors();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltStackMasterSshDriver.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltStackMasterSshDriver.java b/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltStackMasterSshDriver.java
deleted file mode 100644
index 8a326e7..0000000
--- a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltStackMasterSshDriver.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.salt;
-
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.java.JavaSoftwareProcessSshDriver;
-import brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.DynamicTasks;
-
-import com.google.common.collect.ImmutableMap;
-
-public class SaltStackMasterSshDriver extends JavaSoftwareProcessSshDriver implements SaltStackMasterDriver {
-
- public SaltStackMasterSshDriver(SaltStackMasterImpl entity, SshMachineLocation machine) {
- super(entity, machine);
- }
-
- @Override
- public SaltStackMasterImpl getEntity() {
- return (SaltStackMasterImpl) super.getEntity();
- }
-
- @Override
- protected String getLogFileLocation() {
- return "master.log";
- }
-
- private String getPidFile() {
- return "master.pid";
- }
-
- @Override
- public void install() {
- String url = Entities.getRequiredUrlConfig(getEntity(), SaltStackMaster.BOOTSTRAP_URL);
- copyTemplate(url, "/etc/salt/master");
-
- // Copy the file contents to the remote machine
-// DynamicTasks.queue(SshEffectorTasks.put("/tmp/cumulus.yaml").contents(contents)).get();
-
- // Run Salt bootstrap task to install master
- DynamicTasks.queue(SaltTasks.installSaltMaster(getEntity(), getRunDir(), true));
-
-
- newScript("createInstallDir")
- .body.append("mkdir -p "+getInstallDir())
- .failOnNonZeroResultCode()
- .execute();
-
- newScript(INSTALLING).
- failOnNonZeroResultCode().
- body.append("").execute();
- }
-
- @Override
- public void customize() {
- }
-
- @Override
- public void launch() {
- newScript(ImmutableMap.of("usePidFile", false), LAUNCHING)
- .body.append(BashCommands.sudo("start salt-master"))
- .execute();
- }
-
- @Override
- public boolean isRunning() {
- return newScript(ImmutableMap.of("usePidFile", false), CHECK_RUNNING)
- .body.append(BashCommands.sudo("status salt-master"))
- .execute() == 0;
- }
-
- @Override
- public void stop() {
- newScript(ImmutableMap.of("usePidFile", false), STOPPING)
- .body.append(BashCommands.sudo("stop salt-master"))
- .execute();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltTasks.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltTasks.java b/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltTasks.java
deleted file mode 100644
index 5b4c4ee..0000000
--- a/sandbox/extra/src/main/java/brooklyn/entity/salt/SaltTasks.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.salt;
-
-import static brooklyn.util.ssh.BashCommands.INSTALL_CURL;
-import static brooklyn.util.ssh.BashCommands.INSTALL_TAR;
-import static brooklyn.util.ssh.BashCommands.INSTALL_UNZIP;
-import static brooklyn.util.ssh.BashCommands.downloadToStdout;
-import static brooklyn.util.ssh.BashCommands.sudo;
-
-import java.util.Map;
-
-import brooklyn.entity.Entity;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.effector.EffectorTasks;
-import brooklyn.entity.software.SshEffectorTasks;
-import brooklyn.management.TaskFactory;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.net.Urls;
-import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.text.TemplateProcessor;
-
-import com.google.common.annotations.Beta;
-
-@Beta
-public class SaltTasks {
-
- public static TaskFactory<?> installSaltMaster(Entity master, String saltDirectory, boolean force) {
- // TODO check on entity whether it is salt _server_
- String boostrapUrl = master.getConfig(SaltStackMaster.BOOTSTRAP_URL);
- String version = master.getConfig(SaltStackMaster.SUGGESTED_VERSION);
- String installCmd = cdAndRun(saltDirectory,
- BashCommands.chain(
- INSTALL_CURL,
- INSTALL_TAR,
- INSTALL_UNZIP,
- "( "+downloadToStdout(boostrapUrl) + " | " + sudo("sh -s -- -M -N "+version)+" )"));
- if (!force) installCmd = BashCommands.alternatives("which salt-master", installCmd);
- return SshEffectorTasks.ssh(installCmd).summary("install salt master");
- }
-
- public static TaskFactory<?> installSaltMinion(final Entity minion, final String runDir, final String installDir, final boolean force) {
- return Tasks.<Void>builder().name("install minion").body(
- new Runnable() {
- public void run() {
- // Setup bootstrap installation command for minion
- String boostrapUrl = minion.getConfig(SaltStackMaster.BOOTSTRAP_URL);
- String installCmd = cdAndRun(runDir, BashCommands.chain(
- INSTALL_CURL,
- INSTALL_TAR,
- INSTALL_UNZIP,
- "( "+downloadToStdout(boostrapUrl) + " | " + sudo("sh")+" )"));
- if (!force) installCmd = BashCommands.alternatives("which salt-minion", installCmd);
-
- // Process the minion configuration template
- Boolean masterless = minion.getConfig(SaltConfig.MASTERLESS_MODE);
- String url = masterless ? Entities.getRequiredUrlConfig(minion, SaltConfig.MASTERLESS_CONFIGURATION_URL)
- : Entities.getRequiredUrlConfig(minion, SaltConfig.MINION_CONFIGURATION_URL);
- Map<String, Object> config = MutableMap.<String, Object>builder()
- .put("entity", minion)
- .put("runDir", runDir)
- .put("installDir", installDir)
- .put("formulas", minion.getConfig(SaltConfig.SALT_FORMULAS))
- .build();
- String contents = TemplateProcessor.processTemplateContents(new ResourceUtils(minion).getResourceAsString(url), config);
-
- // Copy the file contents to the remote machine and install/start salt-minion
- DynamicTasks.queue(
- SshEffectorTasks.ssh(installCmd),
- SshEffectorTasks.put("/tmp/minion")
- .contents(contents)
- .createDirectory(),
- SshEffectorTasks.ssh(sudo("mv /tmp/minion /etc/salt/minion")), // TODO clunky
- SshEffectorTasks.ssh(sudo("restart salt-minion"))
- );
- }
- }).buildFactory();
- }
-
- public static TaskFactory<?> installFormulas(final String installDir, final Map<String,String> formulasAndUrls, final boolean force) {
- return Tasks.<Void>builder().name("install formulas").body(
- new Runnable() {
- public void run() {
- Entity e = EffectorTasks.findEntity();
- if (formulasAndUrls==null)
- throw new IllegalStateException("No formulas defined to install at "+e);
- for (String formula: formulasAndUrls.keySet())
- DynamicTasks.queue(installFormula(installDir, formula, formulasAndUrls.get(formula), force));
- }
- }).buildFactory();
- }
-
- public static TaskFactory<?> installFormula(String installDir, String formula, String url, boolean force) {
- return SshEffectorTasks.ssh(cdAndRun(installDir, SaltBashCommands.downloadAndExpandFormula(url, formula, force)))
- .summary("install formula "+formula)
- .requiringExitCodeZero();
- }
-
- protected static String cdAndRun(String targetDirectory, String command) {
- return BashCommands.chain(
- "mkdir -p "+targetDirectory,
- "cd "+targetDirectory,
- command);
- }
-
- public static TaskFactory<?> buildSaltFile(String runDir, Iterable<? extends String> runList, Map<String, Object> attributes) {
- StringBuilder top = new StringBuilder()
- .append("base:\n")
- .append(" '*':\n");
- for (String run : runList) {
- top.append(" - " + run + "\n");
- }
-
- return SshEffectorTasks.put(Urls.mergePaths(runDir, "base", "top.sls"))
- .contents(top.toString())
- .summary("build salt top file")
- .createDirectory();
- }
-
- public static TaskFactory<?> runSalt(String runDir) {
- return SshEffectorTasks.ssh(cdAndRun(runDir, BashCommands.sudo("salt-call state.highstate")))
- .summary("run salt install")
- .requiringExitCodeZero();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/org/apache/brooklyn/entity/database/postgresql/PostgreSqlNodeSaltImpl.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/org/apache/brooklyn/entity/database/postgresql/PostgreSqlNodeSaltImpl.java b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/database/postgresql/PostgreSqlNodeSaltImpl.java
new file mode 100644
index 0000000..66c7acb
--- /dev/null
+++ b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/database/postgresql/PostgreSqlNodeSaltImpl.java
@@ -0,0 +1,179 @@
+/*
+ * 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.database.postgresql;
+
+import org.apache.brooklyn.entity.database.postgresql.PostgreSqlNodeSaltImpl;
+import org.apache.brooklyn.entity.salt.SaltConfig;
+import org.apache.brooklyn.entity.salt.SaltConfigs;
+import org.apache.brooklyn.entity.salt.SaltLifecycleEffectorTasks;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.Effector;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.EffectorStartableImpl;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.database.postgresql.PostgreSqlNode;
+import brooklyn.entity.effector.EffectorBody;
+import brooklyn.entity.effector.Effectors;
+import brooklyn.entity.software.SshEffectorTasks;
+import brooklyn.event.basic.DependentConfiguration;
+import brooklyn.event.feed.ssh.SshFeed;
+import brooklyn.event.feed.ssh.SshPollConfig;
+import brooklyn.location.Location;
+import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.config.ConfigBag;
+import brooklyn.util.ssh.BashCommands;
+import brooklyn.util.task.DynamicTasks;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+public class PostgreSqlNodeSaltImpl extends EffectorStartableImpl implements PostgreSqlNode, SoftwareProcess {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PostgreSqlNodeSaltImpl.class);
+
+ public static final Effector<String> EXECUTE_SCRIPT = Effectors.effector(String.class, "executeScript")
+ .description("invokes a script")
+ .parameter(ExecuteScriptEffectorBody.SCRIPT)
+ .impl(new ExecuteScriptEffectorBody())
+ .build();
+
+ private SshFeed feed;
+
+ @Override
+ public void init() {
+ super.init();
+ new SaltPostgreSqlLifecycle().attachLifecycleEffectors(this);
+ }
+
+ public static class SaltPostgreSqlLifecycle extends SaltLifecycleEffectorTasks {
+ public SaltPostgreSqlLifecycle() {
+ usePidFile("/var/run/postgresql/*.pid");
+ useService("postgresql");
+ }
+
+ @Override
+ protected void startMinionAsync() {
+ Entities.warnOnIgnoringConfig(entity(), SaltConfig.SALT_FORMULAS);
+ Entities.warnOnIgnoringConfig(entity(), SaltConfig.SALT_RUN_LIST);
+ Entities.warnOnIgnoringConfig(entity(), SaltConfig.SALT_LAUNCH_ATTRIBUTES);
+
+ // TODO Set these as defaults, rather than replacing user's value!?
+ SaltConfigs.addToFormulas(entity(), "postgres", "https://github.com/saltstack-formulas/postgres-formula/archive/master.tar.gz");
+ SaltConfigs.addToRunList(entity(), "postgres");
+ SaltConfigs.addLaunchAttributes(entity(), ImmutableMap.<String,Object>builder()
+ .put("port", DependentConfiguration.attributeWhenReady(entity(), PostgreSqlNode.POSTGRESQL_PORT))
+ .put("listen_addresses", "*")
+ .put("pg_hba.type", "host")
+ .put("pg_hba.db", "all")
+ .put("pg_hba.user", "all")
+ .put("pg_hba.addr", "0.0.0.0/0")
+ .put("pg_hba.method", "md5")
+ .build());
+
+ super.startMinionAsync();
+ }
+
+ @Override
+ protected void postStartCustom() {
+ super.postStartCustom();
+
+ // now run the creation script
+ String creationScriptUrl = entity().getConfig(PostgreSqlNode.CREATION_SCRIPT_URL);
+ String creationScript;
+ if (creationScriptUrl != null) {
+ creationScript = new ResourceUtils(entity()).getResourceAsString(creationScriptUrl);
+ } else {
+ creationScript = entity().getConfig(PostgreSqlNode.CREATION_SCRIPT_CONTENTS);
+ }
+ entity().invoke(PostgreSqlNodeSaltImpl.EXECUTE_SCRIPT,
+ ConfigBag.newInstance().configure(ExecuteScriptEffectorBody.SCRIPT, creationScript).getAllConfig()).getUnchecked();
+
+ // and finally connect sensors
+ ((PostgreSqlNodeSaltImpl) entity()).connectSensors();
+ }
+
+ @Override
+ protected void preStopCustom() {
+ ((PostgreSqlNodeSaltImpl) entity()).disconnectSensors();
+ super.preStopCustom();
+ }
+ }
+
+ public static class ExecuteScriptEffectorBody extends EffectorBody<String> {
+ public static final ConfigKey<String> SCRIPT = ConfigKeys.newStringConfigKey("script", "contents of script to run");
+
+ @Override
+ public String call(ConfigBag parameters) {
+ return DynamicTasks.queue(SshEffectorTasks.ssh(
+ BashCommands.pipeTextTo(
+ parameters.get(SCRIPT),
+ BashCommands.sudoAsUser("postgres", "psql --file -")))
+ .requiringExitCodeZero()).getStdout();
+ }
+ }
+
+ protected void connectSensors() {
+ setAttribute(DATASTORE_URL, String.format("postgresql://%s:%s/", getAttribute(HOSTNAME), getAttribute(POSTGRESQL_PORT)));
+
+ Location machine = Iterables.get(getLocations(), 0, null);
+
+ if (machine instanceof SshMachineLocation) {
+ feed = SshFeed.builder()
+ .entity(this)
+ .machine((SshMachineLocation)machine)
+ .poll(new SshPollConfig<Boolean>(SERVICE_UP)
+ .command("ps -ef | grep [p]ostgres")
+ .setOnSuccess(true)
+ .setOnFailureOrException(false))
+ .build();
+ } else {
+ LOG.warn("Location(s) %s not an ssh-machine location, so not polling for status; setting serviceUp immediately", getLocations());
+ }
+ }
+
+ protected void disconnectSensors() {
+ if (feed != null) feed.stop();
+ }
+
+ @Override
+ public Integer getPostgreSqlPort() { return getAttribute(POSTGRESQL_PORT); }
+
+ @Override
+ public String getSharedMemory() { return getConfig(SHARED_MEMORY); }
+
+ @Override
+ public Integer getMaxConnections() { return getConfig(MAX_CONNECTIONS); }
+
+ @Override
+ public String getShortName() {
+ return "PostgreSQL";
+ }
+
+ @Override
+ public String executeScript(String commands) {
+ return Entities.invokeEffector(this, this, EXECUTE_SCRIPT,
+ ConfigBag.newInstance().configure(ExecuteScriptEffectorBody.SCRIPT, commands).getAllConfig()).getUnchecked();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltBashCommands.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltBashCommands.java b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltBashCommands.java
new file mode 100644
index 0000000..a9a07bf
--- /dev/null
+++ b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltBashCommands.java
@@ -0,0 +1,92 @@
+/*
+ * 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.salt;
+
+import static brooklyn.util.ssh.BashCommands.downloadToStdout;
+
+import javax.annotation.Nullable;
+
+import org.apache.commons.io.FilenameUtils;
+
+import brooklyn.entity.chef.ChefBashCommands;
+import brooklyn.util.ssh.BashCommands;
+import brooklyn.util.text.Identifiers;
+import brooklyn.util.text.Strings;
+
+import com.google.common.annotations.Beta;
+import com.google.common.io.Files;
+
+/**
+ * BASH commands useful for setting up SaltStack.
+ */
+@Beta
+public class SaltBashCommands {
+
+ /**
+ * SaltStack formulas can be found at {@code https://github.com/saltstack-formulas} as repositories.
+ * <p>
+ * This assumes the download is an archive containing a single directory on the root which will
+ * be renamed to {@code formulaName}. if that directory already has the correct name {@code formulaName}
+ * can be null, but if taking from a GitHub tarball it will typically be of the form {@code formulaName-master/}
+ * hence the renaming.
+ */
+ // TODO support installing from classpath, and using the repository (tie in with those methods)
+ public static final String downloadAndExpandFormula(String source, @Nullable String formulaName, boolean force) {
+ String dl = downloadAndExpandFormula(source);
+ if (formulaName==null) return dl;
+ String tmpName = "tmp-"+Strings.makeValidFilename(formulaName)+"-"+Identifiers.makeRandomId(4);
+ String installCmd = BashCommands.chain("mkdir "+tmpName, "cd "+tmpName, dl,
+ BashCommands.requireTest("`ls | wc -w` -eq 1", "The archive must contain exactly one directory"),
+ "FORMULA_EXPANDED_DIR=`ls`",
+ "mv $FORMULA_EXPANDED_DIR '../"+formulaName+"'",
+ "cd ..",
+ "rm -rf "+tmpName);
+ if (!force) return BashCommands.alternatives("ls "+formulaName, installCmd);
+ else return BashCommands.alternatives("rm -rf "+formulaName, installCmd);
+ }
+
+ /**
+ * Same as {@link #downloadAndExpandFormula(String, String)} with no formula name.
+ * <p>
+ * Equivalent to the following command, but substituting the given {@code sourceUrl}.
+ * <pre>{@code
+ * curl -f -L https://github.com/saltstack-formulas/nginx-formula/archive/master.tar.gz | tar xvz
+ * }</pre>
+ */
+ public static final String downloadAndExpandFormula(String sourceUrl) {
+ String ext = Files.getFileExtension(sourceUrl);
+ if ("tar".equalsIgnoreCase(ext))
+ return downloadToStdout(sourceUrl) + " | tar xv";
+ if ("tgz".equalsIgnoreCase(ext) || sourceUrl.toLowerCase().endsWith(".tar.gz"))
+ return downloadToStdout(sourceUrl) + " | tar xvz";
+
+ String target = FilenameUtils.getName(sourceUrl);
+ if (target==null) target = ""; else target = target.trim();
+ target += "_"+Strings.makeRandomId(4);
+
+ if ("zip".equalsIgnoreCase(ext) || "tar.gz".equalsIgnoreCase(ext))
+ return BashCommands.chain(
+ BashCommands.commandToDownloadUrlAs(sourceUrl, target),
+ "unzip "+target,
+ "rm "+target);
+
+ throw new UnsupportedOperationException("No way to expand "+sourceUrl+" (yet)");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltConfig.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltConfig.java b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltConfig.java
new file mode 100644
index 0000000..3b5962f
--- /dev/null
+++ b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltConfig.java
@@ -0,0 +1,100 @@
+/*
+ * 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.salt;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.event.AttributeSensor;
+import brooklyn.event.basic.BasicAttributeSensor;
+import brooklyn.event.basic.BasicConfigKey;
+import brooklyn.event.basic.MapConfigKey;
+import brooklyn.event.basic.SetConfigKey;
+import brooklyn.management.TaskAdaptable;
+import brooklyn.management.TaskFactory;
+import brooklyn.util.flags.SetFromFlag;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.common.reflect.TypeToken;
+
+/**
+ * {@link ConfigKey}s used to configure Salt entities.
+ *
+ * @see SaltConfigs
+ * @see SaltLifecycleEffectorTasks
+ */
+@Beta
+public interface SaltConfig {
+
+ MapConfigKey<String> SALT_FORMULAS = new MapConfigKey<String>(String.class,
+ "salt.formulaUrls", "Map of Salt formula URLs (normally GutHub repository archives from the salt-formulas user)");
+ SetConfigKey<String> SALT_RUN_LIST = new SetConfigKey<String>(String.class,
+ "salt.runList", "Set of Salt states to install from the formula URLs");
+ MapConfigKey<Object> SALT_LAUNCH_ATTRIBUTES = new MapConfigKey<Object>(Object.class, "salt.launch.attributes", "TODO");
+
+ @SetFromFlag("master")
+ ConfigKey<SaltStackMaster> MASTER = ConfigKeys.newConfigKey(SaltStackMaster.class,
+ "salt.master.entity", "The Salt master server");
+
+ AttributeSensor<String> MINION_ID = new BasicAttributeSensor<String>(String.class,
+ "salt.minionId", "The ID for a Salt minion");
+
+ @SetFromFlag("masterless")
+ ConfigKey<Boolean> MASTERLESS_MODE = ConfigKeys.newBooleanConfigKey(
+ "salt.masterless", "Salt masterless, minion only configuration (default uses master and minion)",
+ Boolean.FALSE);
+
+ @SetFromFlag("masterConfigUrl")
+ ConfigKey<String> MASTER_CONFIGURATION_URL = ConfigKeys.newStringConfigKey(
+ "salt.master.templateUrl", "The Salt master configuration file template URL",
+ "classpath://org/apache/brooklyn/entity/salt/master");
+
+ @SetFromFlag("minionConfigUrl")
+ ConfigKey<String> MINION_CONFIGURATION_URL = ConfigKeys.newStringConfigKey(
+ "salt.minion.templateUrl", "The Salt minion configuration file template URL",
+ "classpath://org/apache/brooklyn/entity/salt/minion");
+
+ @SetFromFlag("masterlessConfigUrl")
+ ConfigKey<String> MASTERLESS_CONFIGURATION_URL = ConfigKeys.newStringConfigKey(
+ "salt.masterless.templateUrl", "The Salt minion masterless configuration file template URL",
+ "classpath://org/apache/brooklyn/entity/salt/masterless");
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @SetFromFlag("minionIdFunction")
+ ConfigKey<Function<Entity, String>> MINION_ID_FUNCTION = new BasicConfigKey(Function.class,
+ "salt.minionId.function", "Function to generate the ID of a Salt minion for an entity", Functions.toStringFunction());
+
+ @SuppressWarnings("serial")
+ ConfigKey<TaskFactory<? extends TaskAdaptable<Boolean>>> IS_RUNNING_TASK = ConfigKeys.newConfigKey(
+ new TypeToken<TaskFactory<? extends TaskAdaptable<Boolean>>>() {},
+ "salt.driver.isRunningTask");
+
+ @SuppressWarnings("serial")
+ ConfigKey<TaskFactory<?>> STOP_TASK = ConfigKeys.newConfigKey(
+ new TypeToken<TaskFactory<?>>() {},
+ "salt.driver.stopTask");
+
+ /**
+ * The {@link SaltStackMaster master} entity.
+ */
+ SaltStackMaster getMaster();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltConfigs.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltConfigs.java b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltConfigs.java
new file mode 100644
index 0000000..1622d85
--- /dev/null
+++ b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltConfigs.java
@@ -0,0 +1,89 @@
+/*
+ * 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.salt;
+
+import java.util.Map;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.event.basic.MapConfigKey.MapModifications;
+import brooklyn.event.basic.SetConfigKey.SetModifications;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+
+/**
+ * Conveniences for configuring brooklyn Salt entities
+ *
+ * @since 0.6.0
+ */
+@Beta
+public class SaltConfigs {
+
+ public static void addToRunList(EntitySpec<?> entity, String...states) {
+ for (String state : states) {
+ entity.configure(SaltConfig.SALT_RUN_LIST, SetModifications.addItem(state));
+ }
+ }
+
+ public static void addToRunList(EntityInternal entity, String...states) {
+ for (String state : states) {
+ entity.setConfig(SaltConfig.SALT_RUN_LIST, SetModifications.addItem(state));
+ }
+ }
+
+ public static void addToFormuals(EntitySpec<?> entity, String formulaName, String formulaUrl) {
+ entity.configure(SaltConfig.SALT_FORMULAS.subKey(formulaName), formulaUrl);
+ }
+
+ public static void addToFormulas(EntityInternal entity, String formulaName, String formulaUrl) {
+ entity.setConfig(SaltConfig.SALT_FORMULAS.subKey(formulaName), formulaUrl);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static void addLaunchAttributes(EntitySpec<?> entity, Map<? extends Object,? extends Object> attributesMap) {
+ entity.configure(SaltConfig.SALT_LAUNCH_ATTRIBUTES, MapModifications.add((Map)attributesMap));
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static void addLaunchAttributes(EntityInternal entity, Map<? extends Object,? extends Object> attributesMap) {
+ entity.setConfig(SaltConfig.SALT_LAUNCH_ATTRIBUTES, MapModifications.add((Map)attributesMap));
+ }
+
+ /** replaces the attributes underneath the rootAttribute parameter with the given value;
+ * see {@link #addLaunchAttributesMap(EntitySpec, Map)} for richer functionality */
+ public static void setLaunchAttribute(EntitySpec<?> entity, String rootAttribute, Object value) {
+ entity.configure(SaltConfig.SALT_LAUNCH_ATTRIBUTES.subKey(rootAttribute), value);
+ }
+
+ /** replaces the attributes underneath the rootAttribute parameter with the given value;
+ * see {@link #addLaunchAttributesMap(EntitySpec, Map)} for richer functionality */
+ public static void setLaunchAttribute(EntityInternal entity, String rootAttribute, Object value) {
+ entity.setConfig(SaltConfig.SALT_LAUNCH_ATTRIBUTES.subKey(rootAttribute), value);
+ }
+
+ public static <T> T getRequiredConfig(Entity entity, ConfigKey<T> key) {
+ return Preconditions.checkNotNull(
+ Preconditions.checkNotNull(entity, "Entity must be supplied").getConfig(key),
+ "Key "+key+" is required on "+entity);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltLifecycleEffectorTasks.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltLifecycleEffectorTasks.java b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltLifecycleEffectorTasks.java
new file mode 100644
index 0000000..7005db9
--- /dev/null
+++ b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltLifecycleEffectorTasks.java
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.salt;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.BrooklynServerConfig;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.Lifecycle;
+import brooklyn.entity.software.MachineLifecycleEffectorTasks;
+import brooklyn.entity.software.SshEffectorTasks;
+import brooklyn.location.MachineLocation;
+import brooklyn.util.net.Urls;
+import brooklyn.util.ssh.BashCommands;
+import brooklyn.util.task.DynamicTasks;
+import brooklyn.util.task.Tasks;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Supplier;
+
+/**
+ * Creates effectors to start, restart, and stop processes using SaltStack.
+ * <p>
+ * Instances of this should use the {@link SaltConfig} config attributes to configure startup,
+ * and invoke {@link #usePidFile(String)} or {@link #useService(String)} to determine check-running and stop behaviour.
+ * Alternatively this can be subclassed and {@link #postStartCustom()} and {@link #stopProcessesAtMachine()} overridden.
+ *
+ * @since 0.6.0
+ */
+@Beta
+public class SaltLifecycleEffectorTasks extends MachineLifecycleEffectorTasks implements SaltConfig {
+
+ private static final Logger log = LoggerFactory.getLogger(SaltLifecycleEffectorTasks.class);
+
+ protected SaltStackMaster master = null;
+ protected String pidFile, serviceName, windowsServiceName;
+
+ public SaltLifecycleEffectorTasks() {
+ }
+
+ public SaltLifecycleEffectorTasks usePidFile(String pidFile) {
+ this.pidFile = pidFile;
+ return this;
+ }
+ public SaltLifecycleEffectorTasks useService(String serviceName) {
+ this.serviceName = serviceName;
+ return this;
+ }
+ public SaltLifecycleEffectorTasks useWindowsService(String serviceName) {
+ this.windowsServiceName = serviceName;
+ return this;
+ }
+ public SaltLifecycleEffectorTasks master(SaltStackMaster master) {
+ this.master = master;
+ return this;
+ }
+
+ @Override
+ public void attachLifecycleEffectors(Entity entity) {
+ if (pidFile==null && serviceName==null && getClass().equals(SaltLifecycleEffectorTasks.class)) {
+ // warn on incorrect usage
+ log.warn("Uses of "+getClass()+" must define a PID file or a service name (or subclass and override {start,stop} methods as per javadoc) " +
+ "in order for check-running and stop to work");
+ }
+
+ super.attachLifecycleEffectors(entity);
+ }
+
+ @Override
+ protected String startProcessesAtMachine(Supplier<MachineLocation> machineS) {
+ startMinionAsync();
+ return "salt start tasks submitted";
+ }
+
+ protected void startMinionAsync() {
+ // TODO make directories more configurable (both for ssh-drivers and for this)
+ String installDir = Urls.mergePaths(BrooklynServerConfig.getMgmtBaseDir(entity().getManagementContext()), "salt-install");
+ String runDir = Urls.mergePaths(BrooklynServerConfig.getMgmtBaseDir(entity().getManagementContext()),
+ "apps/"+entity().getApplicationId()+"/salt-entities/"+entity().getId());
+
+ Boolean masterless = entity().getConfig(SaltConfig.MASTERLESS_MODE);
+ if (masterless) {
+ DynamicTasks.queue(
+ SaltTasks.installFormulas(installDir, SaltConfigs.getRequiredConfig(entity(), SALT_FORMULAS), false),
+ SaltTasks.buildSaltFile(runDir,
+ SaltConfigs.getRequiredConfig(entity(), SALT_RUN_LIST),
+ entity().getConfig(SALT_LAUNCH_ATTRIBUTES)),
+ SaltTasks.installSaltMinion(entity(), runDir, installDir, false),
+ SaltTasks.runSalt(runDir));
+ } else {
+ throw new UnsupportedOperationException("Salt master mode not yet supported for minions");
+ }
+ }
+
+ @Override
+ protected void postStartCustom() {
+ boolean result = false;
+ result |= tryCheckStartPid();
+ result |= tryCheckStartService();
+ result |= tryCheckStartWindowsService();
+ if (!result) {
+ throw new IllegalStateException("The process for "+entity()+" appears not to be running (no way to check!)");
+ }
+ }
+
+ protected boolean tryCheckStartPid() {
+ if (pidFile==null) return false;
+
+ // if it's still up after 5s assume we are good (default behaviour)
+ Time.sleep(Duration.FIVE_SECONDS);
+ if (!DynamicTasks.queue(SshEffectorTasks.isPidFromFileRunning(pidFile).runAsRoot()).get()) {
+ throw new IllegalStateException("The process for "+entity()+" appears not to be running (pid file "+pidFile+")");
+ }
+
+ // and set the PID
+ entity().setAttribute(Attributes.PID,
+ Integer.parseInt(DynamicTasks.queue(SshEffectorTasks.ssh("cat "+pidFile).runAsRoot()).block().getStdout().trim()));
+ return true;
+ }
+
+ protected boolean tryCheckStartService() {
+ if (serviceName==null) return false;
+
+ // if it's still up after 5s assume we are good (default behaviour)
+ Time.sleep(Duration.FIVE_SECONDS);
+ if (!((Integer)0).equals(DynamicTasks.queue(SshEffectorTasks.ssh("/etc/init.d/"+serviceName+" status").runAsRoot()).get())) {
+ throw new IllegalStateException("The process for "+entity()+" appears not to be running (service "+serviceName+")");
+ }
+
+ return true;
+ }
+
+ protected boolean tryCheckStartWindowsService() {
+ if (windowsServiceName==null) return false;
+
+ // if it's still up after 5s assume we are good (default behaviour)
+ Time.sleep(Duration.FIVE_SECONDS);
+ if (!((Integer)0).equals(DynamicTasks.queue(SshEffectorTasks.ssh("sc query \""+serviceName+"\" | find \"RUNNING\"").runAsCommand()).get())) {
+ throw new IllegalStateException("The process for "+entity()+" appears not to be running (windowsService "+windowsServiceName+")");
+ }
+
+ return true;
+ }
+
+ @Override
+ protected String stopProcessesAtMachine() {
+ boolean result = false;
+ result |= tryStopService();
+ result |= tryStopPid();
+ if (!result) {
+ throw new IllegalStateException("The process for "+entity()+" appears could not be stopped (no impl!)");
+ }
+ return "stopped";
+ }
+
+ protected boolean tryStopService() {
+ if (serviceName==null) return false;
+ int result = DynamicTasks.queue(SshEffectorTasks.ssh("/etc/init.d/"+serviceName+" stop").runAsRoot()).get();
+ if (0==result) return true;
+ if (entity().getAttribute(Attributes.SERVICE_STATE)!=Lifecycle.RUNNING)
+ return true;
+
+ throw new IllegalStateException("The process for "+entity()+" appears could not be stopped (exit code "+result+" to service stop)");
+ }
+
+ protected boolean tryStopPid() {
+ Integer pid = entity().getAttribute(Attributes.PID);
+ if (pid==null) {
+ if (entity().getAttribute(Attributes.SERVICE_STATE)==Lifecycle.RUNNING && pidFile==null)
+ log.warn("No PID recorded for "+entity()+" when running, with PID file "+pidFile+"; skipping kill in "+Tasks.current());
+ else
+ if (log.isDebugEnabled())
+ log.debug("No PID recorded for "+entity()+"; skipping ("+entity().getAttribute(Attributes.SERVICE_STATE)+" / "+pidFile+")");
+ return false;
+ }
+
+ // allow non-zero exit as process may have already been killed
+ DynamicTasks.queue(SshEffectorTasks.ssh(
+ "kill "+pid, "sleep 5", BashCommands.ok("kill -9 "+pid)).allowingNonZeroExitCode().runAsRoot()).block();
+
+ if (DynamicTasks.queue(SshEffectorTasks.isPidRunning(pid).runAsRoot()).get()) {
+ throw new IllegalStateException("Process for "+entity()+" in "+pid+" still running after kill");
+ }
+ entity().setAttribute(Attributes.PID, null);
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the Salt master entity if it exists.
+ * @see #master(SaltStackMaster)
+ * @see SaltConfig#MASTERLESS_MODE
+ */
+ @Override
+ public SaltStackMaster getMaster() {
+ return master;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltStackMaster.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltStackMaster.java b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltStackMaster.java
new file mode 100644
index 0000000..8ce2e3b
--- /dev/null
+++ b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltStackMaster.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.salt;
+
+import java.util.List;
+
+import org.apache.brooklyn.catalog.Catalog;
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.BrooklynConfigKeys;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.proxying.ImplementedBy;
+import brooklyn.event.AttributeSensor;
+import brooklyn.event.basic.BasicAttributeSensor;
+import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
+import brooklyn.util.flags.SetFromFlag;
+
+import com.google.common.reflect.TypeToken;
+
+@ImplementedBy(SaltStackMasterImpl.class)
+@Catalog(name="SaltStack Master", description="The Salt master server")
+public interface SaltStackMaster extends SoftwareProcess {
+
+ @SetFromFlag("version")
+ ConfigKey<String> SUGGESTED_VERSION = ConfigKeys.newConfigKeyWithDefault(BrooklynConfigKeys.SUGGESTED_VERSION, "stable");
+
+ @SetFromFlag("bootstrapUrl")
+ ConfigKey<String> BOOTSTRAP_URL = ConfigKeys.newStringConfigKey(
+ "salt.bootstrap.url", "The URL that returns the Salt boostrap commands",
+ "http://bootstrap.saltstack.org/");
+
+ @SetFromFlag("masterUser")
+ ConfigKey<String> MASTER_USER = ConfigKeys.newStringConfigKey(
+ "salt.master.user", "The user that runs the Salt master daemon process",
+ "root");
+
+ @SetFromFlag("masterConfigTemplate")
+ ConfigKey<String> MASTER_CONFIG_TEMPLATE_URL = ConfigKeys.newStringConfigKey(
+ "salt.master.config.templateUrl", "The template for the Salt master configuration (URL)",
+ "classpath://org/apache/brooklyn/entity/salt/master");
+
+ @SetFromFlag("saltPort")
+ PortAttributeSensorAndConfigKey SALT_PORT = new PortAttributeSensorAndConfigKey(
+ "salt.port", "Port used for communication between Salt master and minion processes", "4506+");
+
+ @SetFromFlag("publishPort")
+ PortAttributeSensorAndConfigKey PUBLISH_PORT = new PortAttributeSensorAndConfigKey(
+ "salt.publish.port", "Port used by the Salt master publisher", "4505+");
+
+ @SuppressWarnings("serial")
+ AttributeSensor<List<String>> MINION_IDS = new BasicAttributeSensor<List<String>>(new TypeToken<List<String>>() {},
+ "salt.minions", "List of Salt minion IDs");
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltStackMasterDriver.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltStackMasterDriver.java b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltStackMasterDriver.java
new file mode 100644
index 0000000..703213a
--- /dev/null
+++ b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltStackMasterDriver.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.salt;
+
+import brooklyn.entity.basic.SoftwareProcessDriver;
+
+public interface SaltStackMasterDriver extends SoftwareProcessDriver {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltStackMasterImpl.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltStackMasterImpl.java b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltStackMasterImpl.java
new file mode 100644
index 0000000..1adfd1a
--- /dev/null
+++ b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltStackMasterImpl.java
@@ -0,0 +1,56 @@
+/*
+ * 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.salt;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.basic.SoftwareProcessImpl;
+import brooklyn.event.feed.ConfigToAttributes;
+
+public class SaltStackMasterImpl extends SoftwareProcessImpl implements SaltStackMaster {
+
+ private static final Logger log = LoggerFactory.getLogger(SaltStackMasterImpl.class);
+
+ public SaltStackMasterImpl() {
+ super();
+ }
+
+ @Override
+ public Class getDriverInterface() {
+ return SaltStackMasterDriver.class;
+ }
+
+ @Override
+ protected void connectSensors() {
+ super.connectSensors();
+
+ // TODO what sensors should we poll?
+ ConfigToAttributes.apply(this);
+
+ connectServiceUpIsRunning();
+ }
+
+ @Override
+ protected void disconnectSensors() {
+ disconnectServiceUpIsRunning();
+
+ super.disconnectSensors();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltStackMasterSshDriver.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltStackMasterSshDriver.java b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltStackMasterSshDriver.java
new file mode 100644
index 0000000..4b88acc
--- /dev/null
+++ b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltStackMasterSshDriver.java
@@ -0,0 +1,95 @@
+/*
+ * 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.salt;
+
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.java.JavaSoftwareProcessSshDriver;
+import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.util.ssh.BashCommands;
+import brooklyn.util.task.DynamicTasks;
+
+import com.google.common.collect.ImmutableMap;
+
+public class SaltStackMasterSshDriver extends JavaSoftwareProcessSshDriver implements SaltStackMasterDriver {
+
+ public SaltStackMasterSshDriver(SaltStackMasterImpl entity, SshMachineLocation machine) {
+ super(entity, machine);
+ }
+
+ @Override
+ public SaltStackMasterImpl getEntity() {
+ return (SaltStackMasterImpl) super.getEntity();
+ }
+
+ @Override
+ protected String getLogFileLocation() {
+ return "master.log";
+ }
+
+ private String getPidFile() {
+ return "master.pid";
+ }
+
+ @Override
+ public void install() {
+ String url = Entities.getRequiredUrlConfig(getEntity(), SaltStackMaster.BOOTSTRAP_URL);
+ copyTemplate(url, "/etc/salt/master");
+
+ // Copy the file contents to the remote machine
+// DynamicTasks.queue(SshEffectorTasks.put("/tmp/cumulus.yaml").contents(contents)).get();
+
+ // Run Salt bootstrap task to install master
+ DynamicTasks.queue(SaltTasks.installSaltMaster(getEntity(), getRunDir(), true));
+
+
+ newScript("createInstallDir")
+ .body.append("mkdir -p "+getInstallDir())
+ .failOnNonZeroResultCode()
+ .execute();
+
+ newScript(INSTALLING).
+ failOnNonZeroResultCode().
+ body.append("").execute();
+ }
+
+ @Override
+ public void customize() {
+ }
+
+ @Override
+ public void launch() {
+ newScript(ImmutableMap.of("usePidFile", false), LAUNCHING)
+ .body.append(BashCommands.sudo("start salt-master"))
+ .execute();
+ }
+
+ @Override
+ public boolean isRunning() {
+ return newScript(ImmutableMap.of("usePidFile", false), CHECK_RUNNING)
+ .body.append(BashCommands.sudo("status salt-master"))
+ .execute() == 0;
+ }
+
+ @Override
+ public void stop() {
+ newScript(ImmutableMap.of("usePidFile", false), STOPPING)
+ .body.append(BashCommands.sudo("stop salt-master"))
+ .execute();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltTasks.java
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltTasks.java b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltTasks.java
new file mode 100644
index 0000000..5cec099
--- /dev/null
+++ b/sandbox/extra/src/main/java/org/apache/brooklyn/entity/salt/SaltTasks.java
@@ -0,0 +1,145 @@
+/*
+ * 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.salt;
+
+import static brooklyn.util.ssh.BashCommands.INSTALL_CURL;
+import static brooklyn.util.ssh.BashCommands.INSTALL_TAR;
+import static brooklyn.util.ssh.BashCommands.INSTALL_UNZIP;
+import static brooklyn.util.ssh.BashCommands.downloadToStdout;
+import static brooklyn.util.ssh.BashCommands.sudo;
+
+import java.util.Map;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.effector.EffectorTasks;
+import brooklyn.entity.software.SshEffectorTasks;
+import brooklyn.management.TaskFactory;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.net.Urls;
+import brooklyn.util.ssh.BashCommands;
+import brooklyn.util.task.DynamicTasks;
+import brooklyn.util.task.Tasks;
+import brooklyn.util.text.TemplateProcessor;
+
+import com.google.common.annotations.Beta;
+
+@Beta
+public class SaltTasks {
+
+ public static TaskFactory<?> installSaltMaster(Entity master, String saltDirectory, boolean force) {
+ // TODO check on entity whether it is salt _server_
+ String boostrapUrl = master.getConfig(SaltStackMaster.BOOTSTRAP_URL);
+ String version = master.getConfig(SaltStackMaster.SUGGESTED_VERSION);
+ String installCmd = cdAndRun(saltDirectory,
+ BashCommands.chain(
+ INSTALL_CURL,
+ INSTALL_TAR,
+ INSTALL_UNZIP,
+ "( "+downloadToStdout(boostrapUrl) + " | " + sudo("sh -s -- -M -N "+version)+" )"));
+ if (!force) installCmd = BashCommands.alternatives("which salt-master", installCmd);
+ return SshEffectorTasks.ssh(installCmd).summary("install salt master");
+ }
+
+ public static TaskFactory<?> installSaltMinion(final Entity minion, final String runDir, final String installDir, final boolean force) {
+ return Tasks.<Void>builder().name("install minion").body(
+ new Runnable() {
+ public void run() {
+ // Setup bootstrap installation command for minion
+ String boostrapUrl = minion.getConfig(SaltStackMaster.BOOTSTRAP_URL);
+ String installCmd = cdAndRun(runDir, BashCommands.chain(
+ INSTALL_CURL,
+ INSTALL_TAR,
+ INSTALL_UNZIP,
+ "( "+downloadToStdout(boostrapUrl) + " | " + sudo("sh")+" )"));
+ if (!force) installCmd = BashCommands.alternatives("which salt-minion", installCmd);
+
+ // Process the minion configuration template
+ Boolean masterless = minion.getConfig(SaltConfig.MASTERLESS_MODE);
+ String url = masterless ? Entities.getRequiredUrlConfig(minion, SaltConfig.MASTERLESS_CONFIGURATION_URL)
+ : Entities.getRequiredUrlConfig(minion, SaltConfig.MINION_CONFIGURATION_URL);
+ Map<String, Object> config = MutableMap.<String, Object>builder()
+ .put("entity", minion)
+ .put("runDir", runDir)
+ .put("installDir", installDir)
+ .put("formulas", minion.getConfig(SaltConfig.SALT_FORMULAS))
+ .build();
+ String contents = TemplateProcessor.processTemplateContents(new ResourceUtils(minion).getResourceAsString(url), config);
+
+ // Copy the file contents to the remote machine and install/start salt-minion
+ DynamicTasks.queue(
+ SshEffectorTasks.ssh(installCmd),
+ SshEffectorTasks.put("/tmp/minion")
+ .contents(contents)
+ .createDirectory(),
+ SshEffectorTasks.ssh(sudo("mv /tmp/minion /etc/salt/minion")), // TODO clunky
+ SshEffectorTasks.ssh(sudo("restart salt-minion"))
+ );
+ }
+ }).buildFactory();
+ }
+
+ public static TaskFactory<?> installFormulas(final String installDir, final Map<String,String> formulasAndUrls, final boolean force) {
+ return Tasks.<Void>builder().name("install formulas").body(
+ new Runnable() {
+ public void run() {
+ Entity e = EffectorTasks.findEntity();
+ if (formulasAndUrls==null)
+ throw new IllegalStateException("No formulas defined to install at "+e);
+ for (String formula: formulasAndUrls.keySet())
+ DynamicTasks.queue(installFormula(installDir, formula, formulasAndUrls.get(formula), force));
+ }
+ }).buildFactory();
+ }
+
+ public static TaskFactory<?> installFormula(String installDir, String formula, String url, boolean force) {
+ return SshEffectorTasks.ssh(cdAndRun(installDir, SaltBashCommands.downloadAndExpandFormula(url, formula, force)))
+ .summary("install formula "+formula)
+ .requiringExitCodeZero();
+ }
+
+ protected static String cdAndRun(String targetDirectory, String command) {
+ return BashCommands.chain(
+ "mkdir -p "+targetDirectory,
+ "cd "+targetDirectory,
+ command);
+ }
+
+ public static TaskFactory<?> buildSaltFile(String runDir, Iterable<? extends String> runList, Map<String, Object> attributes) {
+ StringBuilder top = new StringBuilder()
+ .append("base:\n")
+ .append(" '*':\n");
+ for (String run : runList) {
+ top.append(" - " + run + "\n");
+ }
+
+ return SshEffectorTasks.put(Urls.mergePaths(runDir, "base", "top.sls"))
+ .contents(top.toString())
+ .summary("build salt top file")
+ .createDirectory();
+ }
+
+ public static TaskFactory<?> runSalt(String runDir) {
+ return SshEffectorTasks.ssh(cdAndRun(runDir, BashCommands.sudo("salt-call state.highstate")))
+ .summary("run salt install")
+ .requiringExitCodeZero();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/resources/brooklyn/entity/salt/master
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/resources/brooklyn/entity/salt/master b/sandbox/extra/src/main/resources/brooklyn/entity/salt/master
deleted file mode 100644
index 72d7eb9..0000000
--- a/sandbox/extra/src/main/resources/brooklyn/entity/salt/master
+++ /dev/null
@@ -1,65 +0,0 @@
-[#ftl]
-#
-# 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.
-#
-# /etc/salt/master
-##
-
-#interface: 0.0.0.0
-#ipv6: False
-#publish_port: ${entity.publishPort,c} # 4505
-
-#user: root
-#max_open_files: 100000
-#worker_threads: 5
-ret_port: ${entity.saltPort,c} # 4506
-
-root_dir: /
-pidfile: ${driver.pidFile}
-pki_dir: ${runDir}/pki
-cachedir: ${runDir}/cache
-log_file: ${driver.logFileLocation}
-key_logfile: ${runDir}/key.log
-
-#verify_env: True
-#keep_jobs: 24
-
-#timeout: 5
-#loop_interval: 60
-
-output: nested
-color: False
-log_level: info
-log_level_logfile: debug # Debugging
-
-#job_cache: True
-#minion_data_cache: True
-
-#open_mode: False
-#auto_accept: False
-#autosign_file: autosign.conf
-#permissive_pki_access: False
-
-fileserver_backend:
- - git
-
-gitfs_remotes:
- - git://github.com/saltstack/salt-states.git
- - git://github.com/saltstack-formulas/postgres-formula.git
- - ${entity.remoteUrl}
- # TODO iterate through formula URLs
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/070b5ca7/sandbox/extra/src/main/resources/brooklyn/entity/salt/masterless
----------------------------------------------------------------------
diff --git a/sandbox/extra/src/main/resources/brooklyn/entity/salt/masterless b/sandbox/extra/src/main/resources/brooklyn/entity/salt/masterless
deleted file mode 100644
index ba41c6e..0000000
--- a/sandbox/extra/src/main/resources/brooklyn/entity/salt/masterless
+++ /dev/null
@@ -1,53 +0,0 @@
-[#ftl]
-##
-#
-# 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.
-#
-# SaltStack Masterless Minion Configuration
-#
-# /etc/salt/minion
-##
-
-# Minion configuration
-id: ${entity.id}
-user: root
-backup_mode: minion
-
-# Directory settings
-root_dir: /
-pidfile: ${runDir}/salt-minion.pid
-pki_dir: ${runDir}/pki
-cachedir: ${runDir}/cache
-log_file: ${runDir}/minion.log
-key_logfile: ${runDir}/key.log
-
-file_client: local
-file_roots:
- base:
- - ${runDir}/base
-[#list formulas?keys as formulaName]
- - ${installDir}/${formulaName}
-[/#list]
-
-#verify_env: True
-#cache_jobs: True # Debugging
-
-output: nested
-color: False
-log_level: info
-log_level_logfile: debug # Debugging