You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2014/09/01 18:14:39 UTC
[01/17] git commit: Replaced CouchbaseLoadGenerator classes with yaml
VanillaSoftwareProcess
Repository: incubator-brooklyn
Updated Branches:
refs/heads/master 68592b4db -> be9396160
Replaced CouchbaseLoadGenerator classes with yaml VanillaSoftwareProcess
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/f2d05ff3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/f2d05ff3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/f2d05ff3
Branch: refs/heads/master
Commit: f2d05ff3d48925bffea39ec96d28345f00d3601f
Parents: 21a037f
Author: Martin Harris <gi...@nakomis.com>
Authored: Thu Jun 19 14:38:10 2014 +0100
Committer: Martin Harris <gi...@nakomis.com>
Committed: Mon Aug 18 14:36:11 2014 +0100
----------------------------------------------------------------------
.../nosql/couchbase/CouchbaseLoadGenerator.java | 59 ---------
.../couchbase/CouchbaseLoadGeneratorDriver.java | 28 -----
.../couchbase/CouchbaseLoadGeneratorImpl.java | 50 --------
.../CouchbaseLoadGeneratorSshDriver.java | 122 -------------------
.../launcher/src/test/resources/couchbase.yaml | 77 +++++++++++-
5 files changed, 75 insertions(+), 261 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f2d05ff3/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseLoadGenerator.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseLoadGenerator.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseLoadGenerator.java
deleted file mode 100644
index 37130b9..0000000
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseLoadGenerator.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.couchbase;
-
-import brooklyn.entity.annotation.Effector;
-import brooklyn.entity.annotation.EffectorParam;
-import brooklyn.entity.basic.MethodEffector;
-import brooklyn.entity.basic.SoftwareProcess;
-import brooklyn.entity.proxying.ImplementedBy;
-
-@ImplementedBy(CouchbaseLoadGeneratorImpl.class)
-public interface CouchbaseLoadGenerator extends SoftwareProcess {
- public static final MethodEffector<Void> PILLOWFIGHT = new MethodEffector<Void>(CouchbaseLoadGenerator.class, "pillowfight");
-
- /**
- * NOTE: EffectorParam names match the documentation at http://www.couchbase.com/autodocs/couchbase-c-client-2.1.1/cbc.1.html
- */
- @Effector(description = "Runs cbc pillowfight")
- public void pillowfight(
- @EffectorParam(name = "host", defaultValue="127.0.0.1:8091",
- description = "list of hosts to connect to") String targetHostnameAndPort,
- @EffectorParam(name = "bucket", defaultValue = "default",
- description = "bucket to use") String bucket,
- @EffectorParam(name = "username", description = "username used for authentication to the cluster") String username,
- @EffectorParam(name = "password", description = "password used for authentication to the cluster") String password,
- @EffectorParam(name = "iterations", defaultValue = "1000",
- description = "number of iterations to run") Integer iterations,
- @EffectorParam(name = "num-items", defaultValue = "1000",
- description = "number of items to operate on") Integer numItems,
- @EffectorParam(name = "key-prefix", description = "prefix for keys") String keyPrefix,
- @EffectorParam(name = "num-threads", defaultValue = "1",
- description = "number of threads to use") Integer numThreads,
- @EffectorParam(name = "num-instances", defaultValue = "1",
- description = "number of connection instances to put into the shared connection pool") Integer numInstances,
- @EffectorParam(name = "random-seed", defaultValue = "0", description = "random seed") Integer randomSeed,
- @EffectorParam(name = "ratio", defaultValue = "33",
- description = "Specify SET/GET command ratio (default: 33, i.e. 33% SETs and 67% GETs)") Integer ratio,
- @EffectorParam(name = "min-size", defaultValue = "50",
- description = "minimum size of payload, i.e. document body") Integer minSize,
- @EffectorParam(name = "max-size", defaultValue = "5120",
- description = "maximum size of payload, i.e. document body") Integer maxSize
- );
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f2d05ff3/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseLoadGeneratorDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseLoadGeneratorDriver.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseLoadGeneratorDriver.java
deleted file mode 100644
index 62b1249..0000000
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseLoadGeneratorDriver.java
+++ /dev/null
@@ -1,28 +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.couchbase;
-
-import brooklyn.entity.basic.SoftwareProcessDriver;
-
-public interface CouchbaseLoadGeneratorDriver extends SoftwareProcessDriver {
-
- void pillowfight(String targetHostnameAndPort, String bucket, String username, String password, Integer iterations,
- Integer numItems, String keyPrefix, Integer numThreads, Integer numInstances, Integer randomSeed, Integer ratio,
- Integer minSize, Integer maxSize);
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f2d05ff3/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseLoadGeneratorImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseLoadGeneratorImpl.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseLoadGeneratorImpl.java
deleted file mode 100644
index 8d932df..0000000
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseLoadGeneratorImpl.java
+++ /dev/null
@@ -1,50 +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.couchbase;
-
-import brooklyn.entity.basic.SoftwareProcessImpl;
-
-public class CouchbaseLoadGeneratorImpl extends SoftwareProcessImpl implements CouchbaseLoadGenerator {
-
- @SuppressWarnings("rawtypes")
- @Override
- public Class getDriverInterface() {
- return CouchbaseLoadGeneratorSshDriver.class;
- }
-
- @Override
- public CouchbaseLoadGeneratorSshDriver getDriver() {
- return (CouchbaseLoadGeneratorSshDriver)super.getDriver();
- }
-
- @Override
- public void pillowfight(String targetHostnameAndPort, String bucket, String username, String password, Integer iterations,
- Integer numItems, String keyPrefix, Integer numThreads, Integer numInstances, Integer randomSeed, Integer ratio,
- Integer minSize, Integer maxSize) {
- getDriver().pillowfight(targetHostnameAndPort, bucket, username, password,
- iterations, numItems, keyPrefix, numThreads, numInstances, randomSeed, ratio, minSize, maxSize);
- }
-
- @Override
- protected void connectSensors() {
- super.connectSensors();
- connectServiceUpIsRunning();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f2d05ff3/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseLoadGeneratorSshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseLoadGeneratorSshDriver.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseLoadGeneratorSshDriver.java
deleted file mode 100644
index b47c5d0..0000000
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseLoadGeneratorSshDriver.java
+++ /dev/null
@@ -1,122 +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.couchbase;
-
-import java.util.List;
-
-import brooklyn.entity.basic.AbstractSoftwareProcessSshDriver;
-import brooklyn.entity.basic.EntityLocal;
-import brooklyn.location.OsDetails;
-import brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.text.Strings;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-
-public class CouchbaseLoadGeneratorSshDriver extends AbstractSoftwareProcessSshDriver implements CouchbaseLoadGeneratorDriver {
-
- public CouchbaseLoadGeneratorSshDriver(EntityLocal entity, SshMachineLocation machine) {
- super(entity, machine);
- }
-
- @Override
- public void install() {
- OsDetails osDetails = getMachine().getMachineDetails().getOsDetails();
- if (osDetails.isLinux()) {
- String aptSetup = BashCommands.ifExecutableElse0("apt-get", BashCommands.chainGroup(
- BashCommands.sudo("apt-get update"),
- BashCommands.sudo("wget -O/etc/apt/sources.list.d/couchbase.list http://packages.couchbase.com/ubuntu/couchbase-ubuntu1204.list"),
- "wget -O- http://packages.couchbase.com/ubuntu/couchbase.key | sudo apt-key add - "
- ));
- String yumSetup = BashCommands.ifExecutableElse0("yum", BashCommands.chainGroup(
- // TODO: 32bit / 64bit
- BashCommands.sudo("yum check-update"),
- BashCommands.sudo("wget -O/etc/yum.repos.d/couchbase.repo http://packages.couchbase.com/rpm/couchbase-centos55-x86_64.repo")
- ));
- String installPackage = BashCommands.installPackage(ImmutableMap.of(
- "apt", "libcouchbase2-libevent libcouchbase-dev libcouchbase2-bin",
- "yum", "libcouchbase2-libevent libcouchbase-devel libcouchbase2-bin"
- ), null);
- List<String> commands = ImmutableList.<String>builder()
- .add(BashCommands.INSTALL_WGET)
- .add(BashCommands.alternatives(aptSetup, yumSetup))
- .add(installPackage)
- .build();
- newScript(INSTALLING)
- .body.append(commands).execute();
- }
- }
-
- @Override
- public void customize() {
- // no-op
- }
-
- @Override
- public void launch() {
- // no-op, process is only launch when pillowfight is called
- }
-
- @Override
- public boolean isRunning() {
- return true;
- }
-
- @Override
- public void stop() {
- // no-op
- }
-
- @Override
- public void pillowfight(String targetHostnameAndPort, String bucket, String username, String password, Integer iterations,
- Integer numItems, String keyPrefix, Integer numThreads, Integer numInstances, Integer randomSeed, Integer ratio,
- Integer minSize, Integer maxSize) {
- StringBuilder builder = new StringBuilder();
- builder.append("cbc pillowfight ");
- addOptionalStringParam(builder, "h", targetHostnameAndPort);
- addOptionalStringParam(builder, "b", bucket);
- addOptionalStringParam(builder, "u", username);
- addOptionalStringParam(builder, "P", password);
- addIntegerParam(builder, "i", iterations);
- addIntegerParam(builder, "I", numItems);
- addOptionalStringParam(builder, "p", keyPrefix);
- addIntegerParam(builder, "t", numThreads);
- addIntegerParam(builder, "Q", numInstances);
- addIntegerParam(builder, "s", randomSeed);
- addIntegerParam(builder, "r", ratio);
- addIntegerParam(builder, "m", minSize);
- addIntegerParam(builder, "M", maxSize);
- newScript("pillow-fight")
- .body.append(builder.toString())
- .gatherOutput()
- .failOnNonZeroResultCode()
- .execute();
- }
-
- private void addOptionalStringParam(StringBuilder builder, String paramFlag, String value) {
- if (!Strings.isEmpty(value)) {
- builder.append(String.format("-%s %s ", paramFlag, value));
- }
- }
-
- private void addIntegerParam(StringBuilder builder, String paramFlag, Integer value) {
- builder.append(String.format("-%s %d ", paramFlag, value));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f2d05ff3/usage/launcher/src/test/resources/couchbase.yaml
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/resources/couchbase.yaml b/usage/launcher/src/test/resources/couchbase.yaml
index 0359bd8..f22d4f5 100644
--- a/usage/launcher/src/test/resources/couchbase.yaml
+++ b/usage/launcher/src/test/resources/couchbase.yaml
@@ -17,10 +17,83 @@
# under the License.
#
name: Couchbase
+
+location: aws-ec2:eu-west-1
+
services:
- type: brooklyn.entity.nosql.couchbase.CouchbaseCluster
adminUsername: Administrator
adminPassword: Password
initialSize: 3
-- type: brooklyn.entity.nosql.couchbase.CouchbaseLoadGenerator
-location: aws-ec2
+- type: brooklyn.entity.basic.VanillaSoftwareProcess
+ name: CBC Pillowfight
+ checkRunning.command: ""
+ stop.command: ""
+ launch.command: |
+ sudo wget -O/etc/apt/sources.list.d/couchbase.list http://packages.couchbase.com/ubuntu/couchbase-ubuntu1204.list
+ sudo wget -O- http://packages.couchbase.com/ubuntu/couchbase.key | sudo apt-key add -
+ sudo apt-get update
+ sudo apt-get install -y libcouchbase2-libevent libcouchbase-dev libcouchbase2-bin
+ brooklyn.initializers:
+ - type: brooklyn.entity.software.ssh.SshCommandEffector
+ brooklyn.config:
+ name: cbcPillowFight
+ description: runs cbc pillowfight
+ command: >
+ cbc pillowfight
+ `if [ -n "$host" ]; then echo -h $host; fi`
+ `if [ -n "$bucket" ]; then echo -b $bucket; fi`
+ `if [ -n "$username" ]; then echo -u $username; fi`
+ `if [ -n "$password" ]; then echo -p $password; fi`
+ `if [ -n "$iterations" ]; then echo -i $iterations; fi`
+ `if [ -n "$numItems" ]; then echo -I $numItems; fi`
+ `if [ -n "$keyPrefix" ]; then echo -p $keyPrefix; fi`
+ `if [ -n "$numThreads" ]; then echo -t $numThreads; fi`
+ `if [ -n "$numInstances" ]; then echo -Q $numInstances; fi`
+ `if [ -n "$randomSeed" ]; then echo -s $randomSeed; fi`
+ `if [ -n "$minSize" ]; then echo -m $minSize; fi`
+ `if [ -n "$maxSize" ]; then echo -M $maxSize; fi`
+ parameters:
+ host:
+ description: list of hosts to connect to
+ defaultValue: 127.0.0.1:8091
+ bucket:
+ description: bucket to use
+ defaultValue: default
+ username:
+ description: username used for authentication to the cluster
+ password:
+ description: password used for authentication to the cluster
+ iterations:
+ description: number of iterations to run
+ defaultValue: 1000
+ numItems:
+ description: number of items to operate on
+ defaultValue: 1000
+ keyPrefix:
+ description: prefix for keys
+ numThreads:
+ description: number of threads to use
+ defaultValue: 1
+ numInstances:
+ description: number of connection instances to put into the shared connection pool
+ defaultValue: 1
+ randomSeed:
+ description: random seed
+ defaultValue: 0
+ ratio:
+ description: "specify SET/GET command ratio (default: 33, i.e. 33% SETs and 67% GETs)"
+ defaultValue: 33
+ minSize:
+ description: minimum size of payload, i.e. document body
+ defaultValue: 50
+ maxSize:
+ description: maximum size of payload, i.e. document body
+ defaultValue: 5120
+
+# For CentOS, use the following launch command:
+# launch.command: |
+# sudo wget -O/etc/yum.repos.d/couchbase.repo http://packages.couchbase.com/rpm/couchbase-centos55-x86_64.repo
+# sudo yum check-update
+# sudo yum install -y libcouchbase2-libevent libcouchbase-devel libcouchbase2-bin
+
[09/17] git commit: This closes #25
Posted by he...@apache.org.
This closes #25
Conflicts:
software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java - connect enrichers was removed, fixed here
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/4734ad89
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/4734ad89
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/4734ad89
Branch: refs/heads/master
Commit: 4734ad8932f59d228d347669e1ad8c560f06f0f3
Parents: c720e8c f23ee27
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Aug 29 19:02:03 2014 -0400
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Aug 29 19:02:03 2014 -0400
----------------------------------------------------------------------
.../nosql/couchbase/CouchbaseCluster.java | 23 ++-
.../nosql/couchbase/CouchbaseClusterImpl.java | 108 +++++++++++-
.../entity/nosql/couchbase/CouchbaseNode.java | 6 +
.../nosql/couchbase/CouchbaseNodeDriver.java | 2 +
.../nosql/couchbase/CouchbaseNodeImpl.java | 4 +
.../nosql/couchbase/CouchbaseNodeSshDriver.java | 123 ++++++++++++-
.../nosql/couchbase/CouchbaseSyncGateway.java | 75 ++++++++
.../couchbase/CouchbaseSyncGatewayDriver.java | 27 +++
.../couchbase/CouchbaseSyncGatewayImpl.java | 82 +++++++++
.../CouchbaseSyncGatewaySshDriver.java | 176 +++++++++++++++++++
.../CouchbaseSyncGatewayEc2LiveTest.java | 137 +++++++++++++++
11 files changed, 753 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4734ad89/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
----------------------------------------------------------------------
diff --cc software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
index b47f133,4affcd1..dc63e8c
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
@@@ -42,6 -43,13 +45,11 @@@ import brooklyn.entity.group.DynamicClu
import brooklyn.entity.proxying.EntitySpec;
import brooklyn.entity.trait.Startable;
import brooklyn.event.AttributeSensor;
-import brooklyn.event.SensorEvent;
-import brooklyn.event.SensorEventListener;
+ import brooklyn.event.basic.DependentConfiguration;
+ import brooklyn.event.feed.http.HttpFeed;
+ import brooklyn.event.feed.http.HttpPollConfig;
+ import brooklyn.event.feed.http.HttpValueFunctions;
+ import brooklyn.event.feed.http.JsonFunctions;
import brooklyn.location.Location;
import brooklyn.policy.PolicySpec;
import brooklyn.util.collections.MutableSet;
@@@ -129,7 -147,10 +147,9 @@@ public class CouchbaseClusterImpl exten
super.start(locations);
connectSensors();
- connectEnrichers();
+ setAttribute(BUCKET_CREATION_IN_PROGRESS, false);
+
//start timeout before adding the servers
Time.sleep(getConfig(SERVICE_UP_TIME_OUT));
[11/17] git commit: expands power of Tasks.resolveValue with new
supporting class ValueResolver, supporting timeouts on resolving value and
forcing submission of execution to a task context where needed;
means that config arguments can be resolved in mor
Posted by he...@apache.org.
expands power of Tasks.resolveValue with new supporting class ValueResolver, supporting timeouts on resolving value and forcing submission of execution to a task context where needed;
means that config arguments can be resolved in more places, such as effector default values from the GUI
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/05a39488
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/05a39488
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/05a39488
Branch: refs/heads/master
Commit: 05a39488dca27887f563c20ad1110ed3916c25f5
Parents: 4734ad8
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Aug 29 01:32:52 2014 -0400
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Sep 1 17:07:00 2014 +0100
----------------------------------------------------------------------
.../java/brooklyn/util/flags/TypeCoercions.java | 11 +-
.../src/main/java/brooklyn/util/task/Tasks.java | 124 ++------
.../java/brooklyn/util/task/ValueResolver.java | 284 +++++++++++++++++++
.../test/java/brooklyn/util/task/TasksTest.java | 1 +
.../brooklyn/util/task/ValueResolverTest.java | 75 +++++
.../BrooklynPropertiesSecurityFilter.java | 9 +-
.../rest/transform/EffectorTransformer.java | 28 +-
.../main/java/brooklyn/util/time/Durations.java | 26 ++
8 files changed, 439 insertions(+), 119 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/05a39488/core/src/main/java/brooklyn/util/flags/TypeCoercions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/flags/TypeCoercions.java b/core/src/main/java/brooklyn/util/flags/TypeCoercions.java
index 7e92ed5..a3864a3 100644
--- a/core/src/main/java/brooklyn/util/flags/TypeCoercions.java
+++ b/core/src/main/java/brooklyn/util/flags/TypeCoercions.java
@@ -103,6 +103,15 @@ public class TypeCoercions {
return coerce(value, TypeToken.of(targetType));
}
+ public static <T> Maybe<T> tryCoerce(Object value, TypeToken<T> targetTypeToken) {
+ try {
+ return Maybe.of( coerce(value, targetTypeToken) );
+ } catch (Throwable t) {
+ Exceptions.propagateIfFatal(t);
+ return Maybe.absent(t);
+ }
+ }
+
/** @see #coerce(Object, Class) */
@SuppressWarnings({ "unchecked" })
public static <T> T coerce(Object value, TypeToken<T> targetTypeToken) {
@@ -622,7 +631,7 @@ public class TypeCoercions {
registerAdapter(String.class, AttributeSensor.class, new Function<String,AttributeSensor>() {
@Override
public AttributeSensor apply(final String input) {
- return new BasicAttributeSensor(Object.class, input);
+ return new BasicAttributeSensor<Object>(Object.class, input);
}
});
registerAdapter(String.class, List.class, new Function<String,List>() {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/05a39488/core/src/main/java/brooklyn/util/task/Tasks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/Tasks.java b/core/src/main/java/brooklyn/util/task/Tasks.java
index 9a7a062..71b43b3 100644
--- a/core/src/main/java/brooklyn/util/task/Tasks.java
+++ b/core/src/main/java/brooklyn/util/task/Tasks.java
@@ -20,13 +20,9 @@ package brooklyn.util.task;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nullable;
@@ -40,7 +36,6 @@ import brooklyn.management.TaskAdaptable;
import brooklyn.management.TaskFactory;
import brooklyn.management.TaskQueueingContext;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.TypeCoercions;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
@@ -48,9 +43,6 @@ import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
public class Tasks {
@@ -109,109 +101,29 @@ public class Tasks {
@SuppressWarnings("rawtypes")
public static Task current() { return BasicExecutionManager.getPerThreadCurrentTask().get(); }
+ /** creates a {@link ValueResolver} instance which allows significantly more customization than
+ * the various {@link #resolveValue(Object, Class, ExecutionContext)} methods here */
+ public static <T> ValueResolver<T> resolving(Object v, Class<T> type) {
+ return new ValueResolver<T>(v, type);
+ }
+
+ public static ValueResolver.ResolverBuilderPretype resolving(Object v) {
+ return new ValueResolver.ResolverBuilderPretype(v);
+ }
+
/** @see #resolveValue(Object, Class, ExecutionContext, String) */
- public static <T> T resolveValue(Object v, Class<T> type, ExecutionContext exec) throws ExecutionException, InterruptedException {
- return resolveValue(v, type, exec, null);
+ public static <T> T resolveValue(Object v, Class<T> type, @Nullable ExecutionContext exec) throws ExecutionException, InterruptedException {
+ return new ValueResolver<T>(v, type).context(exec).get();
}
/** attempt to resolve the given value as the given type, waiting on futures, submitting if necessary,
* and coercing as allowed by TypeCoercions;
- * contextMessage (optional) will be displayed in status reports while it waits (e.g. the name of the config key being looked up) */
- public static <T> T resolveValue(Object v, Class<T> type, ExecutionContext exec, String contextMessage) throws ExecutionException, InterruptedException {
- return resolveValue(v, type, exec, contextMessage, false);
+ * contextMessage (optional) will be displayed in status reports while it waits (e.g. the name of the config key being looked up).
+ * if no execution context supplied (null) this method will throw an exception if the object is an unsubmitted task */
+ public static <T> T resolveValue(Object v, Class<T> type, @Nullable ExecutionContext exec, String contextMessage) throws ExecutionException, InterruptedException {
+ return new ValueResolver<T>(v, type).context(exec).description(contextMessage).get();
}
- @SuppressWarnings({ "unchecked", "rawtypes" })
- private static <T> T resolveValue(Object v, Class<T> type, ExecutionContext exec, String contextMessage, boolean forceDeep) throws ExecutionException, InterruptedException {
- if (type==null)
- throw new NullPointerException("type cannot be null in resolveValue, for '"+v+"'"+(contextMessage!=null ? ", "+contextMessage : ""));
- //if the expected type is a closure or map and that's what we have, we're done (or if it's null);
- //but not allowed to return a future or DeferredSupplier as the resolved value
- if (v==null || (!forceDeep && type.isInstance(v) && !Future.class.isInstance(v) && !DeferredSupplier.class.isInstance(v)))
- return (T) v;
- try {
- //if it's a task or a future, we wait for the task to complete
- if (v instanceof TaskAdaptable<?>) {
- //if it's a task, we make sure it is submitted
- //(perhaps could run it here? ... tbd)
- if (!((TaskAdaptable<?>) v).asTask().isSubmitted() ) {
- exec.submit(((TaskAdaptable<?>) v).asTask());
- }
- }
-
- if (v instanceof Future) {
- final Future<?> vfuture = (Future<?>) v;
-
- //including tasks, above
- if (!vfuture.isDone()) {
- final AtomicReference<Object> vref = new AtomicReference<Object>(v);
-
- withBlockingDetails("Waiting for "+(contextMessage!=null ? contextMessage : ""+v),
- new Callable<Void>() {
- public Void call() throws Exception {
- vref.set( vfuture.get() );
- return null;
- }
- });
-
- v = vref.get();
-
- } else {
- v = vfuture.get();
- }
-
- } else if (v instanceof DeferredSupplier<?>) {
- v = ((DeferredSupplier<?>) v).get();
-
- } else if (v instanceof Map) {
- //and if a map or list we look inside
- Map result = Maps.newLinkedHashMap();
- for (Map.Entry<?,?> entry : ((Map<?,?>)v).entrySet()) {
- result.put(entry.getKey(), resolveValue(entry.getValue(), type, exec,
- (contextMessage!=null ? contextMessage+", " : "") + "map entry "+entry.getKey(), forceDeep));
- }
- return (T) result;
-
- } else if (v instanceof List) {
- List result = Lists.newArrayList();
- int count = 0;
- for (Object it : (List)v) {
- result.add(resolveValue(it, type, exec,
- (contextMessage!=null ? contextMessage+", " : "") + "list entry "+count, forceDeep));
- count++;
- }
- return (T) result;
-
- } else if (v instanceof Set) {
- Set result = Sets.newLinkedHashSet();
- int count = 0;
- for (Object it : (Set)v) {
- result.add(resolveValue(it, type, exec,
- (contextMessage!=null ? contextMessage+", " : "") + "list entry "+count, forceDeep));
- count++;
- }
- return (T) result;
-
- } else if (v instanceof Iterable) {
- List result = Lists.newArrayList();
- int count = 0;
- for (Object it : (Iterable)v) {
- result.add(resolveValue(it, type, exec,
- (contextMessage!=null ? contextMessage+", " : "") + "list entry "+count, forceDeep));
- count++;
- }
- return (T) result;
-
- } else {
- return TypeCoercions.coerce(v, type);
- }
-
- } catch (Exception e) {
- throw new IllegalArgumentException("Error resolving "+(contextMessage!=null ? contextMessage+", " : "")+v+", in "+exec+": "+e, e);
- }
- return resolveValue(v, type, exec, contextMessage, forceDeep);
- }
-
/**
* @see #resolveDeepValue(Object, Class, ExecutionContext, String)
*/
@@ -238,8 +150,8 @@ public class Tasks {
* e.g. if the requested type is an Object, {@link #resolveValue(Object, Class, ExecutionContext, String)}
* will decide that it matches a Map and not recurse on it, whereas this will recurse on it.
*/
- public static Object resolveDeepValue(Object v, Class<?> type, ExecutionContext exec, String contextMessage) throws ExecutionException, InterruptedException {
- return resolveValue(v, type, exec, contextMessage, true);
+ public static <T> T resolveDeepValue(Object v, Class<T> type, ExecutionContext exec, String contextMessage) throws ExecutionException, InterruptedException {
+ return new ValueResolver<T>(v, type).context(exec).deep(true).description(contextMessage).get();
}
/** sets extra status details on the current task, if possible (otherwise does nothing).
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/05a39488/core/src/main/java/brooklyn/util/task/ValueResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/ValueResolver.java b/core/src/main/java/brooklyn/util/task/ValueResolver.java
new file mode 100644
index 0000000..5508b0d
--- /dev/null
+++ b/core/src/main/java/brooklyn/util/task/ValueResolver.java
@@ -0,0 +1,284 @@
+/*
+ * 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.util.task;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import brooklyn.management.ExecutionContext;
+import brooklyn.management.Task;
+import brooklyn.management.TaskAdaptable;
+import brooklyn.util.flags.TypeCoercions;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.time.CountdownTimer;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Durations;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.common.reflect.TypeToken;
+
+/**
+ * Resolves a given object, as follows:
+ * <li> If it is a {@link Tasks} or a {@link DeferredSupplier} then get its contents
+ * <li> If it's a map and {@link #deep(boolean)} is requested, it applies resolution to contents
+ * <li> It applies coercion
+ * <p>
+ * Fluent-style API exposes a number of other options.
+ */
+public class ValueResolver<T> {
+
+ final Object value;
+ final Class<T> type;
+ ExecutionContext exec;
+ String description;
+ boolean forceDeep;
+ /** null means do it if you can; true means always, false means never */
+ Boolean embedResolutionInTask;
+ /** timeout on execution, if possible, or if embedResolutionInTask is true */
+ Duration timeout;
+
+ // internal fields
+ final Object parentOriginalValue;
+ final CountdownTimer parentTimer;
+ AtomicBoolean started = new AtomicBoolean(false);
+ boolean expired;
+
+ ValueResolver(Object v, Class<T> type) {
+ this.value = v;
+ this.type = type;
+ checkTypeNotNull();
+ parentOriginalValue = null;
+ parentTimer = null;
+ }
+
+ ValueResolver(Object v, Class<T> type, ValueResolver<?> parent) {
+ this.value = v;
+ this.type = type;
+ checkTypeNotNull();
+
+ exec = parent.exec;
+ description = parent.description;
+ forceDeep = parent.forceDeep;
+ embedResolutionInTask = parent.embedResolutionInTask;
+
+ parentOriginalValue = parent.getOriginalValue();
+
+ timeout = parent.timeout;
+ parentTimer = parent.parentTimer;
+ if (parentTimer!=null && parentTimer.isExpired())
+ expired = true;
+ }
+
+ public static class ResolverBuilderPretype {
+ final Object v;
+ public ResolverBuilderPretype(Object v) {
+ this.v = v;
+ }
+ public <T> ValueResolver<T> as(Class<T> type) {
+ return new ValueResolver<T>(v, type);
+ }
+ }
+
+ /** execution context to use when resolving; required if resolving unsubmitted tasks or running with a time limit */
+ public ValueResolver<T> context(ExecutionContext exec) {
+ this.exec = exec;
+ return this;
+ }
+
+ /** sets a message which will be displayed in status reports while it waits (e.g. the name of the config key being looked up) */
+ public ValueResolver<T> description(String description) {
+ this.description = description;
+ return this;
+ }
+
+ /** causes nested structures (maps, lists) to be descended and nested unresolved values resolved */
+ public ValueResolver<T> deep(boolean forceDeep) {
+ this.forceDeep = forceDeep;
+ return this;
+ }
+
+ /** if true, forces execution of a deferred supplier to be run in a task;
+ * if false, it prevents it (meaning time limits may not be applied);
+ * if null, the default, it runs in a task if a time limit is applied.
+ * <p>
+ * running inside a task is required for some {@link DeferredSupplier}
+ * instances which look up a task {@link ExecutionContext}. */
+ public ValueResolver<T> embedResolutionInTask(Boolean embedResolutionInTask) {
+ this.embedResolutionInTask = embedResolutionInTask;
+ return this;
+ }
+
+ /** sets a time limit on executions
+ * <p>
+ * used for {@link Task} and {@link DeferredSupplier} instances.
+ * may require an execution context at runtime. */
+ public ValueResolver<T> timeout(Duration timeout) {
+ this.timeout = timeout;
+ return this;
+ }
+
+ protected void checkTypeNotNull() {
+ if (type==null)
+ throw new NullPointerException("type must be set to resolve, for '"+value+"'"+(description!=null ? ", "+description : ""));
+ }
+
+ public T get() {
+ return getMaybe().get();
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public Maybe<T> getMaybe() {
+ if (started.getAndSet(true))
+ throw new IllegalStateException("ValueResolver can only be used once");
+
+ if (expired) return Maybe.absent("Nested resolution of "+getOriginalValue()+" did not complete within "+timeout);
+
+ CountdownTimer timerU = parentTimer;
+ if (timerU==null && timeout!=null)
+ timerU = timeout.countdownTimer();
+ final CountdownTimer timer = timerU;
+ if (timer!=null && !timer.isRunning())
+ timer.start();
+
+ checkTypeNotNull();
+ Object v = this.value;
+
+ //if the expected type is a closure or map and that's what we have, we're done (or if it's null);
+ //but not allowed to return a future or DeferredSupplier as the resolved value
+ if (v==null || (!forceDeep && type.isInstance(v) && !Future.class.isInstance(v) && !DeferredSupplier.class.isInstance(v)))
+ return Maybe.of((T) v);
+
+ try {
+ //if it's a task or a future, we wait for the task to complete
+ if (v instanceof TaskAdaptable<?>) {
+ //if it's a task, we make sure it is submitted
+ if (!((TaskAdaptable<?>) v).asTask().isSubmitted() ) {
+ // TODO could try to get exec context from Tasks.current() ... should we?
+ if (exec==null)
+ return Maybe.absent("Value for unsubmitted task '"+getDescription()+"' requested but no execution context available");
+ exec.submit(((TaskAdaptable<?>) v).asTask());
+ }
+ }
+
+ if (v instanceof Future) {
+ final Future<?> vfuture = (Future<?>) v;
+
+ //including tasks, above
+ if (!vfuture.isDone()) {
+ Callable<Maybe> callable = new Callable<Maybe>() {
+ public Maybe call() throws Exception {
+ return Durations.get(vfuture, timer);
+ } };
+
+ String description = getDescription();
+ Maybe vm = Tasks.withBlockingDetails("Waiting for "+description, callable);
+ if (vm.isAbsent()) return vm;
+ v = vm.get();
+
+ } else {
+ v = vfuture.get();
+
+ }
+
+ } else if (v instanceof DeferredSupplier<?>) {
+ final Object vf = v;
+ Callable<Object> callable = new Callable<Object>() {
+ public Object call() throws Exception {
+ return ((DeferredSupplier<?>) vf).get();
+ } };
+
+ if (Boolean.TRUE.equals(embedResolutionInTask) || timeout!=null) {
+ if (exec==null)
+ return Maybe.absent("Embedding in task needed for '"+getDescription()+"' but no execution context available");
+
+ String description = getDescription();
+ Task<Object> vt = exec.submit(Tasks.<Object>builder().body(callable).name("Resolving dependent value").description(description).build());
+ Maybe<Object> vm = Durations.get(vt, timer);
+ vt.cancel(true);
+ if (vm.isAbsent()) return (Maybe<T>)vm;
+ v = vm.get();
+
+ } else {
+ v = callable.call();
+
+ }
+
+ } else if (v instanceof Map) {
+ //and if a map or list we look inside
+ Map result = Maps.newLinkedHashMap();
+ for (Map.Entry<?,?> entry : ((Map<?,?>)v).entrySet()) {
+ Maybe<?> vv = new ValueResolver(entry.getValue(), type, this)
+ .description( (description!=null ? description+", " : "") + "map entry "+entry.getKey() )
+ .getMaybe();
+ if (vv.isAbsent()) return (Maybe<T>)vv;
+ result.put(entry.getKey(), vv.get());
+ }
+ return Maybe.of((T) result);
+
+ } else if (v instanceof Set) {
+ Set result = Sets.newLinkedHashSet();
+ int count = 0;
+ for (Object it : (Set)v) {
+ Maybe<?> vv = new ValueResolver(it, type, this)
+ .description( (description!=null ? description+", " : "") + "entry "+count )
+ .getMaybe();
+ if (vv.isAbsent()) return (Maybe<T>)vv;
+ result.add(vv.get());
+ count++;
+ }
+ return Maybe.of((T) result);
+
+ } else if (v instanceof Iterable) {
+ List result = Lists.newArrayList();
+ int count = 0;
+ for (Object it : (Iterable)v) {
+ Maybe<?> vv = new ValueResolver(it, type, this)
+ .description( (description!=null ? description+", " : "") + "entry "+count )
+ .getMaybe();
+ if (vv.isAbsent()) return (Maybe<T>)vv;
+ result.add(vv.get());
+ count++;
+ }
+ return Maybe.of((T) result);
+
+ } else {
+ return TypeCoercions.tryCoerce(v, TypeToken.of(type));
+ }
+
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Error resolving "+(description!=null ? description+", " : "")+v+", in "+exec+": "+e, e);
+ }
+
+ return new ValueResolver(v, type, this).getMaybe();
+ }
+
+ protected String getDescription() {
+ return description!=null ? description : ""+value;
+ }
+ protected Object getOriginalValue() {
+ if (parentOriginalValue!=null) return parentOriginalValue;
+ return value;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/05a39488/core/src/test/java/brooklyn/util/task/TasksTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/task/TasksTest.java b/core/src/test/java/brooklyn/util/task/TasksTest.java
index 2d53a1e..8ba61e0 100644
--- a/core/src/test/java/brooklyn/util/task/TasksTest.java
+++ b/core/src/test/java/brooklyn/util/task/TasksTest.java
@@ -88,6 +88,7 @@ public class TasksTest extends BrooklynAppUnitTestSupport {
assertResolvesValue(orig, String.class, expected);
}
+ @SuppressWarnings("unchecked")
@Test
public void testResolvesIterableOfMapsWithAttributeWhenReady() throws Exception {
app.setAttribute(TestApplication.MY_ATTRIBUTE, "myval");
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/05a39488/core/src/test/java/brooklyn/util/task/ValueResolverTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/task/ValueResolverTest.java b/core/src/test/java/brooklyn/util/task/ValueResolverTest.java
new file mode 100644
index 0000000..43c156c
--- /dev/null
+++ b/core/src/test/java/brooklyn/util/task/ValueResolverTest.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 brooklyn.util.task;
+
+import java.util.concurrent.Callable;
+
+import org.junit.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.BrooklynAppUnitTestSupport;
+import brooklyn.management.ExecutionContext;
+import brooklyn.management.Task;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+/**
+ * see also {@link TasksTest} for more tests
+ */
+@Test
+public class ValueResolverTest extends BrooklynAppUnitTestSupport {
+
+ private ExecutionContext executionContext;
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ executionContext = app.getExecutionContext();
+ }
+
+ public static final Task<String> newSleepTask(final Duration timeout, final String result) {
+ return Tasks.<String>builder().body(new Callable<String>() {
+ public String call() {
+ Time.sleep(timeout);
+ return result;
+ }}
+ ).build();
+ }
+
+ public void testTimeoutZero() {
+ Maybe<String> result = Tasks.resolving(newSleepTask(Duration.TEN_SECONDS, "foo")).as(String.class).context(executionContext).timeout(Duration.ZERO).getMaybe();
+ Assert.assertFalse(result.isPresent());
+ }
+
+ public void testTimeoutBig() {
+ Maybe<String> result = Tasks.resolving(newSleepTask(Duration.ZERO, "foo")).as(String.class).context(executionContext).timeout(Duration.TEN_SECONDS).getMaybe();
+ Assert.assertEquals(result.get(), "foo");
+ }
+
+ public void testNoExecutionContextOnCompleted() {
+ Task<String> t = newSleepTask(Duration.ZERO, "foo");
+ executionContext.submit(t).getUnchecked();
+ Maybe<String> result = Tasks.resolving(t).as(String.class).timeout(Duration.ZERO).getMaybe();
+ Assert.assertEquals(result.get(), "foo");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/05a39488/usage/rest-server/src/main/java/brooklyn/rest/security/BrooklynPropertiesSecurityFilter.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/security/BrooklynPropertiesSecurityFilter.java b/usage/rest-server/src/main/java/brooklyn/rest/security/BrooklynPropertiesSecurityFilter.java
index bffa6a3..e5894f6 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/security/BrooklynPropertiesSecurityFilter.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/security/BrooklynPropertiesSecurityFilter.java
@@ -111,11 +111,10 @@ public class BrooklynPropertiesSecurityFilter implements Filter {
}
return;
} catch (Throwable e) {
- // NB errors are typically already caught at this point
- if (log.isDebugEnabled()) {
- log.debug("REST failed processing request " + uri + " with " + entitlementContext + ": " + e, e);
- }
- throw Exceptions.propagate(e);
+ // errors are typically already caught at this point, except for serialization errors
+ log.warn("REST failed processing request " + uri + " with " + entitlementContext + ": " + e, e);
+ ((HttpServletResponse) response).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ return;
} finally {
originalRequest.remove();
Entitlements.clearEntitlementContext();
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/05a39488/usage/rest-server/src/main/java/brooklyn/rest/transform/EffectorTransformer.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/transform/EffectorTransformer.java b/usage/rest-server/src/main/java/brooklyn/rest/transform/EffectorTransformer.java
index 89f3f02..1d15abe 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/transform/EffectorTransformer.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/transform/EffectorTransformer.java
@@ -24,10 +24,17 @@ import java.util.Set;
import javax.annotation.Nullable;
import brooklyn.entity.Effector;
+import brooklyn.entity.Entity;
import brooklyn.entity.ParameterType;
+import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.basic.EntityLocal;
import brooklyn.rest.domain.EffectorSummary;
import brooklyn.rest.domain.EffectorSummary.ParameterSummary;
+import brooklyn.rest.util.WebResourceUtils;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.task.Tasks;
+import brooklyn.util.time.Duration;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
@@ -36,7 +43,7 @@ import com.google.common.collect.Iterables;
public class EffectorTransformer {
- public static EffectorSummary effectorSummary(EntityLocal entity, Effector<?> effector) {
+ public static EffectorSummary effectorSummary(final EntityLocal entity, Effector<?> effector) {
String applicationUri = "/v1/applications/" + entity.getApplicationId();
String entityUri = applicationUri + "/entities/" + entity.getId();
return new EffectorSummary(effector.getName(), effector.getReturnTypeName(),
@@ -44,7 +51,7 @@ public class EffectorTransformer {
new Function<ParameterType<?>, EffectorSummary.ParameterSummary<?>>() {
@Override
public EffectorSummary.ParameterSummary<?> apply(@Nullable ParameterType<?> parameterType) {
- return parameterSummary(parameterType);
+ return parameterSummary(entity, parameterType);
}
})), effector.getDescription(), ImmutableMap.of(
"self", URI.create(entityUri + "/effectors/" + effector.getName()),
@@ -58,16 +65,23 @@ public class EffectorTransformer {
new Function<ParameterType<?>, EffectorSummary.ParameterSummary<?>>() {
@Override
public EffectorSummary.ParameterSummary<?> apply(ParameterType<?> parameterType) {
- return parameterSummary(parameterType);
+ return parameterSummary(null, parameterType);
}
}));
return new EffectorSummary(effector.getName(),
effector.getReturnTypeName(), parameters, effector.getDescription(), null);
}
- @SuppressWarnings("unchecked")
- protected static EffectorSummary.ParameterSummary<?> parameterSummary(ParameterType<?> parameterType) {
- return new ParameterSummary(parameterType.getName(), parameterType.getParameterClassName(),
- parameterType.getDescription(), parameterType.getDefaultValue());
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected static EffectorSummary.ParameterSummary<?> parameterSummary(Entity entity, ParameterType<?> parameterType) {
+ try {
+ Maybe<?> defaultValue = Tasks.resolving(parameterType.getDefaultValue()).as(parameterType.getParameterClass())
+ .context(entity!=null ? ((EntityInternal)entity).getExecutionContext() : null).timeout(Duration.millis(50)).getMaybe();
+ return new ParameterSummary(parameterType.getName(), parameterType.getParameterClassName(),
+ parameterType.getDescription(),
+ WebResourceUtils.getValueForDisplay(defaultValue.orNull(), true, false));
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
}
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/05a39488/utils/common/src/main/java/brooklyn/util/time/Durations.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/time/Durations.java b/utils/common/src/main/java/brooklyn/util/time/Durations.java
index b1fb6d2..60e77f4 100644
--- a/utils/common/src/main/java/brooklyn/util/time/Durations.java
+++ b/utils/common/src/main/java/brooklyn/util/time/Durations.java
@@ -19,7 +19,12 @@
package brooklyn.util.time;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
public class Durations {
@@ -30,5 +35,26 @@ public class Durations {
public static void join(Thread thread, Duration time) throws InterruptedException {
thread.join(time.toMillisecondsRoundingUp());
}
+
+ public static <T> Maybe<T> get(Future<T> t, Duration timeout) {
+ try {
+ if (timeout==null || timeout.toMilliseconds()<0 || Duration.PRACTICALLY_FOREVER.equals(timeout))
+ return Maybe.of(t.get());
+ if (timeout.toMilliseconds()==0 && !t.isDone())
+ return Maybe.absent("Task "+t+" not completed when immediate completion requested");
+ return Maybe.of(t.get(timeout.toMilliseconds(), TimeUnit.MILLISECONDS));
+ } catch (TimeoutException e) {
+ return Maybe.absent("Task "+t+" did not complete within "+timeout);
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ public static <T> Maybe<T> get(Future<T> t, CountdownTimer timer) {
+ if (timer==null) return get(t, (Duration)null);
+ Duration remaining = timer.getDurationRemaining();
+ if (remaining.isPositive()) return get(t, remaining);
+ return get(t, Duration.ZERO);
+ }
}
[02/17] git commit: Splits pillowfight into separate (referable) YAML
file, rebases on master
Posted by he...@apache.org.
Splits pillowfight into separate (referable) YAML file, rebases on master
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/fbb86438
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/fbb86438
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/fbb86438
Branch: refs/heads/master
Commit: fbb86438a19a693de25244d09bfe066e00d571c9
Parents: f2d05ff
Author: Martin Harris <gi...@nakomis.com>
Authored: Mon Aug 18 15:40:05 2014 +0100
Committer: Martin Harris <gi...@nakomis.com>
Committed: Mon Aug 18 15:40:05 2014 +0100
----------------------------------------------------------------------
.../launcher/src/test/resources/couchbase.yaml | 74 +---------------
.../src/test/resources/pillowfight.yaml | 91 ++++++++++++++++++++
2 files changed, 93 insertions(+), 72 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/fbb86438/usage/launcher/src/test/resources/couchbase.yaml
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/resources/couchbase.yaml b/usage/launcher/src/test/resources/couchbase.yaml
index f22d4f5..d2ae0ed 100644
--- a/usage/launcher/src/test/resources/couchbase.yaml
+++ b/usage/launcher/src/test/resources/couchbase.yaml
@@ -18,82 +18,12 @@
#
name: Couchbase
-location: aws-ec2:eu-west-1
+location: softlayer:ams01
services:
- type: brooklyn.entity.nosql.couchbase.CouchbaseCluster
adminUsername: Administrator
adminPassword: Password
initialSize: 3
-- type: brooklyn.entity.basic.VanillaSoftwareProcess
- name: CBC Pillowfight
- checkRunning.command: ""
- stop.command: ""
- launch.command: |
- sudo wget -O/etc/apt/sources.list.d/couchbase.list http://packages.couchbase.com/ubuntu/couchbase-ubuntu1204.list
- sudo wget -O- http://packages.couchbase.com/ubuntu/couchbase.key | sudo apt-key add -
- sudo apt-get update
- sudo apt-get install -y libcouchbase2-libevent libcouchbase-dev libcouchbase2-bin
- brooklyn.initializers:
- - type: brooklyn.entity.software.ssh.SshCommandEffector
- brooklyn.config:
- name: cbcPillowFight
- description: runs cbc pillowfight
- command: >
- cbc pillowfight
- `if [ -n "$host" ]; then echo -h $host; fi`
- `if [ -n "$bucket" ]; then echo -b $bucket; fi`
- `if [ -n "$username" ]; then echo -u $username; fi`
- `if [ -n "$password" ]; then echo -p $password; fi`
- `if [ -n "$iterations" ]; then echo -i $iterations; fi`
- `if [ -n "$numItems" ]; then echo -I $numItems; fi`
- `if [ -n "$keyPrefix" ]; then echo -p $keyPrefix; fi`
- `if [ -n "$numThreads" ]; then echo -t $numThreads; fi`
- `if [ -n "$numInstances" ]; then echo -Q $numInstances; fi`
- `if [ -n "$randomSeed" ]; then echo -s $randomSeed; fi`
- `if [ -n "$minSize" ]; then echo -m $minSize; fi`
- `if [ -n "$maxSize" ]; then echo -M $maxSize; fi`
- parameters:
- host:
- description: list of hosts to connect to
- defaultValue: 127.0.0.1:8091
- bucket:
- description: bucket to use
- defaultValue: default
- username:
- description: username used for authentication to the cluster
- password:
- description: password used for authentication to the cluster
- iterations:
- description: number of iterations to run
- defaultValue: 1000
- numItems:
- description: number of items to operate on
- defaultValue: 1000
- keyPrefix:
- description: prefix for keys
- numThreads:
- description: number of threads to use
- defaultValue: 1
- numInstances:
- description: number of connection instances to put into the shared connection pool
- defaultValue: 1
- randomSeed:
- description: random seed
- defaultValue: 0
- ratio:
- description: "specify SET/GET command ratio (default: 33, i.e. 33% SETs and 67% GETs)"
- defaultValue: 33
- minSize:
- description: minimum size of payload, i.e. document body
- defaultValue: 50
- maxSize:
- description: maximum size of payload, i.e. document body
- defaultValue: 5120
-# For CentOS, use the following launch command:
-# launch.command: |
-# sudo wget -O/etc/yum.repos.d/couchbase.repo http://packages.couchbase.com/rpm/couchbase-centos55-x86_64.repo
-# sudo yum check-update
-# sudo yum install -y libcouchbase2-libevent libcouchbase-devel libcouchbase2-bin
-
+- type: "classpath://pillowfight.yaml"
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/fbb86438/usage/launcher/src/test/resources/pillowfight.yaml
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/resources/pillowfight.yaml b/usage/launcher/src/test/resources/pillowfight.yaml
new file mode 100644
index 0000000..9442725
--- /dev/null
+++ b/usage/launcher/src/test/resources/pillowfight.yaml
@@ -0,0 +1,91 @@
+#
+# 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.
+#
+services:
+- type: brooklyn.entity.basic.VanillaSoftwareProcess
+ name: CBC Pillowfight
+ checkRunning.command: ""
+ stop.command: ""
+ launch.command: |
+ sudo wget -O/etc/apt/sources.list.d/couchbase.list http://packages.couchbase.com/ubuntu/couchbase-ubuntu1204.list
+ sudo wget -O- http://packages.couchbase.com/ubuntu/couchbase.key | sudo apt-key add -
+ sudo apt-get update
+ sudo apt-get install -y libcouchbase2-libevent libcouchbase-dev libcouchbase2-bin
+ brooklyn.initializers:
+ - type: brooklyn.entity.software.ssh.SshCommandEffector
+ brooklyn.config:
+ name: cbcPillowFight
+ description: runs cbc pillowfight
+ command: >
+ cbc pillowfight
+ `if [ -n "$host" ]; then echo -h $host; fi`
+ `if [ -n "$bucket" ]; then echo -b $bucket; fi`
+ `if [ -n "$username" ]; then echo -u $username; fi`
+ `if [ -n "$password" ]; then echo -p $password; fi`
+ `if [ -n "$iterations" ]; then echo -i $iterations; fi`
+ `if [ -n "$numItems" ]; then echo -I $numItems; fi`
+ `if [ -n "$keyPrefix" ]; then echo -p $keyPrefix; fi`
+ `if [ -n "$numThreads" ]; then echo -t $numThreads; fi`
+ `if [ -n "$numInstances" ]; then echo -Q $numInstances; fi`
+ `if [ -n "$randomSeed" ]; then echo -s $randomSeed; fi`
+ `if [ -n "$minSize" ]; then echo -m $minSize; fi`
+ `if [ -n "$maxSize" ]; then echo -M $maxSize; fi`
+ parameters:
+ host:
+ description: list of hosts to connect to
+ defaultValue: 127.0.0.1:8091
+ bucket:
+ description: bucket to use
+ defaultValue: default
+ username:
+ description: username used for authentication to the cluster
+ password:
+ description: password used for authentication to the cluster
+ iterations:
+ description: number of iterations to run
+ defaultValue: 1000
+ numItems:
+ description: number of items to operate on
+ defaultValue: 1000
+ keyPrefix:
+ description: prefix for keys
+ numThreads:
+ description: number of threads to use
+ defaultValue: 1
+ numInstances:
+ description: number of connection instances to put into the shared connection pool
+ defaultValue: 1
+ randomSeed:
+ description: random seed
+ defaultValue: 0
+ ratio:
+ description: "specify SET/GET command ratio (default: 33, i.e. 33% SETs and 67% GETs)"
+ defaultValue: 33
+ minSize:
+ description: minimum size of payload, i.e. document body
+ defaultValue: 50
+ maxSize:
+ description: maximum size of payload, i.e. document body
+ defaultValue: 5120
+
+# For CentOS, use the following launch command:
+# launch.command: |
+# sudo wget -O/etc/yum.repos.d/couchbase.repo http://packages.couchbase.com/rpm/couchbase-centos55-x86_64.repo
+# sudo yum check-update
+# sudo yum install -y libcouchbase2-libevent libcouchbase-devel libcouchbase2-bin
+
\ No newline at end of file
[08/17] git commit: This closes #1
Posted by he...@apache.org.
This closes #1
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/c720e8c8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/c720e8c8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/c720e8c8
Branch: refs/heads/master
Commit: c720e8c80d66e145ab6c0c9160f2fa83c278c42d
Parents: 761f471 fbb8643
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Aug 29 19:01:15 2014 -0400
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Aug 29 19:01:15 2014 -0400
----------------------------------------------------------------------
.../nosql/couchbase/CouchbaseLoadGenerator.java | 59 ---------
.../couchbase/CouchbaseLoadGeneratorDriver.java | 28 -----
.../couchbase/CouchbaseLoadGeneratorImpl.java | 50 --------
.../CouchbaseLoadGeneratorSshDriver.java | 122 -------------------
.../launcher/src/test/resources/couchbase.yaml | 7 +-
.../src/test/resources/pillowfight.yaml | 91 ++++++++++++++
6 files changed, 96 insertions(+), 261 deletions(-)
----------------------------------------------------------------------
[14/17] git commit: add overridable doStart to DynamicClusterImpl to
facilitate custom logic to happen before expected state is RUNNING;
add a service problem-indicator rather than setting expected state ON_FIRE,
and wait for queued tasks to complete bef
Posted by he...@apache.org.
add overridable doStart to DynamicClusterImpl to facilitate custom logic to happen before expected state is RUNNING;
add a service problem-indicator rather than setting expected state ON_FIRE, and wait for queued tasks to complete before setting expected state RUNNING
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/f51710de
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/f51710de
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/f51710de
Branch: refs/heads/master
Commit: f51710de18fad107810670d569cbe6efc68aa56f
Parents: df971f5
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Aug 28 22:32:12 2014 -0400
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Sep 1 17:07:01 2014 +0100
----------------------------------------------------------------------
.../entity/group/DynamicClusterImpl.java | 126 ++++++++++---------
1 file changed, 67 insertions(+), 59 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f51710de/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java b/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
index 553d453..647ddaa 100644
--- a/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
+++ b/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
@@ -36,12 +36,12 @@ import org.slf4j.LoggerFactory;
import brooklyn.entity.Entity;
import brooklyn.entity.basic.AbstractGroupImpl;
-import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityFactory;
import brooklyn.entity.basic.EntityFactoryForLocation;
import brooklyn.entity.basic.Lifecycle;
import brooklyn.entity.basic.QuorumCheck.QuorumChecks;
+import brooklyn.entity.basic.ServiceStateLogic.ServiceProblemsLogic;
import brooklyn.entity.basic.ServiceStateLogic;
import brooklyn.entity.effector.Effectors;
import brooklyn.entity.proxying.EntitySpec;
@@ -260,71 +260,79 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus
}
ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING);
+ ServiceProblemsLogic.clearProblemsIndicator(this, START);
try {
- if (isQuarantineEnabled()) {
- QuarantineGroup quarantineGroup = getAttribute(QUARANTINE_GROUP);
- if (quarantineGroup==null || !Entities.isManaged(quarantineGroup)) {
- quarantineGroup = addChild(EntitySpec.create(QuarantineGroup.class).displayName("quarantine"));
- Entities.manage(quarantineGroup);
- setAttribute(QUARANTINE_GROUP, quarantineGroup);
- }
- }
-
- int initialSize = getConfig(INITIAL_SIZE).intValue();
- int initialQuorumSize = getInitialQuorumSize();
+ doStart();
+ DynamicTasks.waitForLast();
+
+ } catch (Exception e) {
+ ServiceProblemsLogic.updateProblemsIndicator(this, START, "start failed with error: "+e);
+ throw Exceptions.propagate(e);
+ } finally {
+ ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING);
+ }
+ }
- try {
- resize(initialSize);
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- // apart from logging, ignore problems here; we extract them below
- LOG.debug("Error resizing "+this+" to size "+initialSize+" (collecting and handling): "+e, e);
+ protected void doStart() {
+ if (isQuarantineEnabled()) {
+ QuarantineGroup quarantineGroup = getAttribute(QUARANTINE_GROUP);
+ if (quarantineGroup==null || !Entities.isManaged(quarantineGroup)) {
+ quarantineGroup = addChild(EntitySpec.create(QuarantineGroup.class).displayName("quarantine"));
+ Entities.manage(quarantineGroup);
+ setAttribute(QUARANTINE_GROUP, quarantineGroup);
}
+ }
- Iterable<Task<?>> failed = Tasks.failed(Tasks.children(Tasks.current()));
- Iterator<Task<?>> fi = failed.iterator();
- boolean noFailed=true, severalFailed=false;
- if (fi.hasNext()) {
- noFailed = false;
- fi.next();
- if (fi.hasNext())
- severalFailed = true;
- }
+ int initialSize = getConfig(INITIAL_SIZE).intValue();
+ int initialQuorumSize = getInitialQuorumSize();
- int currentSize = getCurrentSize().intValue();
- if (currentSize < initialQuorumSize) {
- String message;
- if (currentSize == 0 && !noFailed) {
- if (severalFailed)
- message = "All nodes in cluster "+this+" failed";
- else
- message = "Node in cluster "+this+" failed";
- } else {
- message = "On start of cluster " + this + ", failed to get to initial size of " + initialSize
- + "; size is " + getCurrentSize()
- + (initialQuorumSize != initialSize ? " (initial quorum size is " + initialQuorumSize + ")" : "");
- }
- Throwable firstError = Tasks.getError(Maybe.next(failed.iterator()).orNull());
- if (firstError!=null) {
- if (severalFailed)
- message += "; first failure is: "+Exceptions.collapseText(firstError);
- else
- message += ": "+Exceptions.collapseText(firstError);
- }
- throw new IllegalStateException(message, firstError);
- } else if (currentSize < initialSize) {
- LOG.warn(
- "On start of cluster {}, size {} reached initial minimum quorum size of {} but did not reach desired size {}; continuing",
- new Object[] { this, currentSize, initialQuorumSize, initialSize });
+ try {
+ resize(initialSize);
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ // apart from logging, ignore problems here; we extract them below
+ LOG.debug("Error resizing "+this+" to size "+initialSize+" (collecting and handling): "+e, e);
+ }
+
+ Iterable<Task<?>> failed = Tasks.failed(Tasks.children(Tasks.current()));
+ Iterator<Task<?>> fi = failed.iterator();
+ boolean noFailed=true, severalFailed=false;
+ if (fi.hasNext()) {
+ noFailed = false;
+ fi.next();
+ if (fi.hasNext())
+ severalFailed = true;
+ }
+
+ int currentSize = getCurrentSize().intValue();
+ if (currentSize < initialQuorumSize) {
+ String message;
+ if (currentSize == 0 && !noFailed) {
+ if (severalFailed)
+ message = "All nodes in cluster "+this+" failed";
+ else
+ message = "Node in cluster "+this+" failed";
+ } else {
+ message = "On start of cluster " + this + ", failed to get to initial size of " + initialSize
+ + "; size is " + getCurrentSize()
+ + (initialQuorumSize != initialSize ? " (initial quorum size is " + initialQuorumSize + ")" : "");
}
-
- for (Policy it : getPolicies()) {
- it.resume();
+ Throwable firstError = Tasks.getError(Maybe.next(failed.iterator()).orNull());
+ if (firstError!=null) {
+ if (severalFailed)
+ message += "; first failure is: "+Exceptions.collapseText(firstError);
+ else
+ message += ": "+Exceptions.collapseText(firstError);
}
- ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING);
- } catch (Exception e) {
- ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE);
- throw Exceptions.propagate(e);
+ throw new IllegalStateException(message, firstError);
+ } else if (currentSize < initialSize) {
+ LOG.warn(
+ "On start of cluster {}, size {} reached initial minimum quorum size of {} but did not reach desired size {}; continuing",
+ new Object[] { this, currentSize, initialQuorumSize, initialSize });
+ }
+
+ for (Policy it : getPolicies()) {
+ it.resume();
}
}
[15/17] git commit: publish connection url sensor, use that in
pillowfight;
and ensure nodes have their public hostname, since previously the first node
uses its private ip and thus rebalance and other REST commands don't work
reliably, fixing rebalance;
Posted by he...@apache.org.
publish connection url sensor, use that in pillowfight; and ensure nodes have their public hostname, since previously the first node uses its private ip and thus rebalance and other REST commands don't work reliably, fixing rebalance; and use better timings so it starts faster. now couchbase w pillowfight working very nicely
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/1064cd5d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/1064cd5d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/1064cd5d
Branch: refs/heads/master
Commit: 1064cd5df9cd3c49856efea7a1622745b0dd4ea6
Parents: 94bf299
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Aug 28 22:36:06 2014 -0400
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Sep 1 17:07:28 2014 +0100
----------------------------------------------------------------------
.../main/java/brooklyn/util/http/HttpTool.java | 9 +-
.../brooklynnode/BrooklynEntityMirrorImpl.java | 3 +-
.../nosql/couchbase/CouchbaseCluster.java | 9 +-
.../nosql/couchbase/CouchbaseClusterImpl.java | 98 ++++++++++++++------
.../nosql/couchbase/CouchbaseNodeImpl.java | 49 ++++++++++
.../nosql/couchbase/CouchbaseNodeSshDriver.java | 30 +++---
.../entity/nosql/couchbase/pillowfight.yaml | 74 ++++++---------
.../src/test/resources/couchbase-w-loadgen.yaml | 54 +++++++++++
.../test/resources/couchbase-w-pillowfight.yaml | 35 +++++++
.../launcher/src/test/resources/couchbase.yaml | 13 ++-
10 files changed, 280 insertions(+), 94 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1064cd5d/core/src/main/java/brooklyn/util/http/HttpTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/http/HttpTool.java b/core/src/main/java/brooklyn/util/http/HttpTool.java
index 440f699..61a5b7a 100644
--- a/core/src/main/java/brooklyn/util/http/HttpTool.java
+++ b/core/src/main/java/brooklyn/util/http/HttpTool.java
@@ -26,12 +26,14 @@ import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;
+import org.apache.commons.codec.binary.Base64;
import org.apache.http.ConnectionReuseStrategy;
import org.apache.http.HttpEntity;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
@@ -159,7 +161,8 @@ public class HttpTool {
return this;
}
public HttpClient build() {
- final DefaultHttpClient httpClient = new DefaultHttpClient(clientConnectionManager, httpParams);
+ final DefaultHttpClient httpClient = new DefaultHttpClient(clientConnectionManager);
+ httpClient.setParams(httpParams);
// support redirects for POST (similar to `curl --post301 -L`)
// http://stackoverflow.com/questions/3658721/httpclient-4-error-302-how-to-redirect
@@ -327,4 +330,8 @@ public class HttpTool {
public static boolean isStatusCodeHealthy(int code) { return (code>=200 && code<=299); }
+ public static String toBasicAuthorizationValue(UsernamePasswordCredentials credentials) {
+ return "Basic "+Base64.encodeBase64String( (credentials.getUserName()+":"+credentials.getPassword()).getBytes() );
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1064cd5d/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorImpl.java b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorImpl.java
index 24c3eeb..2743e54 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorImpl.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorImpl.java
@@ -53,6 +53,7 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Suppliers;
+import com.google.common.net.MediaType;
import com.google.gson.Gson;
public class BrooklynEntityMirrorImpl extends AbstractEntity implements BrooklynEntityMirror {
@@ -137,7 +138,7 @@ public class BrooklynEntityMirrorImpl extends AbstractEntity implements Brooklyn
HttpToolResponse result = null;
byte[] content;
try {
- result = HttpTool.httpPost(client, uri, MutableMap.of(com.google.common.net.HttpHeaders.CONTENT_TYPE, "application/json"),
+ result = HttpTool.httpPost(client, uri, MutableMap.of(com.google.common.net.HttpHeaders.CONTENT_TYPE, MediaType.JSON_UTF_8.toString()),
Jsonya.of(args).toString().getBytes());
content = result.getContent();
} catch (Exception e) {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1064cd5d/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseCluster.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseCluster.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseCluster.java
index c478b07..25a2b8d 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseCluster.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseCluster.java
@@ -56,14 +56,17 @@ public interface CouchbaseCluster extends DynamicCluster {
-1);
@SetFromFlag("delayBeforeAdvertisingCluster")
- ConfigKey<Duration> DELAY_BEFORE_ADVERTISING_CLUSTER = ConfigKeys.newConfigKey(Duration.class, "couchbase.cluster.delayBeforeAdvertisingCluster", "Delay after cluster is started before checking and advertising its availability", Duration.THIRTY_SECONDS);
+ ConfigKey<Duration> DELAY_BEFORE_ADVERTISING_CLUSTER = ConfigKeys.newConfigKey(Duration.class, "couchbase.cluster.delayBeforeAdvertisingCluster", "Delay after cluster is started before checking and advertising its availability", Duration.TEN_SECONDS);
- @SetFromFlag("serviceUpTimeOut")
- ConfigKey<Duration> SERVICE_UP_TIME_OUT = ConfigKeys.newConfigKey(Duration.class, "couchbase.cluster.serviceUpTimeOut", "Service up time out duration for all the couchbase nodes", Duration.seconds(3 * 60));
+ // TODO not sure if this is needed; previously waited 3m (SERVICE_UP_TIME_OUT) but that seems absurdly long
+ @SetFromFlag("postStartStabilizationDelay")
+ ConfigKey<Duration> NODES_STARTED_STABILIZATION_DELAY = ConfigKeys.newConfigKey(Duration.class, "couchbase.cluster.postStartStabilizationDelay", "Delay after nodes have been started before treating it as a cluster", Duration.TEN_SECONDS);
@SuppressWarnings("serial")
AttributeSensor<List<String>> COUCHBASE_CLUSTER_UP_NODE_ADDRESSES = Sensors.newSensor(new TypeToken<List<String>>() {},
"couchbase.cluster.node.addresses", "List of host:port of all active nodes in the cluster (http admin port, and public hostname/IP)");
+ AttributeSensor<String> COUCHBASE_CLUSTER_CONNECTION_URL = Sensors.newStringSensor(
+ "couchbase.cluster.connection.url", "Couchbase-style URL to connect to the cluster (e.g. http://127.0.0.1:8091/ or couchbase://10.0.0.1,10.0.0.2/)");
// Interesting stats
AttributeSensor<Double> OPS_PER_NODE = Sensors.newDoubleSensor("couchbase.stats.cluster.per.node.ops",
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1064cd5d/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
index 69b038a..6abf2f7 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
@@ -20,7 +20,6 @@ package brooklyn.entity.nosql.couchbase;
import static brooklyn.util.JavaGroovyEquivalents.groovyTruth;
-import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -37,7 +36,6 @@ import brooklyn.entity.Entity;
import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
-import brooklyn.entity.basic.Lifecycle;
import brooklyn.entity.basic.QuorumCheck;
import brooklyn.entity.basic.ServiceStateLogic;
import brooklyn.entity.group.AbstractMembershipTrackingPolicy;
@@ -50,14 +48,18 @@ import brooklyn.event.feed.http.HttpFeed;
import brooklyn.event.feed.http.HttpPollConfig;
import brooklyn.event.feed.http.HttpValueFunctions;
import brooklyn.event.feed.http.JsonFunctions;
-import brooklyn.location.Location;
import brooklyn.policy.PolicySpec;
+import brooklyn.util.collections.CollectionFunctionals;
import brooklyn.util.collections.MutableSet;
+import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Functionals;
+import brooklyn.util.guava.IfFunctions;
+import brooklyn.util.math.MathPredicates;
import brooklyn.util.task.DynamicTasks;
import brooklyn.util.task.TaskBuilder;
import brooklyn.util.task.Tasks;
import brooklyn.util.text.ByteSizeStrings;
+import brooklyn.util.text.StringFunctions;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Time;
@@ -87,17 +89,23 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
.transforming(COUCHBASE_CLUSTER_UP_NODES)
.from(this)
.publishing(COUCHBASE_CLUSTER_UP_NODE_ADDRESSES)
- .computing(new Function<Set<Entity>, List<String>>() {
- @Override public List<String> apply(Set<Entity> input) {
- List<String> addresses = Lists.newArrayList();
- for (Entity entity : input) {
- addresses.add(String.format("%s:%s", entity.getAttribute(Attributes.ADDRESS),
- entity.getAttribute(CouchbaseNode.COUCHBASE_WEB_ADMIN_PORT)));
- }
- return addresses;
- }
- }).build()
- );
+ .computing(new ListOfHostAndPort()).build() );
+ addEnricher(
+ Enrichers.builder()
+ .transforming(COUCHBASE_CLUSTER_UP_NODE_ADDRESSES)
+ .from(this)
+ .publishing(COUCHBASE_CLUSTER_CONNECTION_URL)
+ .computing(
+ IfFunctions.<List<String>>ifPredicate(
+ Predicates.compose(MathPredicates.lessThan(getConfig(CouchbaseCluster.INITIAL_QUORUM_SIZE)),
+ CollectionFunctionals.sizeFunction(0)) )
+ .value((String)null)
+ .defaultApply(
+ Functionals.chain(
+ CollectionFunctionals.<String,List<String>>limit(4),
+ StringFunctions.joiner(","),
+ StringFunctions.formatter("http://%s/"))) )
+ .build() );
Map<? extends AttributeSensor<? extends Number>, ? extends AttributeSensor<? extends Number>> enricherSetup =
ImmutableMap.<AttributeSensor<? extends Number>, AttributeSensor<? extends Number>>builder()
@@ -143,19 +151,22 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
}
@Override
- public void start(Collection<? extends Location> locations) {
- super.start(locations);
+ protected void doStart() {
+ super.doStart();
connectSensors();
setAttribute(BUCKET_CREATION_IN_PROGRESS, false);
//start timeout before adding the servers
- Time.sleep(getConfig(SERVICE_UP_TIME_OUT));
+ Tasks.setBlockingDetails("Pausing while Couchbase stabilizes");
+ Time.sleep(getConfig(NODES_STARTED_STABILIZATION_DELAY));
Optional<Set<Entity>> upNodes = Optional.<Set<Entity>>fromNullable(getAttribute(COUCHBASE_CLUSTER_UP_NODES));
if (upNodes.isPresent() && !upNodes.get().isEmpty()) {
+ Tasks.setBlockingDetails("Adding servers to Couchbase");
+
//TODO: select a new primary node if this one fails
Entity primaryNode = upNodes.get().iterator().next();
((EntityInternal) primaryNode).setAttribute(CouchbaseNode.IS_PRIMARY_NODE, true);
@@ -178,9 +189,16 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
((CouchbaseNode)getPrimaryNode()).rebalance();
- if (Optional.fromNullable(CREATE_BUCKETS).isPresent()) {
- createBuckets();
- DependentConfiguration.waitInTaskForAttributeReady(this, CouchbaseCluster.BUCKET_CREATION_IN_PROGRESS, Predicates.equalTo(false));
+ if (getConfig(CREATE_BUCKETS)!=null) {
+ try {
+ Tasks.setBlockingDetails("Creating buckets in Couchbase");
+
+ createBuckets();
+ DependentConfiguration.waitInTaskForAttributeReady(this, CouchbaseCluster.BUCKET_CREATION_IN_PROGRESS, Predicates.equalTo(false));
+
+ } finally {
+ Tasks.resetBlockingDetails();
+ }
}
setAttribute(IS_CLUSTER_INITIALIZED, true);
@@ -190,9 +208,8 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
//check Repeater.
}
} else {
- ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE);
+ throw new IllegalStateException("No up nodes available after starting");
}
-
}
@Override
@@ -209,6 +226,17 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
.configure("group", this));
}
+ private final static class ListOfHostAndPort implements Function<Set<Entity>, List<String>> {
+ @Override public List<String> apply(Set<Entity> input) {
+ List<String> addresses = Lists.newArrayList();
+ for (Entity entity : input) {
+ addresses.add(String.format("%s:%s", entity.getAttribute(Attributes.ADDRESS),
+ entity.getAttribute(CouchbaseNode.COUCHBASE_WEB_ADMIN_PORT)));
+ }
+ return addresses;
+ }
+ }
+
public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
@Override protected void onEntityChange(Entity member) {
((CouchbaseClusterImpl)entity).onServerPoolMemberChanged(member);
@@ -311,14 +339,25 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
@Override
protected void initEnrichers() {
+ addEnricher(Enrichers.builder().updatingMap(ServiceStateLogic.SERVICE_NOT_UP_INDICATORS)
+ .from(COUCHBASE_CLUSTER_UP_NODES)
+ .computing(new Function<Set<Entity>, Object>() {
+ @Override
+ public Object apply(Set<Entity> input) {
+ if (input==null) return "Couchbase up nodes not set";
+ if (input.isEmpty()) return "No Couchbase up nodes";
+ if (input.size() < getQuorumSize()) return "Couchbase up nodes not quorate";
+ return null;
+ }
+ }).build());
+
if (getConfigRaw(UP_QUORUM_CHECK, false).isAbsent()) {
class CouchbaseQuorumCheck implements QuorumCheck {
@Override
public boolean isQuorate(int sizeHealthy, int totalSize) {
// check members count passed in AND the sensor
if (sizeHealthy < getQuorumSize()) return false;
- Set<Entity> upNodes = getAttribute(COUCHBASE_CLUSTER_UP_NODES);
- return (upNodes != null && !upNodes.isEmpty() && upNodes.size() >= getQuorumSize());
+ return true;
}
}
setConfig(UP_QUORUM_CHECK, new CouchbaseQuorumCheck());
@@ -370,7 +409,8 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
for (Map<String, Object> bucketMap : bucketsToCreate) {
String bucketName = bucketMap.containsKey("bucket") ? (String) bucketMap.get("bucket") : "default";
String bucketType = bucketMap.containsKey("bucket-type") ? (String) bucketMap.get("bucket-type") : "couchbase";
- Integer bucketPort = bucketMap.containsKey("bucket-port") ? (Integer) bucketMap.get("bucket-port") : 11222;
+ // default bucket must be on this port; other buckets can (must) specify their own (unique) port
+ Integer bucketPort = bucketMap.containsKey("bucket-port") ? (Integer) bucketMap.get("bucket-port") : 11211;
Integer bucketRamSize = bucketMap.containsKey("bucket-ramsize") ? (Integer) bucketMap.get("bucket-ramsize") : 200;
Integer bucketReplica = bucketMap.containsKey("bucket-replica") ? (Integer) bucketMap.get("bucket-replica") : 1;
@@ -415,9 +455,13 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
.onFailureOrException(new Function<Object, Boolean>() {
@Override
public Boolean apply(Object input) {
- if (((brooklyn.util.http.HttpToolResponse) input).getResponseCode() == 404) {
- return true;
+ if (input instanceof brooklyn.util.http.HttpToolResponse) {
+ if (((brooklyn.util.http.HttpToolResponse) input).getResponseCode() == 404) {
+ return true;
+ }
}
+ if (input instanceof Throwable)
+ Exceptions.propagate((Throwable)input);
throw new IllegalStateException("Unexpected response when creating bucket:" + input);
}
}))
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1064cd5d/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java
index 11e36bc..80d563f 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java
@@ -20,10 +20,15 @@ package brooklyn.entity.nosql.couchbase;
import static java.lang.String.format;
+import java.net.URI;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.SoftwareProcessImpl;
import brooklyn.event.AttributeSensor;
@@ -36,22 +41,29 @@ import brooklyn.event.feed.http.JsonFunctions;
import brooklyn.location.MachineProvisioningLocation;
import brooklyn.location.access.BrooklynAccessUtils;
import brooklyn.location.cloud.CloudLocationConfig;
+import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.config.ConfigBag;
+import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Functionals;
import brooklyn.util.guava.MaybeFunctions;
import brooklyn.util.guava.TypeTokens;
+import brooklyn.util.http.HttpTool;
import brooklyn.util.http.HttpToolResponse;
+import brooklyn.util.net.Urls;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Preconditions;
import com.google.common.net.HostAndPort;
+import com.google.common.net.MediaType;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
public class CouchbaseNodeImpl extends SoftwareProcessImpl implements CouchbaseNode {
+ private static final Logger log = LoggerFactory.getLogger(CouchbaseNodeImpl.class);
+
HttpFeed httpFeed;
@Override
@@ -140,6 +152,43 @@ public class CouchbaseNodeImpl extends SoftwareProcessImpl implements CouchbaseN
.onFailureOrException(Functions.<T>constant(null));
}
+ @Override
+ protected void postStart() {
+ super.postStart();
+ renameServerToPublicHostname();
+ }
+
+ protected void renameServerToPublicHostname() {
+ // http://docs.couchbase.com/couchbase-manual-2.5/cb-install/#couchbase-getting-started-hostnames
+ URI apiUri = null;
+ try {
+ String hostname = getAttribute(Attributes.HOSTNAME);
+ String port = ""+getAttribute(COUCHBASE_WEB_ADMIN_PORT);
+ apiUri = new URI("http://"+hostname+":"+port+"/node/controller/rename");
+ UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(
+ getConfig(COUCHBASE_ADMIN_USERNAME), getConfig(COUCHBASE_ADMIN_PASSWORD));
+ HttpToolResponse response = HttpTool.httpPost(HttpTool.httpClientBuilder()
+ // the uri is required by the HttpClientBuilder in order to set the AuthScope of the credentials
+ .uri(apiUri)
+ .credentials(credentials)
+ .build(),
+ apiUri,
+ MutableMap.of(
+ com.google.common.net.HttpHeaders.CONTENT_TYPE, MediaType.FORM_DATA.toString(),
+ com.google.common.net.HttpHeaders.ACCEPT, "*/*",
+ // this appears needed; without it we get org.apache.http.NoHttpResponseException !?
+ com.google.common.net.HttpHeaders.AUTHORIZATION, HttpTool.toBasicAuthorizationValue(credentials)),
+ ("hostname="+Urls.encode(hostname)).getBytes());
+ log.debug("Renamed Couchbase server "+this+" via "+apiUri+": "+response);
+ if (!HttpTool.isStatusCodeHealthy(response.getResponseCode())) {
+ log.warn("Invalid response code, renaming "+apiUri+": "+response);
+ }
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ log.warn("Error renaming server, using "+apiUri+": "+e, e);
+ }
+ }
+
public void connectSensors() {
super.connectSensors();
connectServiceUpIsRunning();
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1064cd5d/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
index 67fa30a..6dc3cfb 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
@@ -195,7 +195,7 @@ public class CouchbaseNodeSshDriver extends AbstractSoftwareProcessSshDriver imp
}
private String getWebPort() {
- return entity.getConfig(CouchbaseNode.COUCHBASE_WEB_ADMIN_PORT).iterator().next().toString();
+ return ""+entity.getAttribute(CouchbaseNode.COUCHBASE_WEB_ADMIN_PORT);
}
private String getCouchbaseHostnameAndCredentials() {
@@ -209,25 +209,27 @@ public class CouchbaseNodeSshDriver extends AbstractSoftwareProcessSshDriver imp
private String getClusterInitRamSize() {
return entity.getConfig(CouchbaseNode.COUCHBASE_CLUSTER_INIT_RAM_SIZE).toString();
}
-
+
@Override
public void rebalance() {
+ entity.setAttribute(CouchbaseNode.REBALANCE_STATUS, "Rebalance Started");
newScript("rebalance")
.body.append(
couchbaseCli("rebalance") +
getCouchbaseHostnameAndCredentials())
.failOnNonZeroResultCode()
.execute();
- entity.setAttribute(CouchbaseNode.REBALANCE_STATUS, "Rebalance Started");
- // wait until the re-balance is complete
+
+ // wait until the re-balance is started
+ // (if it's quick, this might miss it, but it will only block for 30s if so)
Repeater.create()
- .every(Duration.millis(500))
+ .backoff(Duration.millis(10), 2, Duration.millis(500))
.limitTimeTo(Duration.THIRTY_SECONDS)
.until(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
- for (String nodeHostName : CouchbaseNodeSshDriver.this.getNodeHostNames()) {
- if (isNodeRebalancing(nodeHostName)) {
+ for (String nodeHostAndPort : CouchbaseNodeSshDriver.this.getNodesHostAndPort()) {
+ if (isNodeRebalancing(nodeHostAndPort)) {
return true;
}
}
@@ -235,14 +237,16 @@ public class CouchbaseNodeSshDriver extends AbstractSoftwareProcessSshDriver imp
}
})
.run();
+
+ // then wait until the re-balance is complete
Repeater.create()
.every(Duration.FIVE_SECONDS)
.limitTimeTo(Duration.FIVE_MINUTES)
.until(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
- for (String nodeHostName : CouchbaseNodeSshDriver.this.getNodeHostNames()) {
- if (isNodeRebalancing(nodeHostName)) {
+ for (String nodeHostAndPort : getNodesHostAndPort()) {
+ if (isNodeRebalancing(nodeHostAndPort)) {
return false;
}
}
@@ -253,7 +257,7 @@ public class CouchbaseNodeSshDriver extends AbstractSoftwareProcessSshDriver imp
log.info("rebalanced cluster via primary node {}", getEntity());
}
- private Iterable<String> getNodeHostNames() throws URISyntaxException {
+ private Iterable<String> getNodesHostAndPort() throws URISyntaxException {
Function<JsonElement, Iterable<String>> getNodesAsList = new Function<JsonElement, Iterable<String>>() {
@Override public Iterable<String> apply(JsonElement input) {
if (input == null) {
@@ -276,12 +280,12 @@ public class CouchbaseNodeSshDriver extends AbstractSoftwareProcessSshDriver imp
).apply(nodesResponse);
}
- private boolean isNodeRebalancing(String nodeHostName) throws URISyntaxException {
- HttpToolResponse response = getAPIResponse("http://" + nodeHostName + "/pools/nodes/rebalanceProgress");
+ private boolean isNodeRebalancing(String nodeHostAndPort) throws URISyntaxException {
+ HttpToolResponse response = getAPIResponse("http://" + nodeHostAndPort + "/pools/nodes/rebalanceProgress");
if (response.getResponseCode() != 200) {
throw new IllegalStateException("failed to rebalance cluster: " + response);
}
- return !HttpValueFunctions.jsonContents("status", String.class).apply(response).equals("none");
+ return !"none".equals(HttpValueFunctions.jsonContents("status", String.class).apply(response));
}
private HttpToolResponse getAPIResponse(String uri) throws URISyntaxException {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1064cd5d/software/nosql/src/main/resources/brooklyn/entity/nosql/couchbase/pillowfight.yaml
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/resources/brooklyn/entity/nosql/couchbase/pillowfight.yaml b/software/nosql/src/main/resources/brooklyn/entity/nosql/couchbase/pillowfight.yaml
index 9442725..01f4027 100644
--- a/software/nosql/src/main/resources/brooklyn/entity/nosql/couchbase/pillowfight.yaml
+++ b/software/nosql/src/main/resources/brooklyn/entity/nosql/couchbase/pillowfight.yaml
@@ -19,73 +19,59 @@
services:
- type: brooklyn.entity.basic.VanillaSoftwareProcess
name: CBC Pillowfight
- checkRunning.command: ""
- stop.command: ""
launch.command: |
sudo wget -O/etc/apt/sources.list.d/couchbase.list http://packages.couchbase.com/ubuntu/couchbase-ubuntu1204.list
sudo wget -O- http://packages.couchbase.com/ubuntu/couchbase.key | sudo apt-key add -
sudo apt-get update
sudo apt-get install -y libcouchbase2-libevent libcouchbase-dev libcouchbase2-bin
+ provisioning.properties:
+ # CentOS requires a different launch command, see below
+ osFamily: ubuntu
+ checkRunning.command: ""
+ stop.command: ""
+
+ brooklyn.config:
+ base_url: http://127.0.0.1:8091/
+
brooklyn.initializers:
- type: brooklyn.entity.software.ssh.SshCommandEffector
brooklyn.config:
- name: cbcPillowFight
+ name: pillow_fight
description: runs cbc pillowfight
- command: >
- cbc pillowfight
- `if [ -n "$host" ]; then echo -h $host; fi`
- `if [ -n "$bucket" ]; then echo -b $bucket; fi`
- `if [ -n "$username" ]; then echo -u $username; fi`
- `if [ -n "$password" ]; then echo -p $password; fi`
- `if [ -n "$iterations" ]; then echo -i $iterations; fi`
- `if [ -n "$numItems" ]; then echo -I $numItems; fi`
- `if [ -n "$keyPrefix" ]; then echo -p $keyPrefix; fi`
- `if [ -n "$numThreads" ]; then echo -t $numThreads; fi`
- `if [ -n "$numInstances" ]; then echo -Q $numInstances; fi`
- `if [ -n "$randomSeed" ]; then echo -s $randomSeed; fi`
- `if [ -n "$minSize" ]; then echo -m $minSize; fi`
- `if [ -n "$maxSize" ]; then echo -M $maxSize; fi`
+ command: |
+ cbc-pillowfight -U ${base_url}${bucket} \
+ `if [ -n "$username" ]; then echo -u $username; fi` \
+ `if [ -n "$password" ]; then echo -P $password; fi` \
+ `if [ -n "$num_cycles" ]; then echo -c $num_cycles; fi` \
+ `if [ -n "$min_size" ]; then echo -m $min_size; fi` \
+ `if [ -n "$max_size" ]; then echo -M $max_size; fi` \
+ `if [ -n "$ratio" ]; then echo -r $ratio; fi`
parameters:
- host:
- description: list of hosts to connect to
- defaultValue: 127.0.0.1:8091
+ base_url:
+ description: base URL (http or couchbases) and list of hosts/port to connect to, including trailing slash
+ defaultValue: $brooklyn:config("base_url")
bucket:
description: bucket to use
defaultValue: default
username:
- description: username used for authentication to the cluster
+ description: username to authenticate to the bucket
password:
- description: password used for authentication to the cluster
- iterations:
+ description: password to authenticate to the bucket
+ num_cycles:
description: number of iterations to run
- defaultValue: 1000
- numItems:
- description: number of items to operate on
- defaultValue: 1000
- keyPrefix:
- description: prefix for keys
- numThreads:
- description: number of threads to use
- defaultValue: 1
- numInstances:
- description: number of connection instances to put into the shared connection pool
defaultValue: 1
- randomSeed:
- description: random seed
- defaultValue: 0
+ min_size:
+ description: minimum payload size
+ defaultValue: 50
+ max_size:
+ description: maximum payload size
+ defaultValue: 5120
ratio:
description: "specify SET/GET command ratio (default: 33, i.e. 33% SETs and 67% GETs)"
defaultValue: 33
- minSize:
- description: minimum size of payload, i.e. document body
- defaultValue: 50
- maxSize:
- description: maximum size of payload, i.e. document body
- defaultValue: 5120
# For CentOS, use the following launch command:
# launch.command: |
# sudo wget -O/etc/yum.repos.d/couchbase.repo http://packages.couchbase.com/rpm/couchbase-centos55-x86_64.repo
# sudo yum check-update
# sudo yum install -y libcouchbase2-libevent libcouchbase-devel libcouchbase2-bin
-
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1064cd5d/usage/launcher/src/test/resources/couchbase-w-loadgen.yaml
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/resources/couchbase-w-loadgen.yaml b/usage/launcher/src/test/resources/couchbase-w-loadgen.yaml
new file mode 100644
index 0000000..10daa61
--- /dev/null
+++ b/usage/launcher/src/test/resources/couchbase-w-loadgen.yaml
@@ -0,0 +1,54 @@
+#
+# 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.
+#
+name: Couchbase with Elastic Load Generator
+
+services:
+
+- type: brooklyn.entity.nosql.couchbase.CouchbaseCluster
+ id: cb-cluster
+ adminUsername: Administrator
+ adminPassword: Password
+ initialSize: 3
+ createBuckets: [ { bucket: default } ]
+ brooklyn.config:
+ provisioning.properties:
+ minRam: 16384
+ minCores: 4
+ brooklyn.policies:
+ - type: brooklyn.policy.autoscaling.AutoScalerPolicy
+ brooklyn.config:
+ metric: $brooklyn:sensor("brooklyn.entity.nosql.couchbase.CouchbaseCluster",
+ "couchbase.stats.cluster.per.node.ops")
+ metricLowerBound: 500
+ metricUpperBound: 1000
+ minPoolSize: 3
+ maxPoolSize: 8
+
+- type: brooklyn.entity.webapp.ControlledDynamicWebAppCluster
+ name: Web Couchbase Load Gen Cluster
+ war: https://github.com/neykov/web-load-gen/raw/master/load-gen.war
+ brooklyn.config:
+ provisioning.properties:
+ minCores: 4
+ java.sysprops:
+ brooklyn.example.couchbase.nodes: $brooklyn:formatString("'%s'",
+ component("cb-cluster").attributeWhenReady("couchbase.cluster.node.addresses"))
+ initialSize: 2
+
+location: aws-ec2:us-east-1
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1064cd5d/usage/launcher/src/test/resources/couchbase-w-pillowfight.yaml
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/resources/couchbase-w-pillowfight.yaml b/usage/launcher/src/test/resources/couchbase-w-pillowfight.yaml
new file mode 100644
index 0000000..3cc2851
--- /dev/null
+++ b/usage/launcher/src/test/resources/couchbase-w-pillowfight.yaml
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+name: Couchbase w Pillow Fight
+
+location: aws-ec2
+
+services:
+- type: brooklyn.entity.nosql.couchbase.CouchbaseCluster
+ id: couchbase
+ adminUsername: Administrator
+ adminPassword: Password
+ initialSize: 3
+ createBuckets:
+ - bucket: default
+ bucket-port: 11211
+
+- type: "classpath://brooklyn/entity/nosql/couchbase/pillowfight.yaml"
+ brooklyn.config:
+ base_url: $brooklyn:entity("couchbase").attributeWhenReady("couchbase.cluster.connection.url")
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1064cd5d/usage/launcher/src/test/resources/couchbase.yaml
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/resources/couchbase.yaml b/usage/launcher/src/test/resources/couchbase.yaml
index 14e1e15..bba8670 100644
--- a/usage/launcher/src/test/resources/couchbase.yaml
+++ b/usage/launcher/src/test/resources/couchbase.yaml
@@ -16,14 +16,17 @@
# specific language governing permissions and limitations
# under the License.
#
-name: Couchbase
+name: Couchbase Two Bucket
-location: aws-ec2
+location: softlayer:wdc01
services:
- type: brooklyn.entity.nosql.couchbase.CouchbaseCluster
+ initialSize: 3
adminUsername: Administrator
adminPassword: Password
- initialSize: 3
-
-- type: "classpath://brooklyn/entity/nosql/couchbase/pillowfight.yaml"
+ createBuckets:
+ - bucket: default
+ bucket-port: 11211
+ - bucket: my_bucket_2
+ bucket-port: 11222
\ No newline at end of file
[07/17] git commit: Adds apache header to Ec2LiveTest,
adds 'Live' group to tests
Posted by he...@apache.org.
Adds apache header to Ec2LiveTest, adds 'Live' group to tests
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/f23ee27b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/f23ee27b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/f23ee27b
Branch: refs/heads/master
Commit: f23ee27b877642d794f5a209aac8f1597b59ceb8
Parents: 4885a79
Author: Martin Harris <gi...@nakomis.com>
Authored: Wed Aug 20 11:06:16 2014 +0100
Committer: Martin Harris <gi...@nakomis.com>
Committed: Wed Aug 20 11:06:16 2014 +0100
----------------------------------------------------------------------
.../CouchbaseSyncGatewayEc2LiveTest.java | 27 ++++++++++++++++++--
1 file changed, 25 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f23ee27b/software/nosql/src/test/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayEc2LiveTest.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/test/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayEc2LiveTest.java b/software/nosql/src/test/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayEc2LiveTest.java
index 4c659d6..7f2327a 100644
--- a/software/nosql/src/test/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayEc2LiveTest.java
+++ b/software/nosql/src/test/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayEc2LiveTest.java
@@ -1,3 +1,21 @@
+/*
+ * 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.couchbase;
import java.util.List;
@@ -15,7 +33,6 @@ import brooklyn.test.EntityTestUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-@Test
public class CouchbaseSyncGatewayEc2LiveTest extends AbstractEc2LiveTest {
@Override
@@ -57,17 +74,19 @@ public class CouchbaseSyncGatewayEc2LiveTest extends AbstractEc2LiveTest {
// Supported operating systems
-
+ @Test(groups = {"Live"})
@Override
public void test_Ubuntu_12_0() throws Exception {
super.test_Ubuntu_12_0();
}
+ @Test(groups = {"Live"})
@Override
public void test_Red_Hat_Enterprise_Linux_6() throws Exception {
super.test_Red_Hat_Enterprise_Linux_6();
}
+ @Test(groups = {"Live"})
@Override
public void test_CentOS_6_3() throws Exception {
super.test_CentOS_6_3();
@@ -75,6 +94,7 @@ public class CouchbaseSyncGatewayEc2LiveTest extends AbstractEc2LiveTest {
// Unsupported operating systems
+ @Test(groups = {"Live"})
@Override
public void test_CentOS_5_6() throws Exception {
// Unsupported
@@ -92,16 +112,19 @@ public class CouchbaseSyncGatewayEc2LiveTest extends AbstractEc2LiveTest {
// rpmlib(PayloadIsXz) <= 5.2-1 is needed by couchbase-server-2.5.1-1083.x86_64
}
+ @Test(groups = {"Live"})
@Override
public void test_Debian_6() throws Exception {
// Unsupported
}
+ @Test(groups = {"Live"})
@Override
public void test_Debian_7_2() throws Exception {
// Unsupported
}
+ @Test(groups = {"Live"})
@Override
public void test_Ubuntu_10_0() throws Exception {
// Unsupported
[05/17] git commit: fixup me - temp commit
Posted by he...@apache.org.
fixup me - temp commit
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/4885a798
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/4885a798
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/4885a798
Branch: refs/heads/master
Commit: 4885a798700aa22f39e030d97a2d65213ecb9a31
Parents: 48c2217
Author: Martin Harris <gi...@nakomis.com>
Authored: Fri Jul 11 17:12:48 2014 +0100
Committer: Martin Harris <gi...@nakomis.com>
Committed: Mon Aug 18 15:45:44 2014 +0100
----------------------------------------------------------------------
.../nosql/couchbase/CouchbaseClusterImpl.java | 25 ++++++++++---------
.../nosql/couchbase/CouchbaseNodeSshDriver.java | 8 +++---
.../nosql/couchbase/CouchbaseSyncGateway.java | 22 ++++++++++++++---
.../couchbase/CouchbaseSyncGatewayDriver.java | 18 ++++++++++++++
.../couchbase/CouchbaseSyncGatewayImpl.java | 26 ++++++++++++++++----
.../CouchbaseSyncGatewaySshDriver.java | 18 ++++++++++++++
6 files changed, 92 insertions(+), 25 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4885a798/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
index f424eaf..4affcd1 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
@@ -26,6 +26,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -73,7 +74,9 @@ import com.google.gson.JsonElement;
public class CouchbaseClusterImpl extends DynamicClusterImpl implements CouchbaseCluster {
private static final Logger log = LoggerFactory.getLogger(CouchbaseClusterImpl.class);
private final Object mutex = new Object[0];
- private final HttpFeed[] resetBucketCreation = new HttpFeed[]{null};
+ // Used to serialize bucket creation as only one bucket can be created at a time,
+ // so a feed is used to determine when a bucket has finished being created
+ private final AtomicReference<HttpFeed> resetBucketCreation = new AtomicReference<HttpFeed>();
public void init() {
log.info("Initializing the Couchbase cluster...");
@@ -195,8 +198,8 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
@Override
public void stop() {
- if (resetBucketCreation[0] != null) {
- resetBucketCreation[0].stop();
+ if (resetBucketCreation.get() != null) {
+ resetBucketCreation.get().stop();
}
super.stop();
}
@@ -360,8 +363,7 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
}
public void createBuckets() {
- //FIXME: multiple buckets require synchronization/wait time (checks for port conflicts and exceeding ram size)
- //TODO: check for multiple bucket conflicts with port
+ //TODO: check for port conflicts if buckets are being created with a port
List<Map<String, Object>> bucketsToCreate = getConfig(CREATE_BUCKETS);
Entity primaryNode = getPrimaryNode();
@@ -374,7 +376,6 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
log.info("adding bucket: {} to primary node: {}", bucketName, primaryNode.getId());
createBucket(primaryNode, bucketName, bucketType, bucketPort, bucketRamSize, bucketReplica);
- //TODO: add if bucket has been created.
}
}
@@ -384,12 +385,12 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
@Override
public Void call() throws Exception {
DependentConfiguration.waitInTaskForAttributeReady(CouchbaseClusterImpl.this, CouchbaseCluster.BUCKET_CREATION_IN_PROGRESS, Predicates.equalTo(false));
- if (CouchbaseClusterImpl.this.resetBucketCreation[0] != null) {
- CouchbaseClusterImpl.this.resetBucketCreation[0].stop();
+ if (CouchbaseClusterImpl.this.resetBucketCreation.get() != null) {
+ CouchbaseClusterImpl.this.resetBucketCreation.get().stop();
}
setAttribute(CouchbaseCluster.BUCKET_CREATION_IN_PROGRESS, true);
- CouchbaseClusterImpl.this.resetBucketCreation[0] = HttpFeed.builder()
+ CouchbaseClusterImpl.this.resetBucketCreation.set(HttpFeed.builder()
.entity(CouchbaseClusterImpl.this)
.period(500, TimeUnit.MILLISECONDS)
.baseUri(String.format("%s/pools/default/buckets/%s", primaryNode.getAttribute(CouchbaseNode.COUCHBASE_WEB_ADMIN_URL), bucketName))
@@ -420,13 +421,13 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
throw new IllegalStateException("Unexpected response when creating bucket:" + input);
}
}))
- .build();
+ .build());
// TODO: Bail out if bucket creation fails, to allow next bucket to proceed
Entities.invokeEffectorWithArgs(CouchbaseClusterImpl.this, primaryNode, CouchbaseNode.BUCKET_CREATE, bucketName, bucketType, bucketPort, bucketRamSize, bucketReplica);
DependentConfiguration.waitInTaskForAttributeReady(CouchbaseClusterImpl.this, CouchbaseCluster.BUCKET_CREATION_IN_PROGRESS, Predicates.equalTo(false));
- if (CouchbaseClusterImpl.this.resetBucketCreation[0] != null) {
- CouchbaseClusterImpl.this.resetBucketCreation[0].stop();
+ if (CouchbaseClusterImpl.this.resetBucketCreation.get() != null) {
+ CouchbaseClusterImpl.this.resetBucketCreation.get().stop();
}
return null;
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4885a798/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
index 8eb95e0..67fa30a 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
@@ -284,15 +284,15 @@ public class CouchbaseNodeSshDriver extends AbstractSoftwareProcessSshDriver imp
return !HttpValueFunctions.jsonContents("status", String.class).apply(response).equals("none");
}
- private HttpToolResponse getAPIResponse(String path) throws URISyntaxException {
- URI uri = new URI(path);
+ private HttpToolResponse getAPIResponse(String uri) throws URISyntaxException {
+ URI apiUri = new URI(uri);
Credentials credentials = new UsernamePasswordCredentials(getUsername(), getPassword());
return HttpTool.httpGet(HttpTool.httpClientBuilder()
// the uri is required by the HttpClientBuilder in order to set the AuthScope of the credentials
- .uri(uri)
+ .uri(apiUri)
.credentials(credentials)
.build(),
- uri,
+ apiUri,
ImmutableMap.<String, String>of());
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4885a798/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGateway.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGateway.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGateway.java
index ddea721..c0740ee 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGateway.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGateway.java
@@ -1,3 +1,21 @@
+/*
+ * 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.couchbase;
import brooklyn.config.ConfigKey;
@@ -34,10 +52,6 @@ public interface CouchbaseSyncGateway extends SoftwareProcess {
ConfigKey<String> COUCHBASE_SERVER_BUCKET = ConfigKeys.newStringConfigKey("couchbaseSyncGateway.serverBucket",
"Name of the Couchbase bucket to use", "sync_gateway");
- @SetFromFlag("couchbaseServerUrl")
- ConfigKey<String> COUCHBASE_SERVER_URL = ConfigKeys.newStringConfigKey("couchbaseSyncGateway.couchbaseServerUrl",
- "Couchbase Server Admin Url to connect the gateway to");
-
@SetFromFlag("pretty")
ConfigKey<Boolean> PRETTY = ConfigKeys.newBooleanConfigKey("couchbaseSyncGateway.pretty",
"Pretty-print JSON responses. This is useful for debugging, but reduces performance.", false);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4885a798/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayDriver.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayDriver.java
index b1b4339..148ec0b 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayDriver.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayDriver.java
@@ -1,3 +1,21 @@
+/*
+ * 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.couchbase;
import brooklyn.entity.basic.SoftwareProcessDriver;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4885a798/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayImpl.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayImpl.java
index 0ead110..4ac3400 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayImpl.java
@@ -1,6 +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 brooklyn.entity.nosql.couchbase;
-
import brooklyn.config.render.RendererHints;
import brooklyn.entity.basic.SoftwareProcessImpl;
import brooklyn.event.feed.http.HttpFeed;
@@ -8,6 +25,7 @@ import brooklyn.event.feed.http.HttpPollConfig;
import brooklyn.event.feed.http.HttpValueFunctions;
import brooklyn.location.access.BrooklynAccessUtils;
+import com.google.common.base.Functions;
import com.google.common.net.HostAndPort;
public class CouchbaseSyncGatewayImpl extends SoftwareProcessImpl implements CouchbaseSyncGateway {
@@ -27,8 +45,6 @@ public class CouchbaseSyncGatewayImpl extends SoftwareProcessImpl implements Cou
@Override
protected void connectServiceUpIsRunning() {
-
-
HostAndPort hp = BrooklynAccessUtils.getBrooklynAccessibleAddress(this,
getAttribute(CouchbaseSyncGateway.ADMIN_REST_API_PORT));
@@ -42,9 +58,9 @@ public class CouchbaseSyncGatewayImpl extends SoftwareProcessImpl implements Cou
.period(200)
.baseUri(managementUri)
.poll(new HttpPollConfig<Boolean>(SERVICE_UP)
- .onSuccess(HttpValueFunctions.responseCodeEquals(200)))
+ .onSuccess(HttpValueFunctions.responseCodeEquals(200))
+ .onFailureOrException(Functions.constant(false)))
.build();
-
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4885a798/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java
index 6d9157c..3d6104b 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java
@@ -1,3 +1,21 @@
+/*
+ * 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.couchbase;
import static brooklyn.util.ssh.BashCommands.INSTALL_CURL;
[12/17] git commit: better error message when can't find referenced
yaml resource
Posted by he...@apache.org.
better error message when can't find referenced yaml resource
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/df971f5a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/df971f5a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/df971f5a
Branch: refs/heads/master
Commit: df971f5a0972fb3e73e483489ef7e121162ae87f
Parents: c6d6cc4
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Sep 1 16:45:59 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Sep 1 17:07:01 2014 +0100
----------------------------------------------------------------------
.../JavaBrooklynClassLoadingContext.java | 2 +-
.../BrooklynComponentTemplateResolver.java | 6 ++-
.../guava/IllegalStateExceptionSupplier.java | 41 ++++++++++++++++++++
.../main/java/brooklyn/util/guava/Maybe.java | 40 ++++++++++++-------
4 files changed, 71 insertions(+), 18 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df971f5a/core/src/main/java/brooklyn/management/classloading/JavaBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/classloading/JavaBrooklynClassLoadingContext.java b/core/src/main/java/brooklyn/management/classloading/JavaBrooklynClassLoadingContext.java
index 7783b25..ac58c79 100644
--- a/core/src/main/java/brooklyn/management/classloading/JavaBrooklynClassLoadingContext.java
+++ b/core/src/main/java/brooklyn/management/classloading/JavaBrooklynClassLoadingContext.java
@@ -48,7 +48,7 @@ public class JavaBrooklynClassLoadingContext extends AbstractBrooklynClassLoadin
return (Maybe) Maybe.of(loader.loadClass(className));
} catch (Exception e) {
Exceptions.propagateIfFatal(e);
- return Maybe.absent(e);
+ return Maybe.absent("Invalid class: "+className, e);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df971f5a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
index 39ec1c7..cc0eb0e 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
@@ -195,7 +195,10 @@ public class BrooklynComponentTemplateResolver {
/** returns the entity class, if needed in contexts which scan its statics for example */
public Class<? extends Entity> loadEntityClass() {
- return tryLoadEntityClass().get();
+ Maybe<Class<? extends Entity>> result = tryLoadEntityClass();
+ if (result.isAbsent())
+ throw new IllegalStateException("Could not find "+getBrooklynType(), ((Maybe.Absent<?>)result).getException());
+ return result.get();
}
/** tries to load the Java entity class */
@@ -239,7 +242,6 @@ public class BrooklynComponentTemplateResolver {
} else {
// If this is a concrete class, particularly for an Application class, we want the proxy
// to expose all interfaces it implements.
- @SuppressWarnings("rawtypes")
Class interfaceclazz = (Application.class.isAssignableFrom(type)) ? Application.class : Entity.class;
List<Class<?>> additionalInterfaceClazzes = Reflections.getAllInterfaces(type);
spec = EntitySpec.create(interfaceclazz).impl(type).additionalInterfaces(additionalInterfaceClazzes);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df971f5a/utils/common/src/main/java/brooklyn/util/guava/IllegalStateExceptionSupplier.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/guava/IllegalStateExceptionSupplier.java b/utils/common/src/main/java/brooklyn/util/guava/IllegalStateExceptionSupplier.java
new file mode 100644
index 0000000..4fc8546
--- /dev/null
+++ b/utils/common/src/main/java/brooklyn/util/guava/IllegalStateExceptionSupplier.java
@@ -0,0 +1,41 @@
+/*
+ * 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.util.guava;
+
+import com.google.common.base.Supplier;
+
+public class IllegalStateExceptionSupplier implements Supplier<RuntimeException> {
+
+ protected final String message;
+ protected final Throwable cause;
+
+ public IllegalStateExceptionSupplier() { this(null, null); }
+ public IllegalStateExceptionSupplier(String message) { this(message, null); }
+ public IllegalStateExceptionSupplier(Throwable cause) { this(null, cause); }
+ public IllegalStateExceptionSupplier(String message, Throwable cause) {
+ this.message = message;
+ this.cause = cause;
+ }
+
+ @Override
+ public RuntimeException get() {
+ return new IllegalStateException(message, cause);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/df971f5a/utils/common/src/main/java/brooklyn/util/guava/Maybe.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/guava/Maybe.java b/utils/common/src/main/java/brooklyn/util/guava/Maybe.java
index 9a3ebdb..fb60bf8 100644
--- a/utils/common/src/main/java/brooklyn/util/guava/Maybe.java
+++ b/utils/common/src/main/java/brooklyn/util/guava/Maybe.java
@@ -29,6 +29,7 @@ import brooklyn.util.javalang.JavaClassNames;
import com.google.common.base.Function;
import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
@@ -44,25 +45,24 @@ public abstract class Maybe<T> implements Serializable, Supplier<T> {
/** Creates an absent whose get throws an {@link IllegalStateException} with the indicated message.
* Both stack traces (the cause and the callers) are provided, which can be quite handy. */
public static <T> Maybe<T> absent(final String message) {
- return new Absent<T>() {
- private static final long serialVersionUID = 1L;
- @Override
- public T get() {
- throw new IllegalStateException(message);
- }
- };
+ return absent(new IllegalStateExceptionSupplier(message));
}
/** Creates an absent whose get throws an {@link IllegalStateException} with the indicated cause.
* Both stack traces (the cause and the callers) are provided, which can be quite handy. */
public static <T> Maybe<T> absent(final Throwable cause) {
- return new Absent<T>() {
- private static final long serialVersionUID = 1L;
- @Override
- public T get() {
- throw new IllegalStateException(cause);
- }
- };
+ return absent(new IllegalStateExceptionSupplier(cause));
+ }
+
+ /** Creates an absent whose get throws an {@link IllegalStateException} with the indicated message and underlying cause.
+ * Both stack traces (the cause and the callers) are provided, which can be quite handy. */
+ public static <T> Maybe<T> absent(final String message, final Throwable cause) {
+ return absent(new IllegalStateExceptionSupplier(message, cause));
+ }
+
+ /** Creates an absent whose get throws an {@link RuntimeException} generated on demand from the given supplier */
+ public static <T> Maybe<T> absent(final Supplier<RuntimeException> exceptionSupplier) {
+ return new Absent<T>(Preconditions.checkNotNull(exceptionSupplier));
}
public static <T> Maybe<T> of(@Nullable T value) {
@@ -151,13 +151,23 @@ public abstract class Maybe<T> implements Serializable, Supplier<T> {
public static class Absent<T> extends Maybe<T> {
private static final long serialVersionUID = -757170462010887057L;
+ private final Supplier<RuntimeException> exception;
+ public Absent() {
+ this(new IllegalStateExceptionSupplier());
+ }
+ public Absent(Supplier<RuntimeException> exception) {
+ this.exception = exception;
+ }
@Override
public boolean isPresent() {
return false;
}
@Override
public T get() {
- throw new IllegalStateException();
+ throw getException();
+ }
+ public RuntimeException getException() {
+ return exception.get();
}
}
[06/17] git commit: Fixed CouchbaseSyncGateway live tests
Posted by he...@apache.org.
Fixed CouchbaseSyncGateway live tests
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/48c22178
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/48c22178
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/48c22178
Branch: refs/heads/master
Commit: 48c22178417698c7891a4cd29ebc78d5d1db2ec9
Parents: 7d0467d
Author: Martin Harris <gi...@nakomis.com>
Authored: Tue Jul 1 10:43:16 2014 +0100
Committer: Martin Harris <gi...@nakomis.com>
Committed: Mon Aug 18 15:45:44 2014 +0100
----------------------------------------------------------------------
.../nosql/couchbase/CouchbaseNodeSshDriver.java | 17 ++-
.../CouchbaseSyncGatewaySshDriver.java | 9 +-
.../CouchbaseSyncGatewayEc2LiveTest.java | 114 +++++++++++++++++++
3 files changed, 129 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/48c22178/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
index 6f81b73..8eb95e0 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
@@ -21,6 +21,7 @@ package brooklyn.entity.nosql.couchbase;
import static brooklyn.util.ssh.BashCommands.INSTALL_CURL;
import static brooklyn.util.ssh.BashCommands.alternatives;
import static brooklyn.util.ssh.BashCommands.chainGroup;
+import static brooklyn.util.ssh.BashCommands.ok;
import static brooklyn.util.ssh.BashCommands.sudo;
import static java.lang.String.format;
@@ -48,7 +49,6 @@ import brooklyn.util.repeat.Repeater;
import brooklyn.util.ssh.BashCommands;
import brooklyn.util.task.Tasks;
import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
@@ -102,10 +102,13 @@ public class CouchbaseNodeSshDriver extends AbstractSoftwareProcessSshDriver imp
String yum = chainGroup(
"which yum",
- sudo("yum check-update"),
+ // The following prevents failure on RHEL AWS nodes:
+ // https://forums.aws.amazon.com/thread.jspa?threadID=100509
+ ok(sudo("sed -i.bk s/^enabled=1$/enabled=0/ /etc/yum/pluginconf.d/subscription-manager.conf")),
+ ok(sudo("yum check-update")),
sudo("yum install -y pkgconfig"),
// RHEL requires openssl version 098
- sudo("[ -f /etc/redhat-release ] && (grep -i \"red hat\" /etc/redhat-release && yum install -y openssl098e) || :"),
+ sudo("[ -f /etc/redhat-release ] && (grep -i \"red hat\" /etc/redhat-release && sudo yum install -y openssl098e) || :"),
sudo(format("rpm --install %s", saveAs)));
return ImmutableList.<String>builder()
@@ -130,11 +133,15 @@ public class CouchbaseNodeSshDriver extends AbstractSoftwareProcessSshDriver imp
@Override
public void launch() {
- //FIXME needs time for http server to initialize
- Time.sleep(Duration.TEN_SECONDS);
newScript(LAUNCHING)
.body.append(
sudo("/etc/init.d/couchbase-server start"),
+ "for i in {0..120}\n" +
+ "do\n" +
+ " if [ $i -eq 120 ]; then echo REST API unavailable after 120 seconds, failing; exit 1; fi;\n" +
+ " curl -s " + String.format("http://%s:%s", getHostname(), getWebPort()) + " > /dev/null && echo REST API available after $i seconds && break\n" +
+ " sleep 1\n" +
+ "done\n" +
couchbaseCli("cluster-init") +
getCouchbaseHostnameAndPort() +
" --cluster-init-username=" + getUsername() +
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/48c22178/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java
index 7339c40..6d9157c 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java
@@ -21,6 +21,7 @@ import brooklyn.location.basic.SshMachineLocation;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.ssh.BashCommands;
import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
@@ -66,12 +67,8 @@ public class CouchbaseSyncGatewaySshDriver extends AbstractSoftwareProcessSshDri
Entity cbNode = entity.getConfig(CouchbaseSyncGateway.COUCHBASE_SERVER);
Entities.waitForServiceUp(cbNode, Duration.ONE_HOUR);
DependentConfiguration.waitInTaskForAttributeReady(cbNode, CouchbaseCluster.IS_CLUSTER_INITIALIZED, Predicates.equalTo(true));
- try {
- // Even once the bucket has published its API URL, it can still take a couple of seconds for it to become available
- Thread.sleep(10 * 1000);
- } catch (InterruptedException e) {
- // no-op
- }
+ // Even once the bucket has published its API URL, it can still take a couple of seconds for it to become available
+ Time.sleep(10 * 1000);
if (cbNode instanceof CouchbaseCluster) {
Optional<Entity> cbClusterNode = Iterables.tryFind(cbNode.getAttribute(CouchbaseCluster.GROUP_MEMBERS), new Predicate<Entity>() {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/48c22178/software/nosql/src/test/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayEc2LiveTest.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/test/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayEc2LiveTest.java b/software/nosql/src/test/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayEc2LiveTest.java
new file mode 100644
index 0000000..4c659d6
--- /dev/null
+++ b/software/nosql/src/test/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayEc2LiveTest.java
@@ -0,0 +1,114 @@
+package brooklyn.entity.nosql.couchbase;
+
+import java.util.List;
+import java.util.Map;
+
+import org.testng.annotations.Test;
+
+import brooklyn.entity.AbstractEc2LiveTest;
+import brooklyn.entity.group.DynamicCluster;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.trait.Startable;
+import brooklyn.location.Location;
+import brooklyn.test.EntityTestUtils;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+@Test
+public class CouchbaseSyncGatewayEc2LiveTest extends AbstractEc2LiveTest {
+
+ @Override
+ protected void doTest(Location loc) throws Exception {
+ CouchbaseCluster cluster = app.createAndManageChild(EntitySpec.create(CouchbaseCluster.class)
+ .configure(CouchbaseNode.COUCHBASE_ADMIN_USERNAME, "Administrator")
+ .configure(CouchbaseNode.COUCHBASE_ADMIN_PASSWORD, "Password")
+ .configure(DynamicCluster.INITIAL_SIZE, 3)
+ .configure(CouchbaseCluster.CREATE_BUCKETS, (List<Map<String,Object>>)ImmutableList.of(
+ (Map<String,Object>)ImmutableMap.<String, Object>of(
+ "bucket", "default",
+ "bucket-ramsize", 100,
+ "bucket-type", "couchbase",
+ "bucket-port", 11211
+ ),
+ (Map<String,Object>)ImmutableMap.<String, Object>of(
+ "bucket", "my_bucket",
+ "bucket-ramsize", 100,
+ "bucket-type", "couchbase",
+ "bucket-port", 11223
+ ),
+ (Map<String,Object>)ImmutableMap.<String, Object>of(
+ "bucket", "another",
+ "bucket-ramsize", 100,
+ "bucket-type", "couchbase",
+ "bucket-port", 11224
+ ))
+ )
+ );
+ CouchbaseSyncGateway gateway = app.createAndManageChild(EntitySpec.create(CouchbaseSyncGateway.class)
+ .configure(CouchbaseSyncGateway.COUCHBASE_SERVER, cluster)
+ .configure(CouchbaseSyncGateway.COUCHBASE_SERVER_BUCKET, "my_bucket")
+ );
+
+ app.start(ImmutableList.of(loc));
+
+ EntityTestUtils.assertAttributeEqualsEventually(gateway, Startable.SERVICE_UP, true);
+ }
+
+
+ // Supported operating systems
+
+ @Override
+ public void test_Ubuntu_12_0() throws Exception {
+ super.test_Ubuntu_12_0();
+ }
+
+ @Override
+ public void test_Red_Hat_Enterprise_Linux_6() throws Exception {
+ super.test_Red_Hat_Enterprise_Linux_6();
+ }
+
+ @Override
+ public void test_CentOS_6_3() throws Exception {
+ super.test_CentOS_6_3();
+ }
+
+ // Unsupported operating systems
+
+ @Override
+ public void test_CentOS_5_6() throws Exception {
+ // Unsupported
+ // error: Failed dependencies:
+ // libc.so.6(GLIBC_2.7)(64bit) is needed by couchbase-server-2.5.1-1083.x86_64
+ // libcrypto.so.10()(64bit) is needed by couchbase-server-2.5.1-1083.x86_64
+ // libreadline.so.6()(64bit) is needed by couchbase-server-2.5.1-1083.x86_64
+ // libssl.so.10()(64bit) is needed by couchbase-server-2.5.1-1083.x86_64
+ // libstdc++.so.6(GLIBCXX_3.4.10)(64bit) is needed by couchbase-server-2.5.1-1083.x86_64
+ // libstdc++.so.6(GLIBCXX_3.4.11)(64bit) is needed by couchbase-server-2.5.1-1083.x86_64
+ // libstdc++.so.6(GLIBCXX_3.4.9)(64bit) is needed by couchbase-server-2.5.1-1083.x86_64
+ // libtinfo.so.5()(64bit) is needed by couchbase-server-2.5.1-1083.x86_64
+ // openssl >= 1.0.0 is needed by couchbase-server-2.5.1-1083.x86_64
+ // rpmlib(FileDigests) <= 4.6.0-1 is needed by couchbase-server-2.5.1-1083.x86_64
+ // rpmlib(PayloadIsXz) <= 5.2-1 is needed by couchbase-server-2.5.1-1083.x86_64
+ }
+
+ @Override
+ public void test_Debian_6() throws Exception {
+ // Unsupported
+ }
+
+ @Override
+ public void test_Debian_7_2() throws Exception {
+ // Unsupported
+ }
+
+ @Override
+ public void test_Ubuntu_10_0() throws Exception {
+ // Unsupported
+ // Installing cannot proceed since the package 'libssl1*' is missing.
+ // Please install libssl1* and try again.
+ // $sudo apt-get install libssl1*
+ //
+ // Installing libssl1* doesn't fix the issue
+ }
+}
[04/17] git commit: Fixed bucket creation
Posted by he...@apache.org.
Fixed bucket creation
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/7d0467d8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/7d0467d8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/7d0467d8
Branch: refs/heads/master
Commit: 7d0467d887629225b919d9fce93d5abf3c9a0b20
Parents: 4f70aa1
Author: Martin Harris <gi...@nakomis.com>
Authored: Wed Jun 25 16:44:11 2014 +0100
Committer: Martin Harris <gi...@nakomis.com>
Committed: Mon Aug 18 15:45:43 2014 +0100
----------------------------------------------------------------------
.../nosql/couchbase/CouchbaseClusterImpl.java | 47 +++++++-
.../nosql/couchbase/CouchbaseNodeSshDriver.java | 116 +++++++++++++++++--
.../couchbase/CouchbaseSyncGatewayImpl.java | 5 +
.../CouchbaseSyncGatewaySshDriver.java | 34 ++++--
4 files changed, 175 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d0467d8/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
index b7c2026..f424eaf 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
@@ -48,23 +48,27 @@ import brooklyn.event.basic.DependentConfiguration;
import brooklyn.event.feed.http.HttpFeed;
import brooklyn.event.feed.http.HttpPollConfig;
import brooklyn.event.feed.http.HttpValueFunctions;
+import brooklyn.event.feed.http.JsonFunctions;
import brooklyn.location.Location;
import brooklyn.policy.PolicySpec;
import brooklyn.util.collections.MutableSet;
+import brooklyn.util.guava.Functionals;
import brooklyn.util.task.DynamicTasks;
import brooklyn.util.task.TaskBuilder;
import brooklyn.util.task.Tasks;
import brooklyn.util.text.ByteSizeStrings;
+import brooklyn.util.text.Strings;
import brooklyn.util.time.Time;
import com.google.common.base.Function;
-import com.google.common.base.Functions;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
public class CouchbaseClusterImpl extends DynamicClusterImpl implements CouchbaseCluster {
private static final Logger log = LoggerFactory.getLogger(CouchbaseClusterImpl.class);
@@ -141,6 +145,8 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
connectSensors();
connectEnrichers();
+
+ setAttribute(BUCKET_CREATION_IN_PROGRESS, false);
//start timeout before adding the servers
Time.sleep(getConfig(SERVICE_UP_TIME_OUT));
@@ -167,10 +173,12 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
} finally {
Tasks.resetBlockingDetails();
}
- Entities.invokeEffector(this, getPrimaryNode(), CouchbaseNode.REBALANCE);
+
+ ((CouchbaseNode)getPrimaryNode()).rebalance();
if (Optional.fromNullable(CREATE_BUCKETS).isPresent()) {
createBuckets();
+ DependentConfiguration.waitInTaskForAttributeReady(this, CouchbaseCluster.BUCKET_CREATION_IN_PROGRESS, Predicates.equalTo(false));
}
setAttribute(IS_CLUSTER_INITIALIZED, true);
@@ -187,6 +195,9 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
@Override
public void stop() {
+ if (resetBucketCreation[0] != null) {
+ resetBucketCreation[0].stop();
+ }
super.stop();
}
@@ -205,7 +216,7 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
.displayName("Controller targets tracker")
.configure("group", this));
}
-
+
public static class MemberTrackingPolicy extends AbstractMembershipTrackingPolicy {
@Override protected void onEntityChange(Entity member) {
((CouchbaseClusterImpl)entity).onServerPoolMemberChanged(member);
@@ -377,17 +388,41 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
CouchbaseClusterImpl.this.resetBucketCreation[0].stop();
}
setAttribute(CouchbaseCluster.BUCKET_CREATION_IN_PROGRESS, true);
-
+
CouchbaseClusterImpl.this.resetBucketCreation[0] = HttpFeed.builder()
.entity(CouchbaseClusterImpl.this)
.period(500, TimeUnit.MILLISECONDS)
.baseUri(String.format("%s/pools/default/buckets/%s", primaryNode.getAttribute(CouchbaseNode.COUCHBASE_WEB_ADMIN_URL), bucketName))
.credentials(primaryNode.getConfig(CouchbaseNode.COUCHBASE_ADMIN_USERNAME), primaryNode.getConfig(CouchbaseNode.COUCHBASE_ADMIN_PASSWORD))
.poll(new HttpPollConfig<Boolean>(BUCKET_CREATION_IN_PROGRESS)
- .onSuccess(HttpValueFunctions.responseCodeEquals(404))
- .onFailureOrException(Functions.constant(false)))
+ .onSuccess(Functionals.chain(HttpValueFunctions.jsonContents(), JsonFunctions.walkN("nodes"), new Function<JsonElement, Boolean>() {
+ @Override public Boolean apply(JsonElement input) {
+ // Wait until bucket has been created on all nodes and the couchApiBase element has been published (indicating that the bucket is useable)
+ JsonArray servers = input.getAsJsonArray();
+ if (servers.size() != CouchbaseClusterImpl.this.getMembers().size()) {
+ return true;
+ }
+ for (JsonElement server : servers) {
+ Object api = server.getAsJsonObject().get("couchApiBase");
+ if (api == null || Strings.isEmpty(String.valueOf(api))) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }))
+ .onFailureOrException(new Function<Object, Boolean>() {
+ @Override
+ public Boolean apply(Object input) {
+ if (((brooklyn.util.http.HttpToolResponse) input).getResponseCode() == 404) {
+ return true;
+ }
+ throw new IllegalStateException("Unexpected response when creating bucket:" + input);
+ }
+ }))
.build();
+ // TODO: Bail out if bucket creation fails, to allow next bucket to proceed
Entities.invokeEffectorWithArgs(CouchbaseClusterImpl.this, primaryNode, CouchbaseNode.BUCKET_CREATE, bucketName, bucketType, bucketPort, bucketRamSize, bucketReplica);
DependentConfiguration.waitInTaskForAttributeReady(CouchbaseClusterImpl.this, CouchbaseCluster.BUCKET_CREATION_IN_PROGRESS, Predicates.equalTo(false));
if (CouchbaseClusterImpl.this.resetBucketCreation[0] != null) {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d0467d8/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
index e02ddc9..6f81b73 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
@@ -24,19 +24,38 @@ import static brooklyn.util.ssh.BashCommands.chainGroup;
import static brooklyn.util.ssh.BashCommands.sudo;
import static java.lang.String.format;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
import brooklyn.entity.basic.AbstractSoftwareProcessSshDriver;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.drivers.downloads.DownloadResolver;
+import brooklyn.event.feed.http.HttpValueFunctions;
+import brooklyn.event.feed.http.JsonFunctions;
import brooklyn.location.OsDetails;
import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.util.guava.Functionals;
+import brooklyn.util.http.HttpTool;
+import brooklyn.util.http.HttpToolResponse;
+import brooklyn.util.repeat.Repeater;
import brooklyn.util.ssh.BashCommands;
import brooklyn.util.task.Tasks;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
+import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
public class CouchbaseNodeSshDriver extends AbstractSoftwareProcessSshDriver implements CouchbaseNodeDriver {
@@ -193,8 +212,83 @@ public class CouchbaseNodeSshDriver extends AbstractSoftwareProcessSshDriver imp
.failOnNonZeroResultCode()
.execute();
entity.setAttribute(CouchbaseNode.REBALANCE_STATUS, "Rebalance Started");
+ // wait until the re-balance is complete
+ Repeater.create()
+ .every(Duration.millis(500))
+ .limitTimeTo(Duration.THIRTY_SECONDS)
+ .until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ for (String nodeHostName : CouchbaseNodeSshDriver.this.getNodeHostNames()) {
+ if (isNodeRebalancing(nodeHostName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ })
+ .run();
+ Repeater.create()
+ .every(Duration.FIVE_SECONDS)
+ .limitTimeTo(Duration.FIVE_MINUTES)
+ .until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ for (String nodeHostName : CouchbaseNodeSshDriver.this.getNodeHostNames()) {
+ if (isNodeRebalancing(nodeHostName)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ })
+ .run();
+ log.info("rebalanced cluster via primary node {}", getEntity());
}
+ private Iterable<String> getNodeHostNames() throws URISyntaxException {
+ Function<JsonElement, Iterable<String>> getNodesAsList = new Function<JsonElement, Iterable<String>>() {
+ @Override public Iterable<String> apply(JsonElement input) {
+ if (input == null) {
+ return Collections.emptyList();
+ }
+ Collection<String> names = Lists.newArrayList();
+ JsonArray nodes = input.getAsJsonArray();
+ for (JsonElement element : nodes) {
+ // NOTE: the 'hostname' element also includes the port
+ names.add(element.getAsJsonObject().get("hostname").toString().replace("\"", ""));
+ }
+ return names;
+ }
+ };
+ HttpToolResponse nodesResponse = getAPIResponse(String.format("http://%s:%s/pools/nodes", getHostname(), getWebPort()));
+ return Functionals.chain(
+ HttpValueFunctions.jsonContents(),
+ JsonFunctions.walkN("nodes"),
+ getNodesAsList
+ ).apply(nodesResponse);
+ }
+
+ private boolean isNodeRebalancing(String nodeHostName) throws URISyntaxException {
+ HttpToolResponse response = getAPIResponse("http://" + nodeHostName + "/pools/nodes/rebalanceProgress");
+ if (response.getResponseCode() != 200) {
+ throw new IllegalStateException("failed to rebalance cluster: " + response);
+ }
+ return !HttpValueFunctions.jsonContents("status", String.class).apply(response).equals("none");
+ }
+
+ private HttpToolResponse getAPIResponse(String path) throws URISyntaxException {
+ URI uri = new URI(path);
+ Credentials credentials = new UsernamePasswordCredentials(getUsername(), getPassword());
+ return HttpTool.httpGet(HttpTool.httpClientBuilder()
+ // the uri is required by the HttpClientBuilder in order to set the AuthScope of the credentials
+ .uri(uri)
+ .credentials(credentials)
+ .build(),
+ uri,
+ ImmutableMap.<String, String>of());
+ }
+
@Override
public void serverAdd(String serverToAdd, String username, String password) {
newScript("serverAdd").body.append(couchbaseCli("server-add")
@@ -219,15 +313,15 @@ public class CouchbaseNodeSshDriver extends AbstractSoftwareProcessSshDriver imp
}
@Override
- public void bucketCreate(String bucketName, String bucketType, Integer bucketPort, Integer bucketRamSize, Integer bucketReplica) {
- newScript("bucketCreate").body.append(couchbaseCli("bucket-create")
- + getCouchbaseHostnameAndCredentials() +
- " --bucket=" + bucketName +
- " --bucket-type=" + bucketType +
- " --bucket-port=" + bucketPort +
- " --bucket-ramsize=" + bucketRamSize +
- " --bucket-replica=" + bucketReplica)
- .failOnNonZeroResultCode()
- .execute();
- }
+ public void bucketCreate(String bucketName, String bucketType, Integer bucketPort, Integer bucketRamSize, Integer bucketReplica) {
+ newScript("bucketCreate").body.append(couchbaseCli("bucket-create")
+ + getCouchbaseHostnameAndCredentials() +
+ " --bucket=" + bucketName +
+ " --bucket-type=" + bucketType +
+ " --bucket-port=" + bucketPort +
+ " --bucket-ramsize=" + bucketRamSize +
+ " --bucket-replica=" + bucketReplica)
+ .failOnNonZeroResultCode()
+ .execute();
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d0467d8/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayImpl.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayImpl.java
index 09ef569..0ead110 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayImpl.java
@@ -1,6 +1,7 @@
package brooklyn.entity.nosql.couchbase;
+import brooklyn.config.render.RendererHints;
import brooklyn.entity.basic.SoftwareProcessImpl;
import brooklyn.event.feed.http.HttpFeed;
import brooklyn.event.feed.http.HttpPollConfig;
@@ -58,4 +59,8 @@ public class CouchbaseSyncGatewayImpl extends SoftwareProcessImpl implements Cou
httpFeed.stop();
}
}
+
+ static {
+ RendererHints.register(MANAGEMENT_URL, new RendererHints.NamedActionWithUrl("Open"));
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d0467d8/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java
index c7c9129..7339c40 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java
@@ -12,18 +12,21 @@ import javax.annotation.Nullable;
import brooklyn.entity.Entity;
import brooklyn.entity.basic.AbstractSoftwareProcessSshDriver;
-import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityLocal;
import brooklyn.entity.drivers.downloads.DownloadResolver;
+import brooklyn.event.basic.DependentConfiguration;
import brooklyn.location.OsDetails;
import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.util.collections.MutableMap;
import brooklyn.util.ssh.BashCommands;
import brooklyn.util.time.Duration;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
public class CouchbaseSyncGatewaySshDriver extends AbstractSoftwareProcessSshDriver implements CouchbaseSyncGatewayDriver {
@@ -32,11 +35,6 @@ public class CouchbaseSyncGatewaySshDriver extends AbstractSoftwareProcessSshDri
}
@Override
- public boolean isRunning() {
- return Boolean.TRUE.equals(entity.getAttribute(Attributes.SERVICE_UP));
- }
-
- @Override
public void stop() {
}
@@ -67,8 +65,13 @@ public class CouchbaseSyncGatewaySshDriver extends AbstractSoftwareProcessSshDri
public void launch() {
Entity cbNode = entity.getConfig(CouchbaseSyncGateway.COUCHBASE_SERVER);
Entities.waitForServiceUp(cbNode, Duration.ONE_HOUR);
-
-
+ DependentConfiguration.waitInTaskForAttributeReady(cbNode, CouchbaseCluster.IS_CLUSTER_INITIALIZED, Predicates.equalTo(true));
+ try {
+ // Even once the bucket has published its API URL, it can still take a couple of seconds for it to become available
+ Thread.sleep(10 * 1000);
+ } catch (InterruptedException e) {
+ // no-op
+ }
if (cbNode instanceof CouchbaseCluster) {
Optional<Entity> cbClusterNode = Iterables.tryFind(cbNode.getAttribute(CouchbaseCluster.GROUP_MEMBERS), new Predicate<Entity>() {
@@ -106,10 +109,21 @@ public class CouchbaseSyncGatewaySshDriver extends AbstractSoftwareProcessSshDri
String options = format("-url %s -bucket %s -adminInterface 0.0.0.0:%s -interface 0.0.0.0:%s -pool %s %s %s",
serverWebAdminUrl, bucketName, adminRestApiPort, syncRestApiPort, pool, pretty, verbose);
- newScript(LAUNCHING)
- .body.append(format("/opt/couchbase-sync-gateway/bin/sync_gateway %s &", options))
+ newScript(ImmutableMap.of("usePidFile", true), LAUNCHING)
+ .body.append(format("/opt/couchbase-sync-gateway/bin/sync_gateway %s ", options) + "> out.log 2> err.log < /dev/null &")
+ .failOnNonZeroResultCode()
.execute();
}
+
+ @Override
+ public boolean isRunning() {
+ return newScript(MutableMap.of("usePidFile", true), CHECK_RUNNING).execute() == 0;
+ }
+
+ @Override
+ public void kill() {
+ newScript(MutableMap.of("usePidFile", true), KILLING).execute();
+ }
private List<String> installLinux(List<String> urls, String saveAs) {
[13/17] git commit: move pillowfight to core rather than tests
Posted by he...@apache.org.
move pillowfight to core rather than tests
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/94bf2998
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/94bf2998
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/94bf2998
Branch: refs/heads/master
Commit: 94bf2998df461348102beae2a561445cd333b100
Parents: f51710d
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Aug 27 14:26:33 2014 -0400
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Sep 1 17:07:01 2014 +0100
----------------------------------------------------------------------
.../nosql/couchbase/CouchbaseClusterImpl.java | 2 +
.../entity/nosql/couchbase/pillowfight.yaml | 91 ++++++++++++++++++++
.../launcher/src/test/resources/couchbase.yaml | 4 +-
.../src/test/resources/pillowfight.yaml | 91 --------------------
4 files changed, 95 insertions(+), 93 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/94bf2998/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
index dc63e8c..69b038a 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
@@ -363,6 +363,8 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
public void createBuckets() {
//TODO: check for port conflicts if buckets are being created with a port
List<Map<String, Object>> bucketsToCreate = getConfig(CREATE_BUCKETS);
+ if (bucketsToCreate==null) return;
+
Entity primaryNode = getPrimaryNode();
for (Map<String, Object> bucketMap : bucketsToCreate) {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/94bf2998/software/nosql/src/main/resources/brooklyn/entity/nosql/couchbase/pillowfight.yaml
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/resources/brooklyn/entity/nosql/couchbase/pillowfight.yaml b/software/nosql/src/main/resources/brooklyn/entity/nosql/couchbase/pillowfight.yaml
new file mode 100644
index 0000000..9442725
--- /dev/null
+++ b/software/nosql/src/main/resources/brooklyn/entity/nosql/couchbase/pillowfight.yaml
@@ -0,0 +1,91 @@
+#
+# 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.
+#
+services:
+- type: brooklyn.entity.basic.VanillaSoftwareProcess
+ name: CBC Pillowfight
+ checkRunning.command: ""
+ stop.command: ""
+ launch.command: |
+ sudo wget -O/etc/apt/sources.list.d/couchbase.list http://packages.couchbase.com/ubuntu/couchbase-ubuntu1204.list
+ sudo wget -O- http://packages.couchbase.com/ubuntu/couchbase.key | sudo apt-key add -
+ sudo apt-get update
+ sudo apt-get install -y libcouchbase2-libevent libcouchbase-dev libcouchbase2-bin
+ brooklyn.initializers:
+ - type: brooklyn.entity.software.ssh.SshCommandEffector
+ brooklyn.config:
+ name: cbcPillowFight
+ description: runs cbc pillowfight
+ command: >
+ cbc pillowfight
+ `if [ -n "$host" ]; then echo -h $host; fi`
+ `if [ -n "$bucket" ]; then echo -b $bucket; fi`
+ `if [ -n "$username" ]; then echo -u $username; fi`
+ `if [ -n "$password" ]; then echo -p $password; fi`
+ `if [ -n "$iterations" ]; then echo -i $iterations; fi`
+ `if [ -n "$numItems" ]; then echo -I $numItems; fi`
+ `if [ -n "$keyPrefix" ]; then echo -p $keyPrefix; fi`
+ `if [ -n "$numThreads" ]; then echo -t $numThreads; fi`
+ `if [ -n "$numInstances" ]; then echo -Q $numInstances; fi`
+ `if [ -n "$randomSeed" ]; then echo -s $randomSeed; fi`
+ `if [ -n "$minSize" ]; then echo -m $minSize; fi`
+ `if [ -n "$maxSize" ]; then echo -M $maxSize; fi`
+ parameters:
+ host:
+ description: list of hosts to connect to
+ defaultValue: 127.0.0.1:8091
+ bucket:
+ description: bucket to use
+ defaultValue: default
+ username:
+ description: username used for authentication to the cluster
+ password:
+ description: password used for authentication to the cluster
+ iterations:
+ description: number of iterations to run
+ defaultValue: 1000
+ numItems:
+ description: number of items to operate on
+ defaultValue: 1000
+ keyPrefix:
+ description: prefix for keys
+ numThreads:
+ description: number of threads to use
+ defaultValue: 1
+ numInstances:
+ description: number of connection instances to put into the shared connection pool
+ defaultValue: 1
+ randomSeed:
+ description: random seed
+ defaultValue: 0
+ ratio:
+ description: "specify SET/GET command ratio (default: 33, i.e. 33% SETs and 67% GETs)"
+ defaultValue: 33
+ minSize:
+ description: minimum size of payload, i.e. document body
+ defaultValue: 50
+ maxSize:
+ description: maximum size of payload, i.e. document body
+ defaultValue: 5120
+
+# For CentOS, use the following launch command:
+# launch.command: |
+# sudo wget -O/etc/yum.repos.d/couchbase.repo http://packages.couchbase.com/rpm/couchbase-centos55-x86_64.repo
+# sudo yum check-update
+# sudo yum install -y libcouchbase2-libevent libcouchbase-devel libcouchbase2-bin
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/94bf2998/usage/launcher/src/test/resources/couchbase.yaml
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/resources/couchbase.yaml b/usage/launcher/src/test/resources/couchbase.yaml
index d2ae0ed..14e1e15 100644
--- a/usage/launcher/src/test/resources/couchbase.yaml
+++ b/usage/launcher/src/test/resources/couchbase.yaml
@@ -18,7 +18,7 @@
#
name: Couchbase
-location: softlayer:ams01
+location: aws-ec2
services:
- type: brooklyn.entity.nosql.couchbase.CouchbaseCluster
@@ -26,4 +26,4 @@ services:
adminPassword: Password
initialSize: 3
-- type: "classpath://pillowfight.yaml"
+- type: "classpath://brooklyn/entity/nosql/couchbase/pillowfight.yaml"
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/94bf2998/usage/launcher/src/test/resources/pillowfight.yaml
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/resources/pillowfight.yaml b/usage/launcher/src/test/resources/pillowfight.yaml
deleted file mode 100644
index 9442725..0000000
--- a/usage/launcher/src/test/resources/pillowfight.yaml
+++ /dev/null
@@ -1,91 +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.
-#
-services:
-- type: brooklyn.entity.basic.VanillaSoftwareProcess
- name: CBC Pillowfight
- checkRunning.command: ""
- stop.command: ""
- launch.command: |
- sudo wget -O/etc/apt/sources.list.d/couchbase.list http://packages.couchbase.com/ubuntu/couchbase-ubuntu1204.list
- sudo wget -O- http://packages.couchbase.com/ubuntu/couchbase.key | sudo apt-key add -
- sudo apt-get update
- sudo apt-get install -y libcouchbase2-libevent libcouchbase-dev libcouchbase2-bin
- brooklyn.initializers:
- - type: brooklyn.entity.software.ssh.SshCommandEffector
- brooklyn.config:
- name: cbcPillowFight
- description: runs cbc pillowfight
- command: >
- cbc pillowfight
- `if [ -n "$host" ]; then echo -h $host; fi`
- `if [ -n "$bucket" ]; then echo -b $bucket; fi`
- `if [ -n "$username" ]; then echo -u $username; fi`
- `if [ -n "$password" ]; then echo -p $password; fi`
- `if [ -n "$iterations" ]; then echo -i $iterations; fi`
- `if [ -n "$numItems" ]; then echo -I $numItems; fi`
- `if [ -n "$keyPrefix" ]; then echo -p $keyPrefix; fi`
- `if [ -n "$numThreads" ]; then echo -t $numThreads; fi`
- `if [ -n "$numInstances" ]; then echo -Q $numInstances; fi`
- `if [ -n "$randomSeed" ]; then echo -s $randomSeed; fi`
- `if [ -n "$minSize" ]; then echo -m $minSize; fi`
- `if [ -n "$maxSize" ]; then echo -M $maxSize; fi`
- parameters:
- host:
- description: list of hosts to connect to
- defaultValue: 127.0.0.1:8091
- bucket:
- description: bucket to use
- defaultValue: default
- username:
- description: username used for authentication to the cluster
- password:
- description: password used for authentication to the cluster
- iterations:
- description: number of iterations to run
- defaultValue: 1000
- numItems:
- description: number of items to operate on
- defaultValue: 1000
- keyPrefix:
- description: prefix for keys
- numThreads:
- description: number of threads to use
- defaultValue: 1
- numInstances:
- description: number of connection instances to put into the shared connection pool
- defaultValue: 1
- randomSeed:
- description: random seed
- defaultValue: 0
- ratio:
- description: "specify SET/GET command ratio (default: 33, i.e. 33% SETs and 67% GETs)"
- defaultValue: 33
- minSize:
- description: minimum size of payload, i.e. document body
- defaultValue: 50
- maxSize:
- description: maximum size of payload, i.e. document body
- defaultValue: 5120
-
-# For CentOS, use the following launch command:
-# launch.command: |
-# sudo wget -O/etc/yum.repos.d/couchbase.repo http://packages.couchbase.com/rpm/couchbase-centos55-x86_64.repo
-# sudo yum check-update
-# sudo yum install -y libcouchbase2-libevent libcouchbase-devel libcouchbase2-bin
-
\ No newline at end of file
[10/17] git commit: expand the vocabulary for looking for entities in
a given scope,
simplify access to scope (use `descendant("xyz")`) and simplify access to
config/attrWhenReady on the same node,
and use static inner classes in YAML DSL objects
Posted by he...@apache.org.
expand the vocabulary for looking for entities in a given scope, simplify access to scope (use `descendant("xyz")`) and simplify access to config/attrWhenReady on the same node, and use static inner classes in YAML DSL objects
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/c6d6cc4a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/c6d6cc4a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/c6d6cc4a
Branch: refs/heads/master
Commit: c6d6cc4aa3800ac361b55956abe10f9dc8dfe7dc
Parents: 05a3948
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Sep 1 11:00:39 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Sep 1 17:07:00 2014 +0100
----------------------------------------------------------------------
.../java/brooklyn/entity/basic/Entities.java | 28 ++++
.../spi/dsl/methods/BrooklynDslCommon.java | 106 ++++++++----
.../brooklyn/spi/dsl/methods/DslComponent.java | 165 +++++++++++++------
.../camp/brooklyn/EntitiesYamlTest.java | 65 +++++++-
.../brooklyn/ReferencingYamlTestEntity.java | 8 +
.../resources/test-referencing-entities.yaml | 23 ++-
.../util/collections/CollectionFunctionals.java | 23 +++
.../java/brooklyn/util/guava/Functionals.java | 12 ++
8 files changed, 333 insertions(+), 97 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c6d6cc4a/core/src/main/java/brooklyn/entity/basic/Entities.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/Entities.java b/core/src/main/java/brooklyn/entity/basic/Entities.java
index 4191110..77f2f5f 100644
--- a/core/src/main/java/brooklyn/entity/basic/Entities.java
+++ b/core/src/main/java/brooklyn/entity/basic/Entities.java
@@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -579,6 +580,33 @@ public class Entities {
}
/**
+ * returns the entity, its parent, its parent, and so on. */
+ public static Iterable<Entity> ancestors(final Entity root) {
+ return new Iterable<Entity>() {
+ @Override
+ public Iterator<Entity> iterator() {
+ return new Iterator<Entity>() {
+ Entity next = root;
+ @Override
+ public boolean hasNext() {
+ return next!=null;
+ }
+ @Override
+ public Entity next() {
+ Entity result = next;
+ next = next.getParent();
+ return result;
+ }
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ };
+ }
+
+ /**
* Registers a {@link BrooklynShutdownHooks#invokeStopOnShutdown(Entity)} to shutdown this entity when the JVM exits.
* (Convenience method located in this class for easy access.)
*/
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c6d6cc4a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
index 16c3b35..0fdea54 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
@@ -21,6 +21,7 @@ package io.brooklyn.camp.brooklyn.spi.dsl.methods;
import io.brooklyn.camp.brooklyn.spi.creation.EntitySpecConfiguration;
import io.brooklyn.camp.brooklyn.spi.dsl.BrooklynDslDeferredSupplier;
import io.brooklyn.camp.brooklyn.spi.dsl.DslUtils;
+import io.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent.Scope;
import java.util.Map;
@@ -34,49 +35,47 @@ import brooklyn.util.exceptions.Exceptions;
/** static import functions which can be used in `$brooklyn:xxx` contexts */
public class BrooklynDslCommon {
- public static Object literal(Object expression) {
- return expression;
+ // --- access specific entities
+
+ public static DslComponent entity(String scopeOrId) {
+ return new DslComponent(Scope.GLOBAL, scopeOrId);
+ }
+ public static DslComponent parent() {
+ return new DslComponent(Scope.PARENT, null);
+ }
+ public static DslComponent child(String scopeOrId) {
+ return new DslComponent(Scope.CHILD, scopeOrId);
+ }
+ public static DslComponent sibling(String scopeOrId) {
+ return new DslComponent(Scope.SIBLING, scopeOrId);
+ }
+ public static DslComponent descendant(String scopeOrId) {
+ return new DslComponent(Scope.DESCENDANT, scopeOrId);
+ }
+ public static DslComponent ancestor(String scopeOrId) {
+ return new DslComponent(Scope.ANCESTOR, scopeOrId);
+ }
+ // prefer the syntax above to the below now -- but not deprecating the below
+ public static DslComponent component(String scopeOrId) {
+ return component("global", scopeOrId);
}
-
- public static DslComponent component(String id) {
- return component("global", id);
- }
-
public static DslComponent component(String scope, String id) {
if (!DslComponent.Scope.isValid(scope)) {
- throw new IllegalArgumentException(scope + " is not a vlaid scope");
+ throw new IllegalArgumentException(scope + " is not a valid scope");
}
return new DslComponent(DslComponent.Scope.fromString(scope), id);
}
-
- /** returns a DslParsedObject<String> OR a String if it is fully resolved */
- public static Object formatString(final String pattern, final Object ...args) {
- if (DslUtils.resolved(args)) {
- // if all args are resolved, apply the format string now
- return String.format(pattern, args);
- }
- return new FormatString(pattern, args);
- }
- protected static final class FormatString extends BrooklynDslDeferredSupplier<String> {
- private static final long serialVersionUID = -4849297712650560863L;
- private String pattern;
- private Object[] args;
+ // --- access things on entities
- public FormatString(String pattern, Object ...args) {
- this.pattern = pattern;
- this.args = args;
- }
- @Override
- public Task<String> newTask() {
- return DependentConfiguration.formatString(pattern, args);
- }
- @Override
- public String toString() {
- return "$brooklyn:formatString("+pattern+")";
- }
+ public static BrooklynDslDeferredSupplier<?> config(String keyName) {
+ return new DslComponent(Scope.THIS, "").config(keyName);
}
-
+
+ public static BrooklynDslDeferredSupplier<?> attributeWhenReady(String sensorName) {
+ return new DslComponent(Scope.THIS, "").attributeWhenReady(sensorName);
+ }
+
// TODO: Would be nice to have sensor(String sensorName), which would take the sensor from the entity in question,
// but that would require refactoring of Brooklyn DSL
// TODO: Should use catalog's classloader, rather than Class.forName; how to get that? Should we return a future?!
@@ -100,10 +99,47 @@ public class BrooklynDslCommon {
} catch (ClassNotFoundException e) {
throw Exceptions.propagate(e);
}
-
}
+ // --- build complex things
+
public static EntitySpecConfiguration entitySpec(Map<String, Object> arguments) {
return new EntitySpecConfiguration(arguments);
}
+
+ // --- string manipulation
+
+ /** return a literal string -- ie skip parsing */
+ public static Object literal(Object expression) {
+ return expression;
+ }
+
+ /** returns a DslParsedObject<String> OR a String if it is fully resolved */
+ public static Object formatString(final String pattern, final Object ...args) {
+ if (DslUtils.resolved(args)) {
+ // if all args are resolved, apply the format string now
+ return String.format(pattern, args);
+ }
+ return new FormatString(pattern, args);
+ }
+
+ protected static final class FormatString extends BrooklynDslDeferredSupplier<String> {
+ private static final long serialVersionUID = -4849297712650560863L;
+ private String pattern;
+ private Object[] args;
+
+ public FormatString(String pattern, Object ...args) {
+ this.pattern = pattern;
+ this.args = args;
+ }
+ @Override
+ public Task<String> newTask() {
+ return DependentConfiguration.formatString(pattern, args);
+ }
+ @Override
+ public String toString() {
+ return "$brooklyn:formatString("+pattern+")";
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c6d6cc4a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
index a1c96c4..e339f1e 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
@@ -27,6 +27,8 @@ import java.util.concurrent.Callable;
import brooklyn.entity.Entity;
import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.basic.EntityPredicates;
import brooklyn.event.AttributeSensor;
import brooklyn.event.Sensor;
@@ -34,6 +36,7 @@ import brooklyn.event.basic.DependentConfiguration;
import brooklyn.event.basic.Sensors;
import brooklyn.management.Task;
import brooklyn.management.internal.EntityManagerInternal;
+import brooklyn.util.guava.Maybe;
import brooklyn.util.task.TaskBuilder;
import brooklyn.util.task.Tasks;
@@ -41,13 +44,13 @@ import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
public class DslComponent extends BrooklynDslDeferredSupplier<Entity> {
private static final long serialVersionUID = -7715984495268724954L;
private final String componentId;
+ private final DslComponent scopeComponent;
private final Scope scope;
public DslComponent(String componentId) {
@@ -55,47 +58,66 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> {
}
public DslComponent(Scope scope, String componentId) {
+ this(null, scope, componentId);
+ }
+
+ public DslComponent(DslComponent scopeComponent, Scope scope, String componentId) {
Preconditions.checkNotNull(scope, "scope");
+ this.scopeComponent = scopeComponent;
this.componentId = componentId;
this.scope = scope;
}
+ // ---------------------------
+
@Override
public Task<Entity> newTask() {
return TaskBuilder.<Entity>builder().name("component("+componentId+")").body(
- new EntityInScopeFinder(scope, componentId)).build();
+ new EntityInScopeFinder(scopeComponent, scope, componentId)).build();
}
protected static class EntityInScopeFinder implements Callable<Entity> {
- protected Scope scope;
- protected String componentId;
+ protected final DslComponent scopeComponent;
+ protected final Scope scope;
+ protected final String componentId;
- public EntityInScopeFinder(Scope scope, String componentId) {
+ public EntityInScopeFinder(DslComponent scopeComponent, Scope scope, String componentId) {
+ this.scopeComponent = scopeComponent;
this.scope = scope;
this.componentId = componentId;
}
+ protected EntityInternal getEntity() {
+ if (scopeComponent!=null) {
+ return (EntityInternal)scopeComponent.get();
+ } else {
+ return entity();
+ }
+ }
+
@Override
public Entity call() throws Exception {
Iterable<Entity> entitiesToSearch = null;
switch (scope) {
case THIS:
- return entity();
+ return getEntity();
case PARENT:
- return entity().getParent();
+ return getEntity().getParent();
case GLOBAL:
- entitiesToSearch = ((EntityManagerInternal)entity().getManagementContext().getEntityManager())
+ entitiesToSearch = ((EntityManagerInternal)getEntity().getManagementContext().getEntityManager())
.getAllEntitiesInApplication( entity().getApplication() );
break;
case DESCENDANT:
- entitiesToSearch = Sets.newLinkedHashSet();
- addDescendants(entity(), (Set<Entity>)entitiesToSearch);
+ entitiesToSearch = Entities.descendants(getEntity());
+ break;
+ case ANCESTOR:
+ entitiesToSearch = Entities.ancestors(getEntity());
break;
case SIBLING:
- entitiesToSearch = entity().getParent().getChildren();
+ entitiesToSearch = getEntity().getParent().getChildren();
break;
case CHILD:
- entitiesToSearch = entity().getChildren();
+ entitiesToSearch = getEntity().getChildren();
break;
default:
throw new IllegalStateException("Unexpected scope "+scope);
@@ -107,31 +129,66 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> {
return result.get();
// TODO may want to block and repeat on new entities joining?
- throw new NoSuchElementException("No entity matching id " + componentId);
+ throw new NoSuchElementException("No entity matching id " + componentId+
+ (scope==Scope.GLOBAL ? "" : ", in scope "+scope+" wrt "+getEntity()+
+ (scopeComponent!=null ? " ("+scopeComponent+" from "+entity()+")" : "")));
}
}
- private static void addDescendants(Entity entity, Set<Entity> entities) {
- entities.add(entity);
- for (Entity child : entity.getChildren()) {
- addDescendants(child, entities);
+ // -------------------------------
+
+ // DSL words which move to a new component
+
+ public DslComponent entity(String scopeOrId) {
+ return new DslComponent(this, Scope.GLOBAL, scopeOrId);
+ }
+ public DslComponent child(String scopeOrId) {
+ return new DslComponent(this, Scope.CHILD, scopeOrId);
+ }
+ public DslComponent sibling(String scopeOrId) {
+ return new DslComponent(this, Scope.SIBLING, scopeOrId);
+ }
+ public DslComponent descendant(String scopeOrId) {
+ return new DslComponent(this, Scope.DESCENDANT, scopeOrId);
+ }
+ public DslComponent ancestor(String scopeOrId) {
+ return new DslComponent(this, Scope.ANCESTOR, scopeOrId);
+ }
+
+ @Deprecated /** @deprecated since 0.7.0 */
+ public DslComponent component(String scopeOrId) {
+ return new DslComponent(this, Scope.GLOBAL, scopeOrId);
+ }
+
+ public DslComponent parent() {
+ return new DslComponent(this, Scope.PARENT, "");
+ }
+
+ public DslComponent component(String scope, String id) {
+ if (!DslComponent.Scope.isValid(scope)) {
+ throw new IllegalArgumentException(scope + " is not a vlaid scope");
}
+ return new DslComponent(this, DslComponent.Scope.fromString(scope), id);
}
+
+ // DSL words which return things
public BrooklynDslDeferredSupplier<?> attributeWhenReady(final String sensorName) {
- return new AttributeWhenReady(sensorName);
+ return new AttributeWhenReady(this, sensorName);
}
// class simply makes the memento XML files nicer
- protected class AttributeWhenReady extends BrooklynDslDeferredSupplier<Object> {
+ protected static class AttributeWhenReady extends BrooklynDslDeferredSupplier<Object> {
private static final long serialVersionUID = 1740899524088902383L;
- private String sensorName;
- public AttributeWhenReady(String sensorName) {
+ private final DslComponent component;
+ private final String sensorName;
+ public AttributeWhenReady(DslComponent component, String sensorName) {
+ this.component = Preconditions.checkNotNull(component);
this.sensorName = sensorName;
}
@SuppressWarnings("unchecked")
@Override
public Task<Object> newTask() {
- Entity targetEntity = DslComponent.this.get();
+ Entity targetEntity = component.get();
Sensor<?> targetSensor = targetEntity.getEntityType().getSensor(sensorName);
if (!(targetSensor instanceof AttributeSensor<?>)) {
targetSensor = Sensors.newSensor(Object.class, sensorName);
@@ -140,39 +197,50 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> {
}
@Override
public String toString() {
- return DslComponent.this.toString()+"."+"attributeWhenReady("+sensorName+")";
+ return component.toString()+"."+"attributeWhenReady("+sensorName+")";
}
}
-
- public BrooklynDslDeferredSupplier<Object> config(final String keyName) {
- return new BrooklynDslDeferredSupplier<Object>() {
- private static final long serialVersionUID = -4735177561947722511L;
- @Override
- public Task<Object> newTask() {
- return Tasks.builder().name("retrieving config for "+keyName).dynamic(false).body(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- Entity targetEntity = DslComponent.this.get();
- return targetEntity.getConfig(ConfigKeys.newConfigKey(Object.class, keyName));
- }
- }).build();
- }
- @Override
- public String toString() {
- return DslComponent.this.toString()+"."+"config("+keyName+")";
- }
- };
+
+ public BrooklynDslDeferredSupplier<?> config(final String keyName) {
+ return new DslConfigSupplier(this, keyName);
}
-
+ protected final static class DslConfigSupplier extends BrooklynDslDeferredSupplier<Object> {
+ private final DslComponent component;
+ private final String keyName;
+ private static final long serialVersionUID = -4735177561947722511L;
+
+ public DslConfigSupplier(DslComponent component, String keyName) {
+ this.component = Preconditions.checkNotNull(component);
+ this.keyName = keyName;
+ }
+
+ @Override
+ public Task<Object> newTask() {
+ return Tasks.builder().name("retrieving config for "+keyName).dynamic(false).body(new Callable<Object>() {
+ @Override
+ public Object call() throws Exception {
+ Entity targetEntity = component.get();
+ return targetEntity.getConfig(ConfigKeys.newConfigKey(Object.class, keyName));
+ }
+ }).build();
+ }
+
+ @Override
+ public String toString() {
+ return component.toString()+"."+"config("+keyName+")";
+ }
+ }
+
public static enum Scope {
GLOBAL ("global"),
CHILD ("child"),
PARENT ("parent"),
SIBLING ("sibling"),
DESCENDANT ("descendant"),
+ ANCESTOR("ancestor"),
THIS ("this");
- public static final Set<Scope> VALUES = ImmutableSet.of(GLOBAL, CHILD, PARENT, SIBLING, DESCENDANT, THIS);
+ public static final Set<Scope> VALUES = ImmutableSet.of(GLOBAL, CHILD, PARENT, SIBLING, DESCENDANT, ANCESTOR, THIS);
private final String name;
@@ -181,10 +249,14 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> {
}
public static Scope fromString(String name) {
+ return tryFromString(name).get();
+ }
+
+ public static Maybe<Scope> tryFromString(String name) {
for (Scope scope : VALUES)
if (scope.name.toLowerCase().equals(name.toLowerCase()))
- return scope;
- throw new IllegalArgumentException(name + " is not a valid scope");
+ return Maybe.of(scope);
+ return Maybe.absent(new IllegalArgumentException(name + " is not a valid scope"));
}
public static boolean isValid(String name) {
@@ -199,6 +271,7 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> {
@Override
public String toString() {
return "$brooklyn:component("+
+ (scopeComponent==null ? "" : scopeComponent+", ")+
(scope==Scope.GLOBAL ? "" : scope+", ")+
componentId+
")";
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c6d6cc4a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EntitiesYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EntitiesYamlTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EntitiesYamlTest.java
index 53bb4aa..588faf0 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EntitiesYamlTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EntitiesYamlTest.java
@@ -21,6 +21,9 @@ package io.brooklyn.camp.brooklyn;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
+import io.brooklyn.camp.brooklyn.spi.dsl.methods.BrooklynDslCommon;
+import io.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent;
+import io.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent.Scope;
import java.io.StringReader;
import java.util.Iterator;
@@ -43,7 +46,9 @@ import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.BasicEntity;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityFunctions;
import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.basic.EntityPredicates;
import brooklyn.entity.basic.Lifecycle;
import brooklyn.entity.basic.SameServerEntity;
import brooklyn.entity.effector.Effectors;
@@ -56,8 +61,13 @@ import brooklyn.management.Task;
import brooklyn.management.internal.EntityManagerInternal;
import brooklyn.test.entity.TestEntity;
import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Functionals;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.task.Tasks;
import brooklyn.util.time.Duration;
+import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
@@ -350,9 +360,33 @@ public class EntitiesYamlTest extends AbstractYamlTest {
}
@Test
+ public void testMultipleReferencesJava() throws Exception {
+ final Entity app = createAndStartApplication(loadYaml("test-referencing-entities.yaml"));
+ waitForApplicationTasks(app);
+
+ Entity c1 = Tasks.resolving(new DslComponent("c1").newTask(), Entity.class).context( ((EntityInternal)app).getExecutionContext() ).embedResolutionInTask(true).get();
+ Assert.assertEquals(c1, Entities.descendants(app, EntityPredicates.displayNameEqualTo("child 1")).iterator().next());
+
+ Entity e1 = Tasks.resolving(new DslComponent(Scope.PARENT, "xxx").newTask(), Entity.class).context( ((EntityInternal)c1).getExecutionContext() ).embedResolutionInTask(true).get();
+ Assert.assertEquals(e1, Entities.descendants(app, EntityPredicates.displayNameEqualTo("entity 1")).iterator().next());
+
+ Entity c1a = Tasks.resolving(BrooklynDslCommon.descendant("c1").newTask(), Entity.class).context( ((EntityInternal)e1).getExecutionContext() ).embedResolutionInTask(true).get();
+ Assert.assertEquals(c1a, c1);
+ Entity e1a = Tasks.resolving(BrooklynDslCommon.ancestor("e1").newTask(), Entity.class).context( ((EntityInternal)c1).getExecutionContext() ).embedResolutionInTask(true).get();
+ Assert.assertEquals(e1a, e1);
+ try {
+ Tasks.resolving(BrooklynDslCommon.ancestor("c1").newTask(), Entity.class).context( ((EntityInternal)e1).getExecutionContext() ).embedResolutionInTask(true).get();
+ Assert.fail("Should not have found c1 as ancestor of e1");
+ } catch (Exception e) { /* expected */ }
+ }
+
+ @Test
public void testMultipleReferences() throws Exception {
final Entity app = createAndStartApplication(loadYaml("test-referencing-entities.yaml"));
waitForApplicationTasks(app);
+
+ Entities.dumpInfo(app);
+
Assert.assertEquals(app.getDisplayName(), "test-referencing-entities");
Entity entity1 = null, entity2 = null, child1 = null, child2 = null, grandchild1 = null, grandchild2 = null;
@@ -390,6 +424,7 @@ public class EntitiesYamlTest extends AbstractYamlTest {
Map<ConfigKey<Entity>, Entity> keyToEntity = new ImmutableMap.Builder<ConfigKey<Entity>, Entity>()
.put(ReferencingYamlTestEntity.TEST_REFERENCE_APP, app)
.put(ReferencingYamlTestEntity.TEST_REFERENCE_ENTITY1, entity1)
+ .put(ReferencingYamlTestEntity.TEST_REFERENCE_ENTITY1_ALT, entity1)
.put(ReferencingYamlTestEntity.TEST_REFERENCE_ENTITY2, entity2)
.put(ReferencingYamlTestEntity.TEST_REFERENCE_CHILD1, child1)
.put(ReferencingYamlTestEntity.TEST_REFERENCE_CHILD2, child2)
@@ -404,22 +439,36 @@ public class EntitiesYamlTest extends AbstractYamlTest {
}
}).get();
- for (Entity entityInApp : entitiesInApp)
+ for (Entity entityInApp : entitiesInApp) {
checkReferences(entityInApp, keyToEntity);
+ try {
+ getResolvedConfigInTask(entityInApp, ReferencingYamlTestEntity.TEST_REFERENCE_BOGUS);
+ Assert.fail("Should not have resolved "+ReferencingYamlTestEntity.TEST_REFERENCE_BOGUS+" at "+entityInApp);
+ } catch (Exception e) {
+ /* expected */
+ }
+ }
}
private void checkReferences(final Entity entity, Map<ConfigKey<Entity>, Entity> keyToEntity) throws Exception {
for (final ConfigKey<Entity> key : keyToEntity.keySet()) {
- Entity fromConfig = ((EntityInternal)entity).getExecutionContext().submit(MutableMap.of(), new Callable<Entity>() {
- @Override
- public Entity call() throws Exception {
- return (Entity) entity.getConfig(key);
- }
- }).get();
- Assert.assertEquals(fromConfig, keyToEntity.get(key));
+ try {
+ Assert.assertEquals(getResolvedConfigInTask(entity, key).get(), keyToEntity.get(key));
+ } catch (Throwable t) {
+ Exceptions.propagateIfFatal(t);
+ Assert.fail("Wrong value for "+entity+":"+key+", "+entity.getConfigRaw(key, false)+": "+t, t);
+ }
}
}
+ private Maybe<Entity> getResolvedConfigInTask(final Entity entity, final ConfigKey<Entity> key) {
+ return Tasks.resolving(Tasks.<Entity>builder().body(
+ Functionals.callable(Suppliers.compose(EntityFunctions.config(key), Suppliers.ofInstance(entity))) ).build())
+ .as(Entity.class)
+ .context( ((EntityInternal)entity).getExecutionContext() ).embedResolutionInTask(true)
+ .getMaybe();
+ }
+
public void testWithAppLocation() throws Exception {
Entity app = createAndStartApplication(loadYaml("test-entity-basic-template.yaml",
"location: localhost:(name=yaml name)"));
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c6d6cc4a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ReferencingYamlTestEntity.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ReferencingYamlTestEntity.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ReferencingYamlTestEntity.java
index ca6c5a3..02d778a 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ReferencingYamlTestEntity.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ReferencingYamlTestEntity.java
@@ -36,6 +36,10 @@ public interface ReferencingYamlTestEntity extends Entity {
.name("test.reference.entity1")
.build();
@SuppressWarnings("serial")
+ public static final ConfigKey<Entity> TEST_REFERENCE_ENTITY1_ALT = BasicConfigKey.builder(new TypeToken<Entity>(){})
+ .name("test.reference.entity1a")
+ .build();
+ @SuppressWarnings("serial")
public static final ConfigKey<Entity> TEST_REFERENCE_ENTITY2 = BasicConfigKey.builder(new TypeToken<Entity>(){})
.name("test.reference.entity2")
.build();
@@ -55,4 +59,8 @@ public interface ReferencingYamlTestEntity extends Entity {
public static final ConfigKey<Entity> TEST_REFERENCE_GRANDCHILD2 = BasicConfigKey.builder(new TypeToken<Entity>(){})
.name("test.reference.grandchild2")
.build();
+ @SuppressWarnings("serial")
+ public static final ConfigKey<Entity> TEST_REFERENCE_BOGUS = BasicConfigKey.builder(new TypeToken<Entity>(){})
+ .name("test.reference.bogus")
+ .build();
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c6d6cc4a/usage/camp/src/test/resources/test-referencing-entities.yaml
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/resources/test-referencing-entities.yaml b/usage/camp/src/test/resources/test-referencing-entities.yaml
index 84a8d3f..7a5dfec 100644
--- a/usage/camp/src/test/resources/test-referencing-entities.yaml
+++ b/usage/camp/src/test/resources/test-referencing-entities.yaml
@@ -38,36 +38,43 @@ origin: http://brooklyn.io
id: app1
brooklyn.config:
test.reference.app: $brooklyn:component("app1")
- test.reference.entity1: $brooklyn:component("e1")
+ test.reference.entity1: $brooklyn:entity("e1")
+ test.reference.entity1a: $brooklyn:config("test.reference.entity1")
test.reference.entity2: $brooklyn:component("e2")
test.reference.child1: $brooklyn:component("c1")
test.reference.child2: $brooklyn:component("c2")
test.reference.grandchild1: $brooklyn:component("gc1")
test.reference.grandchild2: $brooklyn:component("gc2")
+ test.reference.bogus: $brooklyn:child("c1")
services:
- serviceType: io.brooklyn.camp.brooklyn.ReferencingYamlTestEntity
id: e1
name: entity 1
brooklyn.config:
- test.reference.app: $brooklyn:component("app1")
- test.reference.entity1: $brooklyn:component("e1")
+ test.reference.app: $brooklyn:component("parent", "ignored")
+ test.reference.entity1: $brooklyn:component("this", "ignored")
+ test.reference.entity1a: $brooklyn:ancestor("app1").child("e1")
test.reference.entity2: $brooklyn:component("e2")
- test.reference.child1: $brooklyn:component("c1")
+ test.reference.child1: $brooklyn:component("child", "c1")
test.reference.child2: $brooklyn:component("c2")
test.reference.grandchild1: $brooklyn:component("gc1")
test.reference.grandchild2: $brooklyn:component("gc2")
+ test.reference.bogus: $brooklyn:descendant("app1")
brooklyn.children:
- serviceType: io.brooklyn.camp.brooklyn.ReferencingYamlTestEntity
id: c1
name: child 1
brooklyn.config:
- test.reference.app: $brooklyn:component("app1")
- test.reference.entity1: $brooklyn:component("e1")
+ self: $brooklyn:entity("c1")
+ test.reference.app: $brooklyn:parent().parent()
+ test.reference.entity1: $brooklyn:parent()
+ test.reference.entity1a: $brooklyn:entity("e1").parent().child("e1")
test.reference.entity2: $brooklyn:component("e2")
- test.reference.child1: $brooklyn:component("c1")
+ test.reference.child1: $brooklyn:config("self")
test.reference.child2: $brooklyn:component("c2")
test.reference.grandchild1: $brooklyn:component("gc1")
test.reference.grandchild2: $brooklyn:component("gc2")
+ test.reference.bogus: $brooklyn:component("bogus")
brooklyn.children:
- serviceType: io.brooklyn.camp.brooklyn.ReferencingYamlTestEntity
id: gc1
@@ -95,7 +102,7 @@ services:
id: c2
name: child 2
brooklyn.config:
- test.reference.app: $brooklyn:component("app1")
+ test.reference.app: $brooklyn:parent().parent().descendant("app1")
test.reference.entity1: $brooklyn:component("e1")
test.reference.entity2: $brooklyn:component("e2")
test.reference.child1: $brooklyn:component("c1")
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c6d6cc4a/utils/common/src/main/java/brooklyn/util/collections/CollectionFunctionals.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/collections/CollectionFunctionals.java b/utils/common/src/main/java/brooklyn/util/collections/CollectionFunctionals.java
index f7b1dd0..0a5570d 100644
--- a/utils/common/src/main/java/brooklyn/util/collections/CollectionFunctionals.java
+++ b/utils/common/src/main/java/brooklyn/util/collections/CollectionFunctionals.java
@@ -19,6 +19,7 @@
package brooklyn.util.collections;
import java.util.Arrays;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -130,4 +131,26 @@ public class CollectionFunctionals {
return Predicates.compose(Predicates.equalTo(targetSize), CollectionFunctionals.<K>mapSize());
}
+ public static <T,I extends Iterable<T>> Function<I, List<T>> limit(final int max) {
+ return new LimitFunction<T,I>(max);
+ }
+
+ private static final class LimitFunction<T, I extends Iterable<T>> implements Function<I, List<T>> {
+ private final int max;
+ private LimitFunction(int max) {
+ this.max = max;
+ }
+ @Override
+ public List<T> apply(I input) {
+ if (input==null) return null;
+ MutableList<T> result = MutableList.of();
+ for (T i: input) {
+ result.add(i);
+ if (result.size()>=max)
+ return result;
+ }
+ return result;
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c6d6cc4a/utils/common/src/main/java/brooklyn/util/guava/Functionals.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/guava/Functionals.java b/utils/common/src/main/java/brooklyn/util/guava/Functionals.java
index ef66ded..6688bab 100644
--- a/utils/common/src/main/java/brooklyn/util/guava/Functionals.java
+++ b/utils/common/src/main/java/brooklyn/util/guava/Functionals.java
@@ -18,6 +18,8 @@
*/
package brooklyn.util.guava;
+import java.util.concurrent.Callable;
+
import brooklyn.util.guava.IfFunctions.IfFunctionBuilderApplyingFirst;
import com.google.common.base.Function;
@@ -111,4 +113,14 @@ public class Functionals {
return new SupplierAsRunnable();
}
+ public static <T> Callable<T> callable(final Supplier<T> supplier) {
+ class SupplierAsCallable implements Callable<T> {
+ @Override
+ public T call() {
+ return supplier.get();
+ }
+ }
+ return new SupplierAsCallable();
+ }
+
}
[16/17] git commit: Merge branch 'master' into couchbase
Posted by he...@apache.org.
Merge branch 'master' into couchbase
Conflicts:
core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java - imports
software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java - install commands
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/d23d5c09
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/d23d5c09
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/d23d5c09
Branch: refs/heads/master
Commit: d23d5c09d2133e406d27d445979cc73e991fe185
Parents: 1064cd5 68592b4
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Sep 1 17:10:32 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Sep 1 17:10:32 2014 +0100
----------------------------------------------------------------------
.../entity/basic/BrooklynConfigKeys.java | 101 ++++-----
.../brooklyn/entity/group/DynamicCluster.java | 14 ++
.../entity/group/DynamicClusterImpl.java | 26 ++-
.../basic/PortAttributeSensorAndConfigKey.java | 59 +++---
.../java/brooklyn/util/flags/TypeCoercions.java | 10 +
.../main/java/brooklyn/util/task/BasicTask.java | 3 +-
pom.xml | 2 +-
.../nosql/infinispan/Infinispan5SshDriver.java | 5 -
.../basic/AbstractSoftwareProcessDriver.java | 50 ++++-
.../basic/AbstractSoftwareProcessSshDriver.java | 27 +++
.../entity/basic/EmptySoftwareProcessImpl.java | 11 +-
.../brooklyn/entity/basic/SoftwareProcess.java | 98 +++++----
.../entity/basic/VanillaSoftwareProcess.java | 44 ++--
.../basic/VanillaSoftwareProcessSshDriver.java | 2 -
.../brooklynnode/BrooklynNodeSshDriver.java | 16 +-
.../java/JavaSoftwareProcessSshDriver.java | 8 +-
.../java/brooklyn/entity/java/JmxSupport.java | 109 +++++-----
.../main/java/brooklyn/entity/java/UsesJmx.java | 116 +++++------
.../entity/machine/MachineEntityImpl.java | 3 +-
.../software/MachineLifecycleEffectorTasks.java | 205 +++++++++++--------
.../database/mariadb/MariaDbSshDriver.java | 14 +-
.../entity/database/mysql/MySqlSshDriver.java | 11 +-
.../database/rubyrep/RubyRepSshDriver.java | 13 +-
.../messaging/activemq/ActiveMQSshDriver.java | 9 +-
.../kafka/AbstractfKafkaSshDriver.java | 11 +-
.../entity/messaging/qpid/QpidBroker.java | 10 -
.../entity/messaging/qpid/QpidSshDriver.java | 11 +-
.../messaging/rabbit/RabbitSshDriver.java | 10 +-
.../entity/messaging/storm/StormSshDriver.java | 10 +-
.../entity/zookeeper/ZooKeeperSshDriver.java | 9 +-
.../entity/monitoring/monit/MonitSshDriver.java | 14 +-
.../nosql/cassandra/CassandraNodeSshDriver.java | 12 +-
.../nosql/couchbase/CouchbaseNodeSshDriver.java | 8 +-
.../ElasticSearchNodeSshDriver.java | 10 +-
.../nosql/mongodb/AbstractMongoDBSshDriver.java | 10 +-
.../entity/nosql/redis/RedisStoreSshDriver.java | 10 +-
.../entity/nosql/riak/RiakNodeSshDriver.java | 23 ++-
.../entity/nosql/solr/SolrServerSshDriver.java | 13 +-
.../entity/osgi/karaf/KarafSshDriver.java | 11 +-
.../brooklyn/entity/proxy/ProxySslConfig.java | 20 +-
.../entity/proxy/nginx/NginxSshDriver.java | 14 +-
.../entity/webapp/jboss/JBoss6SshDriver.java | 9 +-
.../entity/webapp/jboss/JBoss7SshDriver.java | 9 +-
.../entity/webapp/jetty/Jetty6SshDriver.java | 9 +-
.../webapp/nodejs/NodeJsWebAppDriver.java | 2 +
.../webapp/nodejs/NodeJsWebAppSshDriver.java | 9 +
.../entity/webapp/tomcat/Tomcat7SshDriver.java | 8 +-
.../java/brooklyn/rest/client/BrooklynApi.java | 51 +++--
48 files changed, 761 insertions(+), 498 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d23d5c09/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
----------------------------------------------------------------------
diff --cc core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
index 647ddaa,d0e273f..be7724d
--- a/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
+++ b/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
@@@ -39,10 -41,10 +41,11 @@@ import brooklyn.entity.basic.DelegateEn
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityFactory;
import brooklyn.entity.basic.EntityFactoryForLocation;
+ import brooklyn.entity.basic.EntityLocal;
import brooklyn.entity.basic.Lifecycle;
import brooklyn.entity.basic.QuorumCheck.QuorumChecks;
- import brooklyn.entity.basic.ServiceStateLogic.ServiceProblemsLogic;
import brooklyn.entity.basic.ServiceStateLogic;
++import brooklyn.entity.basic.ServiceStateLogic.ServiceProblemsLogic;
import brooklyn.entity.effector.Effectors;
import brooklyn.entity.proxying.EntitySpec;
import brooklyn.entity.trait.Startable;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d23d5c09/core/src/main/java/brooklyn/util/flags/TypeCoercions.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d23d5c09/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
----------------------------------------------------------------------
diff --cc software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
index 6dc3cfb,ff56859..3269aad
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
@@@ -37,15 -25,8 +37,14 @@@ import org.apache.http.auth.UsernamePas
import brooklyn.entity.basic.AbstractSoftwareProcessSshDriver;
import brooklyn.entity.basic.Entities;
- import brooklyn.entity.drivers.downloads.DownloadResolver;
+import brooklyn.event.feed.http.HttpValueFunctions;
+import brooklyn.event.feed.http.JsonFunctions;
import brooklyn.location.OsDetails;
import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.util.guava.Functionals;
+import brooklyn.util.http.HttpTool;
+import brooklyn.util.http.HttpToolResponse;
+import brooklyn.util.repeat.Repeater;
import brooklyn.util.ssh.BashCommands;
import brooklyn.util.task.Tasks;
import brooklyn.util.time.Duration;
[17/17] git commit: This closes #137
Posted by he...@apache.org.
This closes #137
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/be939616
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/be939616
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/be939616
Branch: refs/heads/master
Commit: be93961605489a70b183d2f0c4a26ab0dd7afac1
Parents: 68592b4 d23d5c0
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Sep 1 17:14:03 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Sep 1 17:14:03 2014 +0100
----------------------------------------------------------------------
.../java/brooklyn/entity/basic/Entities.java | 28 ++
.../entity/group/DynamicClusterImpl.java | 125 ++++----
.../JavaBrooklynClassLoadingContext.java | 2 +-
.../java/brooklyn/util/flags/TypeCoercions.java | 11 +-
.../main/java/brooklyn/util/http/HttpTool.java | 9 +-
.../src/main/java/brooklyn/util/task/Tasks.java | 124 ++------
.../java/brooklyn/util/task/ValueResolver.java | 284 +++++++++++++++++++
.../test/java/brooklyn/util/task/TasksTest.java | 1 +
.../brooklyn/util/task/ValueResolverTest.java | 75 +++++
.../brooklynnode/BrooklynEntityMirrorImpl.java | 3 +-
.../nosql/couchbase/CouchbaseCluster.java | 32 ++-
.../nosql/couchbase/CouchbaseClusterImpl.java | 194 +++++++++++--
.../nosql/couchbase/CouchbaseLoadGenerator.java | 59 ----
.../couchbase/CouchbaseLoadGeneratorDriver.java | 28 --
.../couchbase/CouchbaseLoadGeneratorImpl.java | 50 ----
.../CouchbaseLoadGeneratorSshDriver.java | 122 --------
.../entity/nosql/couchbase/CouchbaseNode.java | 6 +
.../nosql/couchbase/CouchbaseNodeDriver.java | 2 +
.../nosql/couchbase/CouchbaseNodeImpl.java | 53 ++++
.../nosql/couchbase/CouchbaseNodeSshDriver.java | 138 ++++++++-
.../nosql/couchbase/CouchbaseSyncGateway.java | 75 +++++
.../couchbase/CouchbaseSyncGatewayDriver.java | 27 ++
.../couchbase/CouchbaseSyncGatewayImpl.java | 82 ++++++
.../CouchbaseSyncGatewaySshDriver.java | 176 ++++++++++++
.../entity/nosql/couchbase/pillowfight.yaml | 77 +++++
.../CouchbaseSyncGatewayEc2LiveTest.java | 137 +++++++++
.../BrooklynComponentTemplateResolver.java | 6 +-
.../spi/dsl/methods/BrooklynDslCommon.java | 106 ++++---
.../brooklyn/spi/dsl/methods/DslComponent.java | 165 ++++++++---
.../camp/brooklyn/EntitiesYamlTest.java | 65 ++++-
.../brooklyn/ReferencingYamlTestEntity.java | 8 +
.../resources/test-referencing-entities.yaml | 23 +-
.../src/test/resources/couchbase-w-loadgen.yaml | 54 ++++
.../test/resources/couchbase-w-pillowfight.yaml | 35 +++
.../launcher/src/test/resources/couchbase.yaml | 14 +-
.../BrooklynPropertiesSecurityFilter.java | 9 +-
.../rest/transform/EffectorTransformer.java | 28 +-
.../util/collections/CollectionFunctionals.java | 23 ++
.../java/brooklyn/util/guava/Functionals.java | 12 +
.../guava/IllegalStateExceptionSupplier.java | 41 +++
.../main/java/brooklyn/util/guava/Maybe.java | 40 ++-
.../main/java/brooklyn/util/time/Durations.java | 26 ++
42 files changed, 1981 insertions(+), 594 deletions(-)
----------------------------------------------------------------------
[03/17] git commit: Copied in @ZaidM's work from
https://github.com/ZaidM/brooklyn/tree/couchbase-sync-gateway1
Posted by he...@apache.org.
Copied in @ZaidM's work from https://github.com/ZaidM/brooklyn/tree/couchbase-sync-gateway1
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/4f70aa11
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/4f70aa11
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/4f70aa11
Branch: refs/heads/master
Commit: 4f70aa1172f0900c4a77f9c5a03d3132900c0440
Parents: 21a037f
Author: Martin Harris <gi...@nakomis.com>
Authored: Fri Jun 20 10:34:39 2014 +0100
Committer: Martin Harris <gi...@nakomis.com>
Committed: Mon Aug 18 15:45:43 2014 +0100
----------------------------------------------------------------------
.../nosql/couchbase/CouchbaseCluster.java | 23 ++-
.../nosql/couchbase/CouchbaseClusterImpl.java | 68 ++++++++-
.../entity/nosql/couchbase/CouchbaseNode.java | 6 +
.../nosql/couchbase/CouchbaseNodeDriver.java | 2 +
.../nosql/couchbase/CouchbaseNodeImpl.java | 4 +
.../nosql/couchbase/CouchbaseNodeSshDriver.java | 12 ++
.../nosql/couchbase/CouchbaseSyncGateway.java | 61 ++++++++
.../couchbase/CouchbaseSyncGatewayDriver.java | 9 ++
.../couchbase/CouchbaseSyncGatewayImpl.java | 61 ++++++++
.../CouchbaseSyncGatewaySshDriver.java | 147 +++++++++++++++++++
10 files changed, 390 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4f70aa11/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseCluster.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseCluster.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseCluster.java
index b44f47a..c478b07 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseCluster.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseCluster.java
@@ -19,10 +19,9 @@
package brooklyn.entity.nosql.couchbase;
import java.util.List;
+import java.util.Map;
import java.util.Set;
-import com.google.common.reflect.TypeToken;
-
import brooklyn.config.ConfigKey;
import brooklyn.entity.Entity;
import brooklyn.entity.basic.ConfigKeys;
@@ -33,6 +32,8 @@ import brooklyn.event.basic.Sensors;
import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.time.Duration;
+import com.google.common.reflect.TypeToken;
+
@ImplementedBy(CouchbaseClusterImpl.class)
public interface CouchbaseCluster extends DynamicCluster {
@@ -90,4 +91,22 @@ public interface CouchbaseCluster extends DynamicCluster {
"Average across cluster for pools/nodes/<current node>/interestingStats/couch_docs_actual_disk_size");
AttributeSensor<Long> COUCH_VIEWS_DATA_SIZE_PER_NODE = Sensors.newLongSensor("couchbase.stats.cluster.per.node.couch.views.data.size",
"Average across cluster for pools/nodes/<current node>/interestingStats/couch_views_data_size");
+
+ AttributeSensor<Boolean> BUCKET_CREATION_IN_PROGRESS = Sensors.newBooleanSensor("couchbase.cluster.bucketCreationInProgress", "Indicates that a bucket is currently being created, and" +
+ "further bucket creation should be deferred");
+
+ /**
+ * createBuckets is a list of all the buckets to be created on the couchbase cluster
+ * the buckets will be created on the primary node of the cluster
+ * each map entry for a bucket should contain the following parameters:
+ * - <"bucket",(String) name of the bucket (default: default)>
+ * - <"bucket-type",(String) name of bucket type (default: couchbase)>
+ * - <"bucket-port",(Integer) the bucket port to connect to (default: 11222)>
+ * - <"bucket-ramsize",(Integer) ram size allowed for bucket (default: 200)>
+ * - <"bucket-replica",(Integer) number of replicas for the bucket (default: 1)>
+ */
+ @SuppressWarnings("serial")
+ @SetFromFlag("createBuckets")
+ ConfigKey<List<Map<String, Object>>> CREATE_BUCKETS = ConfigKeys.newConfigKey(new TypeToken<List<Map<String, Object>>>() {},
+ "couchbase.cluster.createBuckets", "a list of all dedicated port buckets to be created on the couchbase cluster");
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4f70aa11/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
index 11c56d7..b7c2026 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
@@ -24,6 +24,8 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,16 +44,24 @@ import brooklyn.entity.trait.Startable;
import brooklyn.event.AttributeSensor;
import brooklyn.event.SensorEvent;
import brooklyn.event.SensorEventListener;
+import brooklyn.event.basic.DependentConfiguration;
+import brooklyn.event.feed.http.HttpFeed;
+import brooklyn.event.feed.http.HttpPollConfig;
+import brooklyn.event.feed.http.HttpValueFunctions;
import brooklyn.location.Location;
import brooklyn.policy.PolicySpec;
import brooklyn.util.collections.MutableSet;
+import brooklyn.util.task.DynamicTasks;
+import brooklyn.util.task.TaskBuilder;
import brooklyn.util.task.Tasks;
import brooklyn.util.text.ByteSizeStrings;
import brooklyn.util.time.Time;
import com.google.common.base.Function;
+import com.google.common.base.Functions;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
@@ -59,6 +69,7 @@ import com.google.common.collect.Sets;
public class CouchbaseClusterImpl extends DynamicClusterImpl implements CouchbaseCluster {
private static final Logger log = LoggerFactory.getLogger(CouchbaseClusterImpl.class);
private final Object mutex = new Object[0];
+ private final HttpFeed[] resetBucketCreation = new HttpFeed[]{null};
public void init() {
log.info("Initializing the Couchbase cluster...");
@@ -146,7 +157,7 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
serversToAdd.remove(getPrimaryNode());
if (getUpNodes().size() >= getQuorumSize() && getUpNodes().size() > 1) {
- log.info("number of SERVICE_UP nodes:{} in cluster:{} did reached Quorum:{}, adding the servers", new Object[]{getUpNodes().size(), getId(), getQuorumSize()});
+ log.info("number of SERVICE_UP nodes:{} in cluster:{} reached Quorum:{}, adding the servers", new Object[]{getUpNodes().size(), getId(), getQuorumSize()});
addServers(serversToAdd);
//wait for servers to be added to the couchbase server
@@ -157,6 +168,10 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
Tasks.resetBlockingDetails();
}
Entities.invokeEffector(this, getPrimaryNode(), CouchbaseNode.REBALANCE);
+
+ if (Optional.fromNullable(CREATE_BUCKETS).isPresent()) {
+ createBuckets();
+ }
setAttribute(IS_CLUSTER_INITIALIZED, true);
} else {
@@ -333,6 +348,57 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
return Optional.fromNullable(e.getAttribute(CouchbaseNode.IS_IN_CLUSTER)).or(false);
}
+ public void createBuckets() {
+ //FIXME: multiple buckets require synchronization/wait time (checks for port conflicts and exceeding ram size)
+ //TODO: check for multiple bucket conflicts with port
+ List<Map<String, Object>> bucketsToCreate = getConfig(CREATE_BUCKETS);
+ Entity primaryNode = getPrimaryNode();
+
+ for (Map<String, Object> bucketMap : bucketsToCreate) {
+ String bucketName = bucketMap.containsKey("bucket") ? (String) bucketMap.get("bucket") : "default";
+ String bucketType = bucketMap.containsKey("bucket-type") ? (String) bucketMap.get("bucket-type") : "couchbase";
+ Integer bucketPort = bucketMap.containsKey("bucket-port") ? (Integer) bucketMap.get("bucket-port") : 11222;
+ Integer bucketRamSize = bucketMap.containsKey("bucket-ramsize") ? (Integer) bucketMap.get("bucket-ramsize") : 200;
+ Integer bucketReplica = bucketMap.containsKey("bucket-replica") ? (Integer) bucketMap.get("bucket-replica") : 1;
+
+ log.info("adding bucket: {} to primary node: {}", bucketName, primaryNode.getId());
+ createBucket(primaryNode, bucketName, bucketType, bucketPort, bucketRamSize, bucketReplica);
+ //TODO: add if bucket has been created.
+ }
+ }
+
+ public void createBucket(final Entity primaryNode, final String bucketName, final String bucketType, final Integer bucketPort, final Integer bucketRamSize, final Integer bucketReplica) {
+ DynamicTasks.queueIfPossible(TaskBuilder.<Void>builder().name("Creating bucket " + bucketName).body(
+ new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ DependentConfiguration.waitInTaskForAttributeReady(CouchbaseClusterImpl.this, CouchbaseCluster.BUCKET_CREATION_IN_PROGRESS, Predicates.equalTo(false));
+ if (CouchbaseClusterImpl.this.resetBucketCreation[0] != null) {
+ CouchbaseClusterImpl.this.resetBucketCreation[0].stop();
+ }
+ setAttribute(CouchbaseCluster.BUCKET_CREATION_IN_PROGRESS, true);
+
+ CouchbaseClusterImpl.this.resetBucketCreation[0] = HttpFeed.builder()
+ .entity(CouchbaseClusterImpl.this)
+ .period(500, TimeUnit.MILLISECONDS)
+ .baseUri(String.format("%s/pools/default/buckets/%s", primaryNode.getAttribute(CouchbaseNode.COUCHBASE_WEB_ADMIN_URL), bucketName))
+ .credentials(primaryNode.getConfig(CouchbaseNode.COUCHBASE_ADMIN_USERNAME), primaryNode.getConfig(CouchbaseNode.COUCHBASE_ADMIN_PASSWORD))
+ .poll(new HttpPollConfig<Boolean>(BUCKET_CREATION_IN_PROGRESS)
+ .onSuccess(HttpValueFunctions.responseCodeEquals(404))
+ .onFailureOrException(Functions.constant(false)))
+ .build();
+
+ Entities.invokeEffectorWithArgs(CouchbaseClusterImpl.this, primaryNode, CouchbaseNode.BUCKET_CREATE, bucketName, bucketType, bucketPort, bucketRamSize, bucketReplica);
+ DependentConfiguration.waitInTaskForAttributeReady(CouchbaseClusterImpl.this, CouchbaseCluster.BUCKET_CREATION_IN_PROGRESS, Predicates.equalTo(false));
+ if (CouchbaseClusterImpl.this.resetBucketCreation[0] != null) {
+ CouchbaseClusterImpl.this.resetBucketCreation[0].stop();
+ }
+ return null;
+ }
+ }
+ ).build()).orSubmitAndBlock();
+ }
+
static {
RendererHints.register(COUCH_DOCS_DATA_SIZE_PER_NODE, RendererHints.displayValue(ByteSizeStrings.metric()));
RendererHints.register(COUCH_DOCS_ACTUAL_DISK_SIZE_PER_NODE, RendererHints.displayValue(ByteSizeStrings.metric()));
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4f70aa11/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNode.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNode.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNode.java
index a27045f..dd46eba 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNode.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNode.java
@@ -122,6 +122,7 @@ public interface CouchbaseNode extends SoftwareProcess {
MethodEffector<Void> SERVER_ADD = new MethodEffector<Void>(CouchbaseNode.class, "serverAdd");
MethodEffector<Void> SERVER_ADD_AND_REBALANCE = new MethodEffector<Void>(CouchbaseNode.class, "serverAddAndRebalance");
MethodEffector<Void> REBALANCE = new MethodEffector<Void>(CouchbaseNode.class, "rebalance");
+ MethodEffector<Void> BUCKET_CREATE = new MethodEffector<Void>(CouchbaseNode.class, "bucketCreate");
@Effector(description = "add a server to a cluster")
public void serverAdd(@EffectorParam(name = "serverHostname") String serverToAdd, @EffectorParam(name = "username") String username, @EffectorParam(name = "password") String password);
@@ -131,5 +132,10 @@ public interface CouchbaseNode extends SoftwareProcess {
@Effector(description = "rebalance the couchbase cluster")
public void rebalance();
+
+ @Effector(description = "create a new bucket")
+ public void bucketCreate(@EffectorParam(name = "bucketName") String bucketName, @EffectorParam(name = "bucketType") String bucketType,
+ @EffectorParam(name = "bucketPort") Integer bucketPort, @EffectorParam(name = "bucketRamSize") Integer bucketRamSize,
+ @EffectorParam(name = "bucketReplica") Integer bucketReplica);
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4f70aa11/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeDriver.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeDriver.java
index 9fc5877..b77f244 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeDriver.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeDriver.java
@@ -26,6 +26,8 @@ public interface CouchbaseNodeDriver extends SoftwareProcessDriver {
public void serverAdd(String serverToAdd, String username, String password);
public void rebalance();
+
+ public void bucketCreate(String bucketName, String bucketType, Integer bucketPort, Integer bucketRamSize, Integer bucketReplica);
public void serverAddAndRebalance(String serverToAdd, String username, String password);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4f70aa11/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java
index e556c5d..11e36bc 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java
@@ -181,4 +181,8 @@ public class CouchbaseNodeImpl extends SoftwareProcessImpl implements CouchbaseN
}
}
+ @Override
+ public void bucketCreate(String bucketName, String bucketType, Integer bucketPort, Integer bucketRamSize, Integer bucketReplica) {
+ getDriver().bucketCreate(bucketName, bucketType, bucketPort, bucketRamSize, bucketReplica);
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4f70aa11/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
index d55f7df..e02ddc9 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
@@ -218,4 +218,16 @@ public class CouchbaseNodeSshDriver extends AbstractSoftwareProcessSshDriver imp
entity.setAttribute(CouchbaseNode.REBALANCE_STATUS, "Rebalance Started");
}
+ @Override
+ public void bucketCreate(String bucketName, String bucketType, Integer bucketPort, Integer bucketRamSize, Integer bucketReplica) {
+ newScript("bucketCreate").body.append(couchbaseCli("bucket-create")
+ + getCouchbaseHostnameAndCredentials() +
+ " --bucket=" + bucketName +
+ " --bucket-type=" + bucketType +
+ " --bucket-port=" + bucketPort +
+ " --bucket-ramsize=" + bucketRamSize +
+ " --bucket-replica=" + bucketReplica)
+ .failOnNonZeroResultCode()
+ .execute();
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4f70aa11/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGateway.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGateway.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGateway.java
new file mode 100644
index 0000000..ddea721
--- /dev/null
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGateway.java
@@ -0,0 +1,61 @@
+package brooklyn.entity.nosql.couchbase;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.proxying.ImplementedBy;
+import brooklyn.event.AttributeSensor;
+import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
+import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
+import brooklyn.event.basic.Sensors;
+import brooklyn.util.flags.SetFromFlag;
+
+@ImplementedBy(CouchbaseSyncGatewayImpl.class)
+public interface CouchbaseSyncGateway extends SoftwareProcess {
+
+ @SetFromFlag("version")
+ ConfigKey<String> SUGGESTED_VERSION = ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION,
+ "1.0-beta3.1");
+
+ @SetFromFlag("downloadUrl")
+ BasicAttributeSensorAndConfigKey<String> DOWNLOAD_URL = new BasicAttributeSensorAndConfigKey<String>(
+ SoftwareProcess.DOWNLOAD_URL, "http://packages.couchbase.com/releases/couchbase-sync-gateway/1.0-beta/couchbase-sync-gateway-community_${version}_${driver.osTag}");
+
+ @SetFromFlag("couchbaseServer")
+ ConfigKey<Entity> COUCHBASE_SERVER = ConfigKeys.newConfigKey(Entity.class, "couchbaseSyncGateway.couchbaseNode",
+ "Couchbase server node or cluster the sync gateway connects to");
+
+ @SetFromFlag("serverPool")
+ ConfigKey<String> COUCHBASE_SERVER_POOL = ConfigKeys.newStringConfigKey("couchbaseSyncGateway.serverPool",
+ "Couchbase Server pool name in which to find buckets", "default");
+
+ @SetFromFlag("couchbaseServerBucket")
+ ConfigKey<String> COUCHBASE_SERVER_BUCKET = ConfigKeys.newStringConfigKey("couchbaseSyncGateway.serverBucket",
+ "Name of the Couchbase bucket to use", "sync_gateway");
+
+ @SetFromFlag("couchbaseServerUrl")
+ ConfigKey<String> COUCHBASE_SERVER_URL = ConfigKeys.newStringConfigKey("couchbaseSyncGateway.couchbaseServerUrl",
+ "Couchbase Server Admin Url to connect the gateway to");
+
+ @SetFromFlag("pretty")
+ ConfigKey<Boolean> PRETTY = ConfigKeys.newBooleanConfigKey("couchbaseSyncGateway.pretty",
+ "Pretty-print JSON responses. This is useful for debugging, but reduces performance.", false);
+
+ @SetFromFlag("verbose")
+ ConfigKey<Boolean> VERBOSE = ConfigKeys.newBooleanConfigKey("couchbaseSyncGateway.verbose",
+ "Logs more information about requests.", false);
+
+ AttributeSensor<String> COUCHBASE_SERVER_WEB_URL = Sensors.newStringSensor("couchbaseSyncGateway.serverWebUrl",
+ "The Url and web port of the couchbase server to connect to");
+
+ AttributeSensor<String> MANAGEMENT_URL = Sensors.newStringSensor("coucbaseSyncGateway.managementUrl",
+ "Management URL for Couchbase Sycn Gateway");
+
+ PortAttributeSensorAndConfigKey SYNC_REST_API_PORT = new PortAttributeSensorAndConfigKey("couchbaseSyncGateway.syncRestPort",
+ "Port the Sync REST API listens on", "4984");
+
+ PortAttributeSensorAndConfigKey ADMIN_REST_API_PORT = new PortAttributeSensorAndConfigKey("couchbaseSyncGateway.adminRestPort",
+ "Port the Admin REST API listens on", "4985");
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4f70aa11/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayDriver.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayDriver.java
new file mode 100644
index 0000000..b1b4339
--- /dev/null
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayDriver.java
@@ -0,0 +1,9 @@
+package brooklyn.entity.nosql.couchbase;
+
+import brooklyn.entity.basic.SoftwareProcessDriver;
+
+public interface CouchbaseSyncGatewayDriver extends SoftwareProcessDriver {
+
+ public String getOsTag();
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4f70aa11/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayImpl.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayImpl.java
new file mode 100644
index 0000000..09ef569
--- /dev/null
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewayImpl.java
@@ -0,0 +1,61 @@
+package brooklyn.entity.nosql.couchbase;
+
+
+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 com.google.common.net.HostAndPort;
+
+public class CouchbaseSyncGatewayImpl extends SoftwareProcessImpl implements CouchbaseSyncGateway {
+
+ private HttpFeed httpFeed;
+
+ @Override
+ public Class<CouchbaseSyncGatewayDriver> getDriverInterface() {
+ return CouchbaseSyncGatewayDriver.class;
+ }
+
+ @Override
+ protected void connectSensors() {
+ super.connectSensors();
+ connectServiceUpIsRunning();
+ }
+
+ @Override
+ protected void connectServiceUpIsRunning() {
+
+
+ HostAndPort hp = BrooklynAccessUtils.getBrooklynAccessibleAddress(this,
+ getAttribute(CouchbaseSyncGateway.ADMIN_REST_API_PORT));
+
+ String managementUri = String.format("http://%s:%s",
+ hp.getHostText(), hp.getPort());
+
+ setAttribute(MANAGEMENT_URL, managementUri);
+
+ httpFeed = HttpFeed.builder()
+ .entity(this)
+ .period(200)
+ .baseUri(managementUri)
+ .poll(new HttpPollConfig<Boolean>(SERVICE_UP)
+ .onSuccess(HttpValueFunctions.responseCodeEquals(200)))
+ .build();
+
+ }
+
+ @Override
+ protected void disconnectSensors() {
+ super.disconnectSensors();
+ disconnectServiceUpIsRunning();
+ }
+
+ @Override
+ protected void disconnectServiceUpIsRunning() {
+ if (httpFeed != null) {
+ httpFeed.stop();
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4f70aa11/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java
new file mode 100644
index 0000000..c7c9129
--- /dev/null
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/couchbase/CouchbaseSyncGatewaySshDriver.java
@@ -0,0 +1,147 @@
+package brooklyn.entity.nosql.couchbase;
+
+import static brooklyn.util.ssh.BashCommands.INSTALL_CURL;
+import static brooklyn.util.ssh.BashCommands.alternatives;
+import static brooklyn.util.ssh.BashCommands.chainGroup;
+import static brooklyn.util.ssh.BashCommands.sudo;
+import static java.lang.String.format;
+
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.AbstractSoftwareProcessSshDriver;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityLocal;
+import brooklyn.entity.drivers.downloads.DownloadResolver;
+import brooklyn.location.OsDetails;
+import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.util.ssh.BashCommands;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+public class CouchbaseSyncGatewaySshDriver extends AbstractSoftwareProcessSshDriver implements CouchbaseSyncGatewayDriver {
+ public CouchbaseSyncGatewaySshDriver(EntityLocal entity, SshMachineLocation machine) {
+ super(entity, machine);
+ }
+
+ @Override
+ public boolean isRunning() {
+ return Boolean.TRUE.equals(entity.getAttribute(Attributes.SERVICE_UP));
+ }
+
+ @Override
+ public void stop() {
+
+ }
+
+ @Override
+ public void install() {
+ //reference http://docs.couchbase.com/sync-gateway/#getting-started-with-sync-gateway
+ DownloadResolver resolver = Entities.newDownloader(this);
+ List<String> urls = resolver.getTargets();
+ String saveAs = resolver.getFilename();
+
+ OsDetails osDetails = getMachine().getMachineDetails().getOsDetails();
+
+ log.info("Installing couchbase-sync-gateway version: {}", getVersion());
+ if (osDetails.isLinux()) {
+ List<String> commands = installLinux(urls, saveAs);
+ newScript(INSTALLING)
+ .body.append(commands).execute();
+ }
+ }
+
+ @Override
+ public void customize() {
+
+ }
+
+ @Override
+ public void launch() {
+ Entity cbNode = entity.getConfig(CouchbaseSyncGateway.COUCHBASE_SERVER);
+ Entities.waitForServiceUp(cbNode, Duration.ONE_HOUR);
+
+
+ if (cbNode instanceof CouchbaseCluster) {
+ Optional<Entity> cbClusterNode = Iterables.tryFind(cbNode.getAttribute(CouchbaseCluster.GROUP_MEMBERS), new Predicate<Entity>() {
+
+ @Override
+ public boolean apply(@Nullable Entity entity) {
+ if (entity instanceof CouchbaseNode && Boolean.TRUE.equals(entity.getAttribute(CouchbaseNode.IS_IN_CLUSTER))) {
+ return true;
+ }
+ return false;
+ }
+ });
+ if (cbClusterNode.isPresent()) {
+ cbNode = cbClusterNode.get();
+ } else {
+ throw new IllegalArgumentException(format("The cluster %s does not contain any suitable Couchbase nodes to connect to..", cbNode.getId()));
+ }
+
+ }
+ String hostname = cbNode.getAttribute(CouchbaseNode.HOSTNAME);
+ String webPort = cbNode.getAttribute(CouchbaseNode.COUCHBASE_WEB_ADMIN_PORT).toString();
+
+
+ String username = cbNode.getConfig(CouchbaseNode.COUCHBASE_ADMIN_USERNAME);
+ String password = cbNode.getConfig(CouchbaseNode.COUCHBASE_ADMIN_PASSWORD);
+
+ String bucketName = entity.getConfig(CouchbaseSyncGateway.COUCHBASE_SERVER_BUCKET);
+ String pool = entity.getConfig(CouchbaseSyncGateway.COUCHBASE_SERVER_POOL);
+ String pretty = entity.getConfig(CouchbaseSyncGateway.PRETTY) ? "-pretty" : "";
+ String verbose = entity.getConfig(CouchbaseSyncGateway.VERBOSE) ? "-verbose" : "";
+
+ String adminRestApiPort = entity.getConfig(CouchbaseSyncGateway.ADMIN_REST_API_PORT).iterator().next().toString();
+ String syncRestApiPort = entity.getConfig(CouchbaseSyncGateway.SYNC_REST_API_PORT).iterator().next().toString();
+
+ String serverWebAdminUrl = format("http://%s:%s@%s:%s", username, password, hostname, webPort);
+ String options = format("-url %s -bucket %s -adminInterface 0.0.0.0:%s -interface 0.0.0.0:%s -pool %s %s %s",
+ serverWebAdminUrl, bucketName, adminRestApiPort, syncRestApiPort, pool, pretty, verbose);
+
+ newScript(LAUNCHING)
+ .body.append(format("/opt/couchbase-sync-gateway/bin/sync_gateway %s &", options))
+ .execute();
+ }
+
+ private List<String> installLinux(List<String> urls, String saveAs) {
+
+ String apt = chainGroup(
+ "which apt-get",
+ sudo("apt-get update"),
+ sudo(format("dpkg -i %s", saveAs)));
+
+ String yum = chainGroup(
+ "which yum",
+ sudo(format("rpm --install %s", saveAs)));
+
+ return ImmutableList.<String>builder()
+ .add(INSTALL_CURL)
+ .addAll(BashCommands.commandsToDownloadUrlsAs(urls, saveAs))
+ .add(alternatives(apt, yum))
+ .build();
+ }
+
+ @Override
+ public String getOsTag() {
+ OsDetails os = getLocation().getOsDetails();
+ if (os == null) {
+ // Default to generic linux
+ return "x86_64.rpm";
+ } else {
+ //FIXME should be a better way to check for OS name and version
+ String osName = os.getName().toLowerCase();
+ String fileExtension = osName.contains("deb") || osName.contains("ubuntu") ? ".deb" : ".rpm";
+ String arch = os.is64bit() ? "x86_64" : "x86";
+ return arch + fileExtension;
+ }
+ }
+
+}
\ No newline at end of file