You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by sj...@apache.org on 2015/09/16 12:52:13 UTC

[1/9] incubator-brooklyn git commit: Adds mongoDB authentication

Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master 5bb7cc693 -> 841db6a25


Adds mongoDB authentication


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

Branch: refs/heads/master
Commit: 1d0e2548cc9b5a5ddf81138c4753c5e915644129
Parents: 07ec193
Author: Martin Harris <gi...@nakomis.com>
Authored: Fri Aug 14 14:13:55 2015 +0100
Committer: Martin Harris <gi...@nakomis.com>
Committed: Mon Sep 14 16:36:21 2015 +0100

----------------------------------------------------------------------
 .../hello-world-sql/src/main/webapp/mongo.jsp   | 12 ++-
 software/nosql/pom.xml                          |  1 +
 .../nosql/mongodb/AbstractMongoDBServer.java    |  3 +-
 .../nosql/mongodb/AbstractMongoDBSshDriver.java | 81 ++++++++++++++++----
 .../mongodb/MongoDBAuthenticationMixins.java    | 51 ++++++++++++
 .../mongodb/MongoDBAuthenticationUtils.java     | 79 +++++++++++++++++++
 .../nosql/mongodb/MongoDBClientSupport.java     | 26 +++++--
 .../entity/nosql/mongodb/MongoDBReplicaSet.java |  2 +-
 .../nosql/mongodb/MongoDBReplicaSetImpl.java    |  8 +-
 .../entity/nosql/mongodb/MongoDBServerImpl.java |  1 -
 .../sharding/CoLocatedMongoDBRouterImpl.java    | 44 ++++++++---
 .../sharding/MongoDBRouterSshDriver.java        |  4 +
 .../sharding/MongoDBShardedDeploymentImpl.java  | 40 +++++++---
 .../nosql/src/test/resources/mongodb-keyfile    | 16 ++++
 .../resources/mongo-sharded-authentication.yaml | 45 +++++++++++
 .../src/test/resources/mongo-sharded.yaml       |  6 +-
 usage/launcher/src/test/resources/mongo.key     | 16 ++++
 .../apache/brooklyn/util/ssh/BashCommands.java  |  7 ++
 18 files changed, 392 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/examples/webapps/hello-world-sql/src/main/webapp/mongo.jsp
----------------------------------------------------------------------
diff --git a/examples/webapps/hello-world-sql/src/main/webapp/mongo.jsp b/examples/webapps/hello-world-sql/src/main/webapp/mongo.jsp
index 50a9a68..7e110cc 100644
--- a/examples/webapps/hello-world-sql/src/main/webapp/mongo.jsp
+++ b/examples/webapps/hello-world-sql/src/main/webapp/mongo.jsp
@@ -1,4 +1,5 @@
 <%@ page language="java" import="java.sql.*,com.mongodb.*"%>
+<%@ page import="java.util.Arrays" %>
 
 <html>
 <!--
@@ -39,6 +40,9 @@
 
 <%
 String port=System.getProperty("brooklyn.example.mongodb.port");
+String username=System.getProperty("brooklyn.example.mongodb.username");
+String password=System.getProperty("brooklyn.example.mongodb.password");
+String authenticationDatabase=System.getProperty("brooklyn.example.mongodb.authenticationDatabase");
 //URL should be supplied e.g. ""-Dbrooklyn.example.db.url=jdbc:mysql://localhost/visitors?user=brooklyn&password=br00k11n"
 //(note quoting needed due to ampersand)
 if (port==null) {
@@ -51,7 +55,13 @@ if (port==null) {
 
 <%
 /* begin database-enabled block */ }
-MongoClient client = new MongoClient("localhost", new Integer(port));
+MongoCredential credential = MongoCredential.createMongoCRCredential(username, authenticationDatabase, password.toCharArray());
+ServerAddress address = new ServerAddress("localhost", new Integer(port));
+MongoClientOptions connectionOptions = MongoClientOptions.builder()
+    .autoConnectRetry(true)
+    .socketKeepAlive(true)
+    .build();
+MongoClient client = new MongoClient(address, Arrays.asList(credential),connectionOptions);
 DB database = client.getDB("visitors");
 DBCollection messages =  database.getCollection("messages");
 int i=0;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/software/nosql/pom.xml
----------------------------------------------------------------------
diff --git a/software/nosql/pom.xml b/software/nosql/pom.xml
index b0d5b6c..be0887d 100644
--- a/software/nosql/pom.xml
+++ b/software/nosql/pom.xml
@@ -265,6 +265,7 @@
                 <exclude>src/test/resources/test-mongodb.conf</exclude>
                 <exclude>src/test/resources/test-mongodb-configserver.conf</exclude>
                 <exclude>src/test/resources/test-mongodb-router.conf</exclude>
+                <exclude>src/test/resources/mongodb-keyfile</exclude>
                 <exclude>src/main/resources/org/apache/brooklyn/entity/nosql/redis/redis.conf</exclude>
                 <exclude>src/main/resources/org/apache/brooklyn/entity/nosql/redis/slave.conf</exclude>
                 <exclude>src/main/resources/org/apache/brooklyn/entity/nosql/riak/app.config</exclude>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBServer.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBServer.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBServer.java
index 52e24d8..5947a43 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBServer.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBServer.java
@@ -27,7 +27,7 @@ import org.apache.brooklyn.core.sensor.PortAttributeSensorAndConfigKey;
 import org.apache.brooklyn.entity.software.base.SoftwareProcess;
 import org.apache.brooklyn.util.core.flags.SetFromFlag;
 
-public interface AbstractMongoDBServer extends SoftwareProcess, Entity {
+public interface AbstractMongoDBServer extends SoftwareProcess, Entity, MongoDBAuthenticationMixins {
 
     // TODO Need to properly test v2.4.x and v2.5.x support.
     // I think the v2.5.x were dev releases.
@@ -58,4 +58,5 @@ public interface AbstractMongoDBServer extends SoftwareProcess, Entity {
     @SetFromFlag("port")
     PortAttributeSensorAndConfigKey PORT =
             new PortAttributeSensorAndConfigKey("mongodb.server.port", "Server port", "27017+");
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBSshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBSshDriver.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBSshDriver.java
index c6974d4..9fe949d 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBSshDriver.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBSshDriver.java
@@ -27,6 +27,8 @@ import org.apache.brooklyn.api.location.OsDetails;
 import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.entity.software.base.AbstractSoftwareProcessSshDriver;
 import org.apache.brooklyn.entity.software.base.lifecycle.ScriptHelper;
+import org.apache.brooklyn.util.time.Duration;
+import org.apache.brooklyn.util.time.Time;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.brooklyn.location.ssh.SshMachineLocation;
@@ -63,7 +65,7 @@ public abstract class AbstractMongoDBSshDriver extends AbstractSoftwareProcessSs
         commands.addAll(BashCommands.commandsToDownloadUrlsAs(urls, saveAs));
         commands.add(BashCommands.INSTALL_TAR);
         commands.add("tar xzfv " + saveAs);
-    
+
         newScript(INSTALLING)
                 .failOnNonZeroResultCode()
                 .body.append(commands).execute();
@@ -73,14 +75,40 @@ public abstract class AbstractMongoDBSshDriver extends AbstractSoftwareProcessSs
     public void customize() {
         Map<?,?> ports = ImmutableMap.of("port", getServerPort());
         Networking.checkPortsValid(ports);
-        String command = String.format("mkdir -p %s", getDataDirectory());
+        List<String> commands = new LinkedList<String>();
+        commands.add(String.format("mkdir -p %s", getDataDirectory()));
+
+        if (MongoDBAuthenticationUtils.usesAuthentication(entity)) {
+            String destinationLocation = Os.mergePaths(getRunDir(), "mongodb-keyfile");
+            entity.sensors().set(AbstractMongoDBServer.MONGODB_KEYFILE_DESTINATION, destinationLocation);
+            String keyfileContents = entity.config().get(AbstractMongoDBServer.MONGODB_KEYFILE_CONTENTS);
+            if (keyfileContents == null) {
+                String keyfileUrl = entity.config().get(AbstractMongoDBServer.MONGODB_KEYFILE_URL);
+                copyResource(keyfileUrl, destinationLocation);
+            } else {
+                commands.add(BashCommands.pipeTextToFile(keyfileContents, destinationLocation));
+                commands.add("chmod 600 " + destinationLocation);
+            }
+        }
+
         newScript(CUSTOMIZING)
                 .updateTaskAndFailOnNonZeroResultCode()
-                .body.append(command).execute();
+                .body.append(commands).execute();
         String templateUrl = entity.getConfig(MongoDBServer.MONGODB_CONF_TEMPLATE_URL);
         if (!Strings.isNullOrEmpty(templateUrl)) copyTemplate(templateUrl, getConfFile());
+        if (MongoDBAuthenticationUtils.usesAuthentication(entity)) {
+            launch(getArgsBuilderWithNoAuthentication((AbstractMongoDBServer) getEntity())
+                    .add("--dbpath", getDataDirectory()));
+            newScript("create-user")
+                    .body.append(String.format("%s --port %s" +
+                            " --host localhost admin --eval \"db.createUser({user: '%s',pwd: '%s',roles: [ 'root' ]})\"",
+                    Os.mergePaths(getExpandedInstallDir(), "bin/mongo"), getServerPort(), getRootUsername(), MongoDBAuthenticationUtils.getRootPassword(entity)))
+                    .updateTaskAndFailOnNonZeroResultCode()
+                    .execute();
+            stop();
+        }
     }
-    
+
     @Override
     public boolean isRunning() {
         try {
@@ -102,7 +130,14 @@ public abstract class AbstractMongoDBSshDriver extends AbstractSoftwareProcessSs
         
         // We could also use SIGTERM (15)
         new ScriptHelper(this, "Send SIGINT to MongoDB server")
-                .body.append("kill -2 $(cat " + getPidFile() + ")")
+                .body.append("MONGO_PID=$(cat " + getPidFile() + ")\n")
+                .body.append("kill -2 $MONGO_PID\n")
+                .body.append("for i in {1..10}\n" +
+                    "do\n" +
+                    "    kill -0 $MONGO_PID || exit \n" +
+                    "    sleep 1\n" +
+                    "done\n" +
+                    "echo \"mongoDB process still running after 10 seconds; continuing but may subsequently fail\"")
                 .execute();
     }
 
@@ -151,24 +186,38 @@ public abstract class AbstractMongoDBSshDriver extends AbstractSoftwareProcessSs
         return getRunDir() + "/mongo.conf";
     }
 
+    protected String getRootUsername() {
+        return entity.config().get(AbstractMongoDBServer.ROOT_USERNAME);
+    }
+
     protected ImmutableList.Builder<String> getArgsBuilderWithDefaults(AbstractMongoDBServer server) {
-        Integer port = server.getAttribute(MongoDBServer.PORT);
+        ImmutableList.Builder<String> builder = getArgsBuilderWithNoAuthentication(server);
+        String keyfileContents = entity.config().get(AbstractMongoDBServer.MONGODB_KEYFILE_CONTENTS);
+        if (keyfileContents != null) {
+            builder.add("--keyFile", entity.getAttribute(AbstractMongoDBServer.MONGODB_KEYFILE_DESTINATION));
+        }
+        return builder;
+    }
 
-        return ImmutableList.<String>builder()
-                .add("--config", getConfFile())
-                .add("--pidfilepath", getPidFile())
-                .add("--logpath", getLogFile())
-                .add("--port", port.toString())
-                .add("--fork");
+    protected ImmutableList.Builder<String> getArgsBuilderWithNoAuthentication(AbstractMongoDBServer server) {
+        Integer port = server.getAttribute(MongoDBServer.PORT);
+        ImmutableList.Builder<String> builder = ImmutableList.builder();
+        builder.add("--config", getConfFile());
+        builder.add("--pidfilepath", getPidFile());
+        builder.add("--logpath", getLogFile());
+        builder.add("--port", port.toString());
+        builder.add("--fork");
+        return builder;
     }
     
     protected void launch(ImmutableList.Builder<String> argsBuilder) {
         String args = Joiner.on(" ").join(argsBuilder.build());
-        String command = String.format("%s/bin/mongod %s > out.log 2> err.log < /dev/null", getExpandedInstallDir(), args);
-        LOG.info(command);
+        List<String> commands = new LinkedList<String>();
+        commands.add(String.format("%s/bin/mongod %s > out.log 2> err.log < /dev/null", getExpandedInstallDir(), args));
+
         newScript(LAUNCHING)
                 .updateTaskAndFailOnNonZeroResultCode()
-                .body.append(command).execute();
+                .body.append(commands).execute();
     }
- 
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationMixins.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationMixins.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationMixins.java
new file mode 100644
index 0000000..a47c384
--- /dev/null
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationMixins.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.nosql.mongodb;
+
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.sensor.BasicAttributeSensorAndConfigKey;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.util.core.flags.SetFromFlag;
+
+public interface MongoDBAuthenticationMixins {
+    @SetFromFlag("mongodbKeyfileContents")
+    ConfigKey<String> MONGODB_KEYFILE_CONTENTS = ConfigKeys.newStringConfigKey(
+            "mongodb.keyfile.contents", "Contents of the keyfile used for authentication");
+
+    @SetFromFlag("mongodbKeyfileUrl")
+    ConfigKey<String> MONGODB_KEYFILE_URL = ConfigKeys.newStringConfigKey(
+            "mongodb.keyfile.url", "Location of the keyfile used for authentication");
+
+    @SetFromFlag("rootUsername")
+    BasicAttributeSensorAndConfigKey<String> ROOT_USERNAME =
+            new BasicAttributeSensorAndConfigKey<>(String.class, "mongodb.root.username", "Username of the initial admin user", "superuser");
+
+    @SetFromFlag("rootPassword")
+    BasicAttributeSensorAndConfigKey<String> ROOT_PASSWORD =
+            new BasicAttributeSensorAndConfigKey<>(String.class, "mongodb.root.password", "Password for the initial admin user, auto-generated if not set");
+
+    @SetFromFlag("authenticationDatabase")
+    BasicAttributeSensorAndConfigKey<String> AUTHENTICATION_DATABASE =
+            new BasicAttributeSensorAndConfigKey<>(String.class, "mongodb.authentication.database", "Database to be used to store authentication details (if used)", "admin");
+
+    AttributeSensor<String> MONGODB_KEYFILE_DESTINATION = Sensors.newStringSensor("mongodb.keyfile.destination",
+            "Destination of the keyfile used for authentication on the target server");
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationUtils.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationUtils.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationUtils.java
new file mode 100644
index 0000000..0c337a0
--- /dev/null
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationUtils.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.nosql.mongodb;
+
+import org.apache.brooklyn.util.text.Strings;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.brooklyn.api.entity.Entity;
+
+
+public class MongoDBAuthenticationUtils {
+
+    private static final Logger LOG = LoggerFactory.getLogger(MongoDBAuthenticationUtils.class);
+
+    private MongoDBAuthenticationUtils(){}
+
+    /**
+     * @return true if either the keyfile contents or keyfile url is set, false otherwise. If both are set, an IllegalStateException is thrown
+     */
+    public static boolean usesAuthentication(Entity entity) {
+        String keyfileContents = entity.config().get(MongoDBAuthenticationMixins.MONGODB_KEYFILE_CONTENTS);
+        String keyfileUrl = entity.config().get(MongoDBAuthenticationMixins.MONGODB_KEYFILE_URL);
+        if (!(Strings.isEmpty(keyfileContents) || Strings.isEmpty(keyfileUrl))) {
+            throw new IllegalStateException("keyfile contents and keyfile location cannot both be set");
+        }
+        if (Strings.isEmpty(keyfileContents) && Strings.isEmpty(keyfileUrl)) {
+            return false;
+        }
+        return true;
+    }
+
+    public static String getRootPassword(Entity entity) {
+        String password = entity.config().get(MongoDBAuthenticationMixins.ROOT_PASSWORD);
+        if (Strings.isEmpty(password)) {
+            LOG.debug(entity + " has no password specified for " + MongoDBAuthenticationMixins.ROOT_PASSWORD.getName() + "; using a random string");
+            password = Strings.makeRandomId(8);
+            entity.sensors().set(MongoDBAuthenticationMixins.ROOT_PASSWORD, password);
+            entity.config().set(MongoDBAuthenticationMixins.ROOT_PASSWORD, password);
+        }
+        return password;
+    }
+
+    public static void setAuthenticationConfig(EntitySpec<?> spec, Entity source) {
+        if (MongoDBAuthenticationUtils.usesAuthentication(source)) {
+            spec.configure(MongoDBAuthenticationMixins.MONGODB_KEYFILE_CONTENTS, source.config().get(MongoDBAuthenticationMixins.MONGODB_KEYFILE_CONTENTS));
+            spec.configure(MongoDBAuthenticationMixins.MONGODB_KEYFILE_URL, source.config().get(MongoDBAuthenticationMixins.MONGODB_KEYFILE_URL));
+            spec.configure(MongoDBAuthenticationMixins.ROOT_USERNAME, source.config().get(MongoDBAuthenticationMixins.ROOT_USERNAME));
+            spec.configure(MongoDBAuthenticationMixins.ROOT_PASSWORD, getRootPassword(source));
+        }
+    }
+
+    public static void setAuthenticationConfig(Entity entity, Entity source) {
+        if (MongoDBAuthenticationUtils.usesAuthentication(source)) {
+            entity.config().set(MongoDBAuthenticationMixins.MONGODB_KEYFILE_CONTENTS, source.config().get(MongoDBAuthenticationMixins.MONGODB_KEYFILE_CONTENTS));
+            entity.config().set(MongoDBAuthenticationMixins.MONGODB_KEYFILE_URL, source.config().get(MongoDBAuthenticationMixins.MONGODB_KEYFILE_URL));
+            entity.config().set(MongoDBAuthenticationMixins.ROOT_USERNAME, source.config().get(MongoDBAuthenticationMixins.ROOT_USERNAME));
+            entity.config().set(MongoDBAuthenticationMixins.ROOT_PASSWORD, getRootPassword(source));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClientSupport.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClientSupport.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClientSupport.java
index 3a6c398..fa2022f 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClientSupport.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClientSupport.java
@@ -27,6 +27,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
 import com.google.common.net.HostAndPort;
 import com.mongodb.BasicDBObject;
 import com.mongodb.CommandResult;
@@ -34,6 +35,7 @@ import com.mongodb.DB;
 import com.mongodb.DBObject;
 import com.mongodb.MongoClient;
 import com.mongodb.MongoClientOptions;
+import com.mongodb.MongoCredential;
 import com.mongodb.MongoException;
 import com.mongodb.ServerAddress;
 
@@ -45,11 +47,20 @@ import com.mongodb.ServerAddress;
 public class MongoDBClientSupport {
 
     private static final Logger LOG = LoggerFactory.getLogger(MongoDBClientSupport.class);
-
     private ServerAddress address;
-    
+
+    private boolean usesAuthentication;
+    private String username;
+    private String password;
+    private String authenticationDatabase;
+
     private MongoClient client() {
-        return new MongoClient(address, connectionOptions);
+        if (usesAuthentication) {
+            MongoCredential credential = MongoCredential.createMongoCRCredential(username, authenticationDatabase, password.toCharArray());
+            return new MongoClient(address, ImmutableList.of(credential), connectionOptions);
+        } else {
+            return new MongoClient(address, connectionOptions);
+        }
     }
 
     // Set client to automatically reconnect to servers.
@@ -60,9 +71,13 @@ public class MongoDBClientSupport {
 
     private static final BasicBSONObject EMPTY_RESPONSE = new BasicBSONObject();
 
-    public MongoDBClientSupport(ServerAddress standalone) {
+    public MongoDBClientSupport(ServerAddress standalone, boolean usesAuthentication, String username, String password, String authenticationDatabase) {
         // We could also use a MongoClient to access an entire replica set. See MongoClient(List<ServerAddress>).
         address = standalone;
+        this.usesAuthentication = usesAuthentication;
+        this.username = username;
+        this.password = password;
+        this.authenticationDatabase = authenticationDatabase;
     }
 
     /**
@@ -71,7 +86,8 @@ public class MongoDBClientSupport {
     public static MongoDBClientSupport forServer(AbstractMongoDBServer standalone) throws UnknownHostException {
         HostAndPort hostAndPort = BrooklynAccessUtils.getBrooklynAccessibleAddress(standalone, standalone.getAttribute(MongoDBServer.PORT));
         ServerAddress address = new ServerAddress(hostAndPort.getHostText(), hostAndPort.getPort());
-        return new MongoDBClientSupport(address);
+        return new MongoDBClientSupport(address, MongoDBAuthenticationUtils.usesAuthentication(standalone), standalone.sensors().get(MongoDBAuthenticationMixins.ROOT_USERNAME),
+                standalone.sensors().get(MongoDBAuthenticationMixins.ROOT_PASSWORD), standalone.sensors().get(MongoDBAuthenticationMixins.AUTHENTICATION_DATABASE));
     }
 
     private ServerAddress getServerAddress() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSet.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSet.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSet.java
index 14d0eb8..12bbe87 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSet.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSet.java
@@ -46,7 +46,7 @@ import com.google.common.reflect.TypeToken;
  * @see <a href="http://docs.mongodb.org/manual/replication/">http://docs.mongodb.org/manual/replication/</a>
  */
 @ImplementedBy(MongoDBReplicaSetImpl.class)
-public interface MongoDBReplicaSet extends DynamicCluster {
+public interface MongoDBReplicaSet extends DynamicCluster, MongoDBAuthenticationMixins {
 
     @SetFromFlag("replicaSetName")
     ConfigKey<String> REPLICA_SET_NAME = ConfigKeys.newStringConfigKey(

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
index 399ea91..a9db033 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
@@ -141,7 +141,12 @@ public class MongoDBReplicaSetImpl extends DynamicClusterImpl implements MongoDB
 
     @Override
     protected EntitySpec<?> getMemberSpec() {
-        return getConfig(MEMBER_SPEC, EntitySpec.create(MongoDBServer.class));
+        EntitySpec<?> spec = config().get(MEMBER_SPEC);
+        if (spec == null) {
+            spec = EntitySpec.create(MongoDBServer.class);
+        }
+        MongoDBAuthenticationUtils.setAuthenticationConfig(spec, this);
+        return spec;
     }
 
     /**
@@ -200,6 +205,7 @@ public class MongoDBReplicaSetImpl extends DynamicClusterImpl implements MongoDB
                 setAttribute(PRIMARY_ENTITY, server);
                 setAttribute(Startable.SERVICE_UP, true);
             } else {
+                ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator(this, "initialization", "replicaset failed to initialize");
                 ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE);
             }
         } else {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBServerImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBServerImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBServerImpl.java
index ea9c406..941dd8e 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBServerImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBServerImpl.java
@@ -210,5 +210,4 @@ public class MongoDBServerImpl extends SoftwareProcessImpl implements MongoDBSer
                 .add("port", getAttribute(PORT))
                 .toString();
     }
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/CoLocatedMongoDBRouterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/CoLocatedMongoDBRouterImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/CoLocatedMongoDBRouterImpl.java
index 7817dbc..0c81de2 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/CoLocatedMongoDBRouterImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/CoLocatedMongoDBRouterImpl.java
@@ -19,32 +19,47 @@
 package org.apache.brooklyn.entity.nosql.mongodb.sharding;
 
 import java.util.Collection;
+import java.util.concurrent.ExecutionException;
 
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.entity.trait.Startable;
 import org.apache.brooklyn.core.sensor.DependentConfiguration;
 import org.apache.brooklyn.enricher.stock.Enrichers;
+import org.apache.brooklyn.entity.group.AbstractGroup;
+import org.apache.brooklyn.entity.nosql.mongodb.MongoDBAuthenticationMixins;
+import org.apache.brooklyn.entity.nosql.mongodb.MongoDBAuthenticationUtils;
 import org.apache.brooklyn.entity.software.base.SameServerEntityImpl;
+import org.apache.brooklyn.util.exceptions.Exceptions;
 
 import com.google.common.base.Predicates;
 import com.google.common.collect.Iterables;
 
-public class CoLocatedMongoDBRouterImpl extends SameServerEntityImpl implements CoLocatedMongoDBRouter {
+public class CoLocatedMongoDBRouterImpl extends SameServerEntityImpl implements CoLocatedMongoDBRouter, MongoDBAuthenticationMixins {
+
+    private MongoDBRouter router;
+
     @Override
     public void init() {
         super.init();
-        
+        router = addChild(EntitySpec.create(MongoDBRouter.class)
+                .configure(MongoDBRouter.CONFIG_SERVERS,
+                        DependentConfiguration.attributeWhenReady(
+                                getConfig(CoLocatedMongoDBRouter.SHARDED_DEPLOYMENT),
+                                MongoDBConfigServerCluster.CONFIG_SERVER_ADDRESSES)));
         for (EntitySpec<?> siblingSpec : getConfig(CoLocatedMongoDBRouter.SIBLING_SPECS)) {
             addChild(siblingSpec);
         }
+        sensors().set(ROUTER, (MongoDBRouter) Iterables.tryFind(getChildren(), Predicates.instanceOf(MongoDBRouter.class)).get());
     }
 
     @Override
     protected void doStart(Collection<? extends Location> locations) {
+
         // TODO Changed to create the router child after init as a workaround.
-        // When we use `mongo-sharded.yaml`, and we call 
+        // When we use `mongo-sharded.yaml`, and we call
         // `getConfig(CoLocatedMongoDBRouter.SHARDED_DEPLOYMENT)`,
         // the value is `$brooklyn:component("shardeddeployment")`.
         // To look up the component, it tries to do `entity().getApplication()` to
@@ -54,17 +69,24 @@ public class CoLocatedMongoDBRouterImpl extends SameServerEntityImpl implements
         //
         // We should move this code back to `init()` once we have a solution for that.
         // We can also remove the call to Entities.manage() once this is in init() again.
-        
-        MongoDBRouter router = addChild(EntitySpec.create(MongoDBRouter.class)
-                .configure(MongoDBRouter.CONFIG_SERVERS,
-                        DependentConfiguration.attributeWhenReady(
-                                getConfig(CoLocatedMongoDBRouter.SHARDED_DEPLOYMENT), 
-                                MongoDBConfigServerCluster.CONFIG_SERVER_ADDRESSES)));
+
+        try {
+            // Do not attempt to read the configuration until after the router has been added to the cluster
+            // as it is at this point that the authentication configuration is set
+            Task<?> clusterTask = DependentConfiguration.attributeWhenReady(router, AbstractGroup.FIRST);
+            Entities.submit(this, clusterTask);
+            clusterTask.get();
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+        }
+        MongoDBAuthenticationUtils.setAuthenticationConfig(router, this);
+        router.sensors().set(MongoDBAuthenticationMixins.ROOT_PASSWORD, router.config().get(MongoDBAuthenticationMixins.ROOT_PASSWORD));
+        router.sensors().set(MongoDBAuthenticationMixins.ROOT_USERNAME, router.config().get(MongoDBAuthenticationMixins.ROOT_USERNAME));
+        router.sensors().set(MongoDBAuthenticationMixins.AUTHENTICATION_DATABASE, router.config().get(MongoDBAuthenticationMixins.AUTHENTICATION_DATABASE));
         Entities.manage(router);
-        setAttribute(ROUTER, (MongoDBRouter) Iterables.tryFind(getChildren(), Predicates.instanceOf(MongoDBRouter.class)).get());
         addEnricher(Enrichers.builder().propagating(MongoDBRouter.PORT).from(router).build());
         
         super.doStart(locations);
-        setAttribute(Startable.SERVICE_UP, true);
+        sensors().set(Startable.SERVICE_UP, true);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBRouterSshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBRouterSshDriver.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBRouterSshDriver.java
index 816906d..df73868 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBRouterSshDriver.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBRouterSshDriver.java
@@ -48,4 +48,8 @@ public class MongoDBRouterSshDriver extends AbstractMongoDBSshDriver implements
                 .body.append(command).execute();
     }
 
+    @Override
+    public boolean isRunning() {
+        return super.isRunning();
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
index 9ef50b9..0b8a1b6 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
@@ -25,7 +25,6 @@ import java.util.List;
 
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.api.entity.Group;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.policy.PolicySpec;
 import org.apache.brooklyn.core.entity.AbstractEntity;
@@ -42,10 +41,12 @@ import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.apache.brooklyn.entity.nosql.mongodb.MongoDBAuthenticationMixins;
+import org.apache.brooklyn.entity.nosql.mongodb.MongoDBAuthenticationUtils;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
-public class MongoDBShardedDeploymentImpl extends AbstractEntity implements MongoDBShardedDeployment {
+public class MongoDBShardedDeploymentImpl extends AbstractEntity implements MongoDBShardedDeployment, MongoDBAuthenticationMixins {
     
     @SuppressWarnings("unused")
     private static final Logger LOG = LoggerFactory.getLogger(MongoDBShardedDeploymentImpl.class);
@@ -53,22 +54,36 @@ public class MongoDBShardedDeploymentImpl extends AbstractEntity implements Mong
     @Override
     public void init() {
         super.init();
-        
-        setAttribute(CONFIG_SERVER_CLUSTER, addChild(EntitySpec.create(MongoDBConfigServerCluster.class)
+
+        EntitySpec<MongoDBConfigServerCluster> configServerClusterSpec = EntitySpec.create(MongoDBConfigServerCluster.class)
                 .configure(MongoDBConfigServerCluster.MEMBER_SPEC, getConfig(MONGODB_CONFIG_SERVER_SPEC))
-                .configure(DynamicCluster.INITIAL_SIZE, getConfig(CONFIG_CLUSTER_SIZE))));
-        setAttribute(ROUTER_CLUSTER, addChild(EntitySpec.create(MongoDBRouterCluster.class)
+                .configure(DynamicCluster.INITIAL_SIZE, getConfig(CONFIG_CLUSTER_SIZE));
+        MongoDBAuthenticationUtils.setAuthenticationConfig(configServerClusterSpec, this);
+        sensors().set(CONFIG_SERVER_CLUSTER, addChild(configServerClusterSpec));
+
+        EntitySpec<MongoDBRouterCluster> routerClusterSpec = EntitySpec.create(MongoDBRouterCluster.class)
                 .configure(MongoDBRouterCluster.MEMBER_SPEC, getConfig(MONGODB_ROUTER_SPEC))
                 .configure(DynamicCluster.INITIAL_SIZE, getConfig(INITIAL_ROUTER_CLUSTER_SIZE))
-                .configure(MongoDBRouter.CONFIG_SERVERS, attributeWhenReady(getAttribute(CONFIG_SERVER_CLUSTER), MongoDBConfigServerCluster.CONFIG_SERVER_ADDRESSES))));
-        setAttribute(SHARD_CLUSTER, addChild(EntitySpec.create(MongoDBShardCluster.class)
+                .configure(MongoDBRouter.CONFIG_SERVERS, attributeWhenReady(getAttribute(CONFIG_SERVER_CLUSTER), MongoDBConfigServerCluster.CONFIG_SERVER_ADDRESSES));
+        MongoDBAuthenticationUtils.setAuthenticationConfig(routerClusterSpec, this);
+        sensors().set(ROUTER_CLUSTER, addChild(routerClusterSpec));
+
+        EntitySpec<MongoDBShardCluster> shardClusterSpec = EntitySpec.create(MongoDBShardCluster.class)
                 .configure(MongoDBShardCluster.MEMBER_SPEC, getConfig(MONGODB_REPLICA_SET_SPEC))
-                .configure(DynamicCluster.INITIAL_SIZE, getConfig(INITIAL_SHARD_CLUSTER_SIZE))));
+                .configure(DynamicCluster.INITIAL_SIZE, getConfig(INITIAL_SHARD_CLUSTER_SIZE));
+        MongoDBAuthenticationUtils.setAuthenticationConfig(shardClusterSpec, this);
+        sensors().set(SHARD_CLUSTER, addChild(shardClusterSpec));
+
         addEnricher(Enrichers.builder()
                 .propagating(MongoDBConfigServerCluster.CONFIG_SERVER_ADDRESSES)
                 .from(getAttribute(CONFIG_SERVER_CLUSTER))
                 .build());
-        
+
+        // Advertise even if default are used (root password is set in MongoDBAuthenticationUtils)
+        sensors().set(MongoDBAuthenticationMixins.AUTHENTICATION_DATABASE, config().get(MongoDBAuthenticationMixins.AUTHENTICATION_DATABASE));
+        sensors().set(MongoDBAuthenticationMixins.ROOT_USERNAME, config().get(MongoDBAuthenticationMixins.ROOT_USERNAME));
+        sensors().set(MongoDBAuthenticationMixins.MONGODB_KEYFILE_DESTINATION, config().get(MongoDBAuthenticationMixins.MONGODB_KEYFILE_CONTENTS));
+
         ServiceNotUpLogic.updateNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL, "stopped");
     }
 
@@ -85,7 +100,7 @@ public class MongoDBShardedDeploymentImpl extends AbstractEntity implements Mong
             if (getConfigRaw(MongoDBShardedDeployment.CO_LOCATED_ROUTER_GROUP, true).isPresent()) {
                 addPolicy(PolicySpec.create(ColocatedRouterTrackingPolicy.class)
                         .displayName("Co-located router tracker")
-                        .configure("group", (Group)getConfig(MongoDBShardedDeployment.CO_LOCATED_ROUTER_GROUP)));
+                        .configure("group", getConfig(MongoDBShardedDeployment.CO_LOCATED_ROUTER_GROUP)));
             }
             ServiceNotUpLogic.clearNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL);
             ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING);
@@ -99,6 +114,7 @@ public class MongoDBShardedDeploymentImpl extends AbstractEntity implements Mong
     public static class ColocatedRouterTrackingPolicy extends AbstractMembershipTrackingPolicy {
         @Override
         protected void onEntityAdded(Entity member) {
+            MongoDBAuthenticationUtils.setAuthenticationConfig(member, entity);
             MongoDBRouterCluster cluster = entity.getAttribute(ROUTER_CLUSTER);
             cluster.addMember(member.getAttribute(CoLocatedMongoDBRouter.ROUTER));
         }
@@ -107,7 +123,7 @@ public class MongoDBShardedDeploymentImpl extends AbstractEntity implements Mong
             MongoDBRouterCluster cluster = entity.getAttribute(ROUTER_CLUSTER);
             cluster.removeMember(member.getAttribute(CoLocatedMongoDBRouter.ROUTER));
         }
-    };
+    }
 
     @Override
     public void stop() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/software/nosql/src/test/resources/mongodb-keyfile
----------------------------------------------------------------------
diff --git a/software/nosql/src/test/resources/mongodb-keyfile b/software/nosql/src/test/resources/mongodb-keyfile
new file mode 100644
index 0000000..6d4640a
--- /dev/null
+++ b/software/nosql/src/test/resources/mongodb-keyfile
@@ -0,0 +1,16 @@
+df1DzycxICi2RFa1xsDP5uiVcVtZ4EQBxffQ+FDuD4n81iOGW7pNOS49aH4t9PW6
+s0t+mASRnY/IVOsiTNT5VQWeMhf6b0/aYuXJp9ZZNQ9PmyA60a8x5x9K3YIoGYAd
+/RGenkIOIG9EjXnqTT1QgN66xVIUp8v2w0iuER0jiG+GcjBVVWGgqKcj6ZLQRecC
+6xSETYuJRbXdPanpnlk8oRYrtWFgcmQ8pl0/0hc/8i82PjTC8DdkqRqYQzhAvexh
+Fo8ZOPiS8xmiDWDsKBJscf6J5KKlgr/3ws0Kv5Qqxmq7oelAmZ+xRvyFBYbao3cz
+3XKBC9SBYfexnl25S9Ef94IV6bqls6SwQMTNS5W0sn3L/Mi55yEWFN44pcYCJ4ng
+oHMDaQyOC+Fi0rRcRduFZWYHlw7ibX0AaRQhwhh0YEbgFY2O7QoTNxwNycxLeKLr
+VMY8ZcTRzvmypAfetWHlwx97G+yXebCsZZ+TbAR/txficwmLFw/M5Qit8Op7YVFM
+zsrKnJZq/Ar8kLzw2UrIFfecaRl3hqT4CI8htaVW+fbc94RHNiZpHg5k/I+aNT45
+9uxRNNPcZiDln7ZV3skhVwQ0UeUZUBp0UZj33N2f/5JXxoRc5slb2mMFEKe+FH6a
+0M86QphH356jrIBSalm7duLAFzB8oyf7+JQgbpwooiO5D+KqIJevpwZXtjuaKVCU
+4bOJNq8AaJU6yjPNihHiGuGLv3/TmXP1Q8Cr4XSyzpv9pxZvvb0XYdlxWIQg0szv
+5QSTkgx6CCBoeDbVoWJh4bE3lobFponKC9o5j3nVAqPbxZocq6Lr6TWrXfwlNRcg
+Cvenxs8mjRQV7Hg7956P/dJtavN3UpSTwbius5h/oIf9ywBmVLNAIhbOS3kcacOC
+YlnJZGN+m1Wo9AvsmLz+yl5GB3W/zA4vUyhWnUY24BoKKEFYef594wi2sagz9TVC
+nLrWCE8djB9j4tudcz6PdFFhQHmB

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/usage/launcher/src/test/resources/mongo-sharded-authentication.yaml
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/resources/mongo-sharded-authentication.yaml b/usage/launcher/src/test/resources/mongo-sharded-authentication.yaml
new file mode 100644
index 0000000..2d59f1c
--- /dev/null
+++ b/usage/launcher/src/test/resources/mongo-sharded-authentication.yaml
@@ -0,0 +1,45 @@
+name: Sharded MongoDB With Web App
+description: Auto-scaling web app backed by MongoDB
+location: softlayer:ams01
+services:
+- type: org.apache.brooklyn.entity.nosql.mongodb.sharding.MongoDBShardedDeployment
+  id: mongo
+  name: Mongo DB Backend
+  brooklyn.config:
+    initialShardClusterSize: 5
+    shardReplicaSetSize: 3
+    coLocatedRouterGroup: $brooklyn:component("webappcluster").attributeWhenReady("controlleddynamicwebappcluster.cluster")
+    mongodb.keyfile.url: classpath://mongo.key
+    mongodb.root.username: mongouser
+
+- type: org.apache.brooklyn.entity.webapp.ControlledDynamicWebAppCluster
+  id: webappcluster
+  brooklyn.config:
+    memberSpec:
+      $brooklyn:entitySpec:
+        type: org.apache.brooklyn.entity.nosql.mongodb.sharding.CoLocatedMongoDBRouter
+        brooklyn.enrichers:
+          - type: brooklyn.enricher.basic.Propagator
+            brooklyn.config:
+              enricher.propagating.sensorMapping:
+                $brooklyn:sensor("org.apache.brooklyn.entity.webapp.tomcat.TomcatServer", "http.port"): $brooklyn:sensor("org.apache.brooklyn.entity.webapp.tomcat.TomcatServer", "http.port")
+              enricher.producer: $brooklyn:component("child", "appserver")
+        brooklyn.config:
+          mongodb.keyfile.url: classpath://mongo.key
+          brooklyn.example.mongodb.username: $brooklyn:component("mongo").attributeWhenReady("mongodb.root.username")
+          brooklyn.example.mongodb.password: $brooklyn:component("mongo").attributeWhenReady("mongodb.root.password")
+          brooklyn.example.mongodb.authenticationDatabase: $brooklyn:component("mongo").attributeWhenReady("mongodb.authentication.database")
+          shardedDeployment: $brooklyn:component("mongo")
+          siblingSpecs:
+          - $brooklyn:entitySpec:
+              id: appserver
+              type: org.apache.brooklyn.entity.webapp.tomcat.TomcatServer
+              brooklyn.config:
+                war: "classpath://brooklyn-example-hello-world-sql-webapp.war"
+                java.sysprops:
+                  brooklyn.example.mongodb.port: $brooklyn:component("parent", "").attributeWhenReady("mongodb.server.port")
+                  brooklyn.example.mongodb.username: $brooklyn:component("mongo").attributeWhenReady("mongodb.root.username")
+                  brooklyn.example.mongodb.password: $brooklyn:component("mongo").attributeWhenReady("mongodb.root.password")
+                  brooklyn.example.mongodb.authenticationDatabase: $brooklyn:component("mongo").attributeWhenReady("mongodb.authentication.database")
+          - $brooklyn:entitySpec:
+              type: brooklyn.entity.basic.EmptySoftwareProcess

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/usage/launcher/src/test/resources/mongo-sharded.yaml
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/resources/mongo-sharded.yaml b/usage/launcher/src/test/resources/mongo-sharded.yaml
index 1a7a0bc..75b5413 100644
--- a/usage/launcher/src/test/resources/mongo-sharded.yaml
+++ b/usage/launcher/src/test/resources/mongo-sharded.yaml
@@ -24,10 +24,11 @@ services:
   id: mongo
   name: Mongo DB Backend
   brooklyn.config:
-    initialRouterClusterSize: 1
     initialShardClusterSize: 5
     shardReplicaSetSize: 3
     coLocatedRouterGroup: $brooklyn:component("webappcluster").attributeWhenReady("controlleddynamicwebappcluster.cluster")
+    mongodb.keyfile.url: classpath://mongo.key
+    mongodb.root.user: mongouser
 
 - type: org.apache.brooklyn.entity.webapp.ControlledDynamicWebAppCluster
   id: webappcluster
@@ -51,5 +52,8 @@ services:
                 war: "classpath://brooklyn-example-hello-world-sql-webapp.war"
                 java.sysprops:
                   brooklyn.example.mongodb.port: $brooklyn:component("parent", "").attributeWhenReady("mongodb.server.port")
+                  brooklyn.example.mongodb.username: $brooklyn:component("parent", "").attributeWhenReady("mongodb.root.username")
+                  brooklyn.example.mongodb.password: $brooklyn:component("parent", "").attributeWhenReady("mongodb.root.password")
+                  brooklyn.example.mongodb.authenticationDatabase: $brooklyn:component("parent", "").attributeWhenReady("mongodb.root.password")
           - $brooklyn:entitySpec:
               type: org.apache.brooklyn.entity.software.base.EmptySoftwareProcess

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/usage/launcher/src/test/resources/mongo.key
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/resources/mongo.key b/usage/launcher/src/test/resources/mongo.key
new file mode 100644
index 0000000..029e424
--- /dev/null
+++ b/usage/launcher/src/test/resources/mongo.key
@@ -0,0 +1,16 @@
+df1DzycxICi2RFa1xsDP5uiVcVtZ4EQBxffQ+FDuD4n81iOGW7pNOS49aH4t9PW6
+s0t+mASRnY/IVOsiTNT5VQWeMhf6b0/aYuXJp9ZZNQ9PmyA60a8x5x9K3YIoGYAd
+/RGenkIOIG9EjXnqTT1QgN66xVIUp8v2w0iuER0jiG+GcjBVVWGgqKcj6ZLQRecC
+6xSETYuJRbXdPanpnlk8oRYrtWFgcmQ8pl0/0hc/8i82PjTC8DdkqRqYQzhAvexh
+Fo8ZOPiS8xmiDWDsKBJscf6J5KKlgr/3ws0Kv5Qqxmq7oelAmZ+xRvyFBYbao3cz
+3XKBC9SBYfexnl25S9Ef94IV6bqls6SwQMTNS5W0sn3L/Mi55yEWFN44pcYCJ4ng
+oHMDaQyOC+Fi0rRcRduFZWYHlw7ibX0AaRQhwhh0YEbgFY2O7QoTNxwNycxLeKLr
+VMY8ZcTRzvmypAfetWHlwx97G+yXebCsZZ+TbAR/txficwmLFw/M5Qit8Op7YVFM
+zsrKnJZq/Ar8kLzw2UrIFfecaRl3hqT4CI8htaVW+fbc94RHNiZpHg5k/I+aNT45
+9uxRNNPcZiDln7ZV3skhVwQ0UeUZUBp0UZj33N2f/5JXxoRc5slb2mMFEKe+FH6a
+0M86QphH356jrIBSalm7duLAFzB8oyf7+JQgbpwooiO5D+KqIJevpwZXtjuaKVCU
+4bOJNq8AaJU6yjPNihHiGuGLv3/TmXP1Q8Cr4XSyzpv9pxZvvb0XYdlxWIQg0szv
+5QSTkgx6CCBoeDbVoWJh4bE3lobFponKC9o5j3nVAqPbxZocq6Lr6TWrXfwlNRcg
+Cvenxs8mjRQV7Hg7956P/dJtavN3UpSTwbius5h/oIf9ywBmVLNAIhbOS3kcacOC
+YlnJZGN+m1Wo9AvsmLz+yl5GB3W/zA4vUyhWnUY24BoKKEFYef594wi2sagz9TVC
+nLrWCE8djB9j4tudcz6PdFFhQHm
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1d0e2548/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommands.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommands.java b/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommands.java
index 4019a67..e91d60c 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommands.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommands.java
@@ -625,6 +625,13 @@ public class BashCommands {
                 +"\n"+"EOF_"+id+"\n";
     }
 
+    public static String pipeTextToFile(String text, String filepath) {
+        String id = Identifiers.makeRandomId(8);
+        return "cat > " + filepath + " << EOL_" + id + "\n"
+                + text
+                + "EOL_" + id + "\n";
+    }
+
     public static String prependToEtcHosts(String ip, String... hostnames) {
         String tempFileId = "bak"+Identifiers.makeRandomId(4);
         return sudo(String.format("sed -i."+tempFileId+" -e '1i\\\n%s %s' /etc/hosts", ip, Joiner.on(" ").join(hostnames)));


[4/9] incubator-brooklyn git commit: Add synchronization and checks for duplicate rules in addPermission security group customizer

Posted by sj...@apache.org.
Add synchronization and checks for duplicate rules in addPermission security group customizer


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

Branch: refs/heads/master
Commit: 4096358f5fcc3058f8185d2587086d93fb023c9a
Parents: 7ca2781
Author: Andrew Kennedy <gr...@apache.org>
Authored: Wed Sep 16 04:11:06 2015 +0100
Committer: Andrew Kennedy <gr...@apache.org>
Committed: Wed Sep 16 04:12:09 2015 +0100

----------------------------------------------------------------------
 .../JcloudsLocationSecurityGroupCustomizer.java | 27 +++++++++++++++-----
 1 file changed, 21 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4096358f/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/networking/JcloudsLocationSecurityGroupCustomizer.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/networking/JcloudsLocationSecurityGroupCustomizer.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/networking/JcloudsLocationSecurityGroupCustomizer.java
index cd4e45f..60a5271 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/networking/JcloudsLocationSecurityGroupCustomizer.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/networking/JcloudsLocationSecurityGroupCustomizer.java
@@ -33,6 +33,7 @@ import org.apache.brooklyn.location.jclouds.JcloudsLocation;
 import org.apache.brooklyn.location.jclouds.JcloudsLocationCustomizer;
 import org.apache.brooklyn.location.jclouds.JcloudsMachineLocation;
 import org.apache.brooklyn.location.jclouds.JcloudsSshMachineLocation;
+
 import org.jclouds.aws.AWSResponseException;
 import org.jclouds.compute.ComputeService;
 import org.jclouds.compute.domain.SecurityGroup;
@@ -43,9 +44,12 @@ import org.jclouds.net.domain.IpPermission;
 import org.jclouds.net.domain.IpProtocol;
 import org.jclouds.providers.ProviderMetadata;
 import org.jclouds.providers.Providers;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+
 import org.apache.brooklyn.location.jclouds.BasicJcloudsLocationCustomizer;
+import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.core.task.Tasks;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.net.Cidr;
@@ -179,14 +183,23 @@ public class JcloudsLocationSecurityGroupCustomizer extends BasicJcloudsLocation
      * Applies the given security group permissions to the given location.
      * <p>
      * Takes no action if the location's compute service does not have a security group extension.
-     * @param permissions The set of permissions to be applied to the location
+     * <p>
+     * The {@code synchronized} block is to serialize the permission changes, preventing race
+     * conditions in some clouds. If multiple customizations of the same group are done in parallel
+     * the changes may not be picked up by later customizations, meaning the same rule could possibly be
+     * added twice, which would fail. A finer grained mechanism would be preferable here, but
+     * we have no access to the information required, so this brute force serializing is required.
+     *
      * @param location Location to gain permissions
+     * @param permissions The set of permissions to be applied to the location
      */
     public JcloudsLocationSecurityGroupCustomizer addPermissionsToLocation(final JcloudsMachineLocation location, final Iterable<IpPermission> permissions) {
-        ComputeService computeService = location.getParent().getComputeService();
-        String nodeId = location.getNode().getId();
-        addPermissionsToLocation(permissions, nodeId, computeService);
-        return this;
+        synchronized (JcloudsLocationSecurityGroupCustomizer.class) {
+            ComputeService computeService = location.getParent().getComputeService();
+            String nodeId = location.getNode().getId();
+            addPermissionsToLocation(permissions, nodeId, computeService);
+            return this;
+        }
     }
 
     /**
@@ -228,7 +241,9 @@ public class JcloudsLocationSecurityGroupCustomizer extends BasicJcloudsLocation
         } finally {
             Tasks.resetBlockingDetails();
         }
-        for (IpPermission permission : permissions) {
+        MutableList<IpPermission> newPermissions = MutableList.copyOf(permissions);
+        Iterables.removeAll(newPermissions, machineUniqueSecurityGroup.getIpPermissions());
+        for (IpPermission permission : newPermissions) {
             addPermission(permission, machineUniqueSecurityGroup, securityApi);
         }
     }


[9/9] incubator-brooklyn git commit: This closes #901

Posted by sj...@apache.org.
This closes #901


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

Branch: refs/heads/master
Commit: 841db6a25a8a5efc4bc87bc5112ba51cd4e246a3
Parents: ec1d33f 4096358
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Wed Sep 16 11:51:48 2015 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed Sep 16 11:51:48 2015 +0100

----------------------------------------------------------------------
 .../JcloudsLocationSecurityGroupCustomizer.java | 27 +++++++++++++++-----
 1 file changed, 21 insertions(+), 6 deletions(-)
----------------------------------------------------------------------



[7/9] incubator-brooklyn git commit: This closes #894

Posted by sj...@apache.org.
This closes #894


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

Branch: refs/heads/master
Commit: d62ed2f30cab2b08314b11ca3119e03c23c401a2
Parents: 68732cc d4bb730
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Wed Sep 16 11:51:19 2015 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed Sep 16 11:51:19 2015 +0100

----------------------------------------------------------------------
 .../hello-world-sql/src/main/webapp/mongo.jsp   |  23 +++-
 parent/pom.xml                                  |   2 +-
 software/nosql/pom.xml                          |   1 +
 .../nosql/mongodb/AbstractMongoDBServer.java    |   3 +-
 .../nosql/mongodb/AbstractMongoDBSshDriver.java |  83 ++++++++++---
 .../mongodb/MongoDBAuthenticationMixins.java    |  51 ++++++++
 .../mongodb/MongoDBAuthenticationUtils.java     |  79 ++++++++++++
 .../nosql/mongodb/MongoDBClientSupport.java     |  71 ++++++++---
 .../entity/nosql/mongodb/MongoDBReplicaSet.java |   2 +-
 .../nosql/mongodb/MongoDBReplicaSetImpl.java    | 122 +++++++++++--------
 .../entity/nosql/mongodb/MongoDBServerImpl.java |   1 -
 .../sharding/CoLocatedMongoDBRouterImpl.java    |  50 ++++----
 .../MongoDBConfigServerClusterImpl.java         |   7 +-
 .../sharding/MongoDBShardClusterImpl.java       |  33 ++---
 .../sharding/MongoDBShardedDeploymentImpl.java  |  42 +++++--
 .../entity/nosql/mongodb/MongoDBTestHelper.java |   2 +-
 .../nosql/src/test/resources/mongodb-keyfile    |  16 +++
 .../resources/mongo-sharded-authentication.yaml |  65 ++++++++++
 .../src/test/resources/mongo-sharded.yaml       |   7 +-
 usage/launcher/src/test/resources/mongo.key     |  16 +++
 .../apache/brooklyn/util/ssh/BashCommands.java  |  11 +-
 21 files changed, 537 insertions(+), 150 deletions(-)
----------------------------------------------------------------------



[2/9] incubator-brooklyn git commit: Fixes mongodb authentication for sharded deployment with webapp

Posted by sj...@apache.org.
Fixes mongodb authentication for sharded deployment with webapp


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

Branch: refs/heads/master
Commit: aed8448b415a0828d01ea7be6930e5c88a1aeea6
Parents: 1d0e254
Author: Martin Harris <gi...@nakomis.com>
Authored: Mon Sep 14 16:32:00 2015 +0100
Committer: Martin Harris <gi...@nakomis.com>
Committed: Mon Sep 14 16:36:22 2015 +0100

----------------------------------------------------------------------
 .../hello-world-sql/src/main/webapp/mongo.jsp   | 15 +++++++--
 parent/pom.xml                                  |  2 +-
 .../nosql/mongodb/AbstractMongoDBSshDriver.java | 12 +++----
 .../nosql/mongodb/MongoDBClientSupport.java     | 19 ++++++-----
 .../nosql/mongodb/MongoDBReplicaSetImpl.java    | 15 +++++++--
 .../entity/nosql/mongodb/ReplicaSetConfig.java  |  4 +++
 .../MongoDBConfigServerClusterImpl.java         |  7 +++--
 .../sharding/MongoDBShardClusterImpl.java       | 33 +++++++++++---------
 .../sharding/MongoDBShardedDeploymentImpl.java  |  3 +-
 .../entity/nosql/mongodb/MongoDBTestHelper.java |  2 +-
 .../resources/mongo-sharded-authentication.yaml | 26 +++++++++++++--
 .../src/test/resources/mongo-sharded.yaml       | 11 ++-----
 12 files changed, 101 insertions(+), 48 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/aed8448b/examples/webapps/hello-world-sql/src/main/webapp/mongo.jsp
----------------------------------------------------------------------
diff --git a/examples/webapps/hello-world-sql/src/main/webapp/mongo.jsp b/examples/webapps/hello-world-sql/src/main/webapp/mongo.jsp
index 7e110cc..bad529f 100644
--- a/examples/webapps/hello-world-sql/src/main/webapp/mongo.jsp
+++ b/examples/webapps/hello-world-sql/src/main/webapp/mongo.jsp
@@ -55,13 +55,24 @@ if (port==null) {
 
 <%
 /* begin database-enabled block */ }
-MongoCredential credential = MongoCredential.createMongoCRCredential(username, authenticationDatabase, password.toCharArray());
+boolean authenticationEnabled = password != null && password.length() > 0;
+
 ServerAddress address = new ServerAddress("localhost", new Integer(port));
+
 MongoClientOptions connectionOptions = MongoClientOptions.builder()
     .autoConnectRetry(true)
     .socketKeepAlive(true)
     .build();
-MongoClient client = new MongoClient(address, Arrays.asList(credential),connectionOptions);
+
+MongoClient client;
+
+if (authenticationEnabled) {
+    MongoCredential credential = MongoCredential.createMongoCRCredential(username, authenticationDatabase, password.toCharArray());
+    client = new MongoClient(address, Arrays.asList(credential),connectionOptions);
+} else {
+    client = new MongoClient(address, connectionOptions);
+}
+
 DB database = client.getDB("visitors");
 DBCollection messages =  database.getCollection("messages");
 int i=0;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/aed8448b/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index 246f64c..ad4ebb1 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -107,7 +107,7 @@
         <jsonPath.version>2.0.0</jsonPath.version>
         <commons-compress.version>1.4</commons-compress.version>
         <qpid.version>0.20</qpid.version>
-        <mongodb.version>2.11.4</mongodb.version>
+        <mongodb.version>3.0.3</mongodb.version>
         <riak.version>1.4.0</riak.version>
         <maven-war-plugin.version>2.4</maven-war-plugin.version>
         <validation-api.version>1.0.0.GA</validation-api.version>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/aed8448b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBSshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBSshDriver.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBSshDriver.java
index 9fe949d..277fafd 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBSshDriver.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBSshDriver.java
@@ -27,8 +27,8 @@ import org.apache.brooklyn.api.location.OsDetails;
 import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.entity.software.base.AbstractSoftwareProcessSshDriver;
 import org.apache.brooklyn.entity.software.base.lifecycle.ScriptHelper;
+import org.apache.brooklyn.util.core.internal.ssh.SshTool;
 import org.apache.brooklyn.util.time.Duration;
-import org.apache.brooklyn.util.time.Time;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.brooklyn.location.ssh.SshMachineLocation;
@@ -61,7 +61,7 @@ public abstract class AbstractMongoDBSshDriver extends AbstractSoftwareProcessSs
         List<String> urls = resolver.getTargets();
         String saveAs = resolver.getFilename();
     
-        List<String> commands = new LinkedList<String>();
+        List<String> commands = new LinkedList<>();
         commands.addAll(BashCommands.commandsToDownloadUrlsAs(urls, saveAs));
         commands.add(BashCommands.INSTALL_TAR);
         commands.add("tar xzfv " + saveAs);
@@ -75,7 +75,7 @@ public abstract class AbstractMongoDBSshDriver extends AbstractSoftwareProcessSs
     public void customize() {
         Map<?,?> ports = ImmutableMap.of("port", getServerPort());
         Networking.checkPortsValid(ports);
-        List<String> commands = new LinkedList<String>();
+        List<String> commands = new LinkedList<>();
         commands.add(String.format("mkdir -p %s", getDataDirectory()));
 
         if (MongoDBAuthenticationUtils.usesAuthentication(entity)) {
@@ -87,8 +87,8 @@ public abstract class AbstractMongoDBSshDriver extends AbstractSoftwareProcessSs
                 copyResource(keyfileUrl, destinationLocation);
             } else {
                 commands.add(BashCommands.pipeTextToFile(keyfileContents, destinationLocation));
-                commands.add("chmod 600 " + destinationLocation);
             }
+            commands.add("chmod 600 " + destinationLocation);
         }
 
         newScript(CUSTOMIZING)
@@ -192,8 +192,7 @@ public abstract class AbstractMongoDBSshDriver extends AbstractSoftwareProcessSs
 
     protected ImmutableList.Builder<String> getArgsBuilderWithDefaults(AbstractMongoDBServer server) {
         ImmutableList.Builder<String> builder = getArgsBuilderWithNoAuthentication(server);
-        String keyfileContents = entity.config().get(AbstractMongoDBServer.MONGODB_KEYFILE_CONTENTS);
-        if (keyfileContents != null) {
+        if (MongoDBAuthenticationUtils.usesAuthentication(entity)) {
             builder.add("--keyFile", entity.getAttribute(AbstractMongoDBServer.MONGODB_KEYFILE_DESTINATION));
         }
         return builder;
@@ -216,6 +215,7 @@ public abstract class AbstractMongoDBSshDriver extends AbstractSoftwareProcessSs
         commands.add(String.format("%s/bin/mongod %s > out.log 2> err.log < /dev/null", getExpandedInstallDir(), args));
 
         newScript(LAUNCHING)
+                .setFlag(SshTool.PROP_CONNECT_TIMEOUT, Duration.TEN_SECONDS.toMilliseconds())
                 .updateTaskAndFailOnNonZeroResultCode()
                 .body.append(commands).execute();
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/aed8448b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClientSupport.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClientSupport.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClientSupport.java
index fa2022f..32c128c 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClientSupport.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClientSupport.java
@@ -65,7 +65,6 @@ public class MongoDBClientSupport {
 
     // Set client to automatically reconnect to servers.
     private static final MongoClientOptions connectionOptions = MongoClientOptions.builder()
-            .autoConnectRetry(true)
             .socketKeepAlive(true)
             .build();
 
@@ -112,12 +111,18 @@ public class MongoDBClientSupport {
         MongoClient client = client();
         try {
             DB db = client.getDB(database);
-            CommandResult status;
-            try {
-                status = db.command(command);
-            } catch (MongoException e) {
-                LOG.warn("Command " + command + " on " + getServerAddress() + " failed", e);
-                return Optional.absent();
+            CommandResult status = null;
+            // The mongoDB client can occasionally fail to connect. Try up to 5 times to run the command
+            for (int i = 0; i < 5; i++) {
+                try {
+                    status = db.command(command);
+                    break;
+                } catch (MongoException e) {
+                    LOG.warn("Command " + command + " on " + getServerAddress() + " failed", e);
+                    if (i == 4) {
+                        return Optional.absent();
+                    }
+                }
             }
             if (!status.ok()) {
                 LOG.debug("Unexpected result of {} on {}: {}",

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/aed8448b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
index a9db033..046c716 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
@@ -35,6 +35,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 import javax.annotation.Nullable;
 
 import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntityLocal;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.policy.PolicySpec;
@@ -400,10 +401,18 @@ public class MongoDBReplicaSetImpl extends DynamicClusterImpl implements MongoDB
             // Ignored
         }
         @Override protected void onEntityAdded(Entity member) {
-            ((MongoDBReplicaSetImpl)entity).serverAdded((MongoDBServer) member);
+            try {
+                ((MongoDBReplicaSetImpl) entity).serverAdded((MongoDBServer) member);
+            } catch (Exception e) {
+                ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator((EntityLocal)member, "Failed to update replicaset", e);
+            }
         }
         @Override protected void onEntityRemoved(Entity member) {
-            ((MongoDBReplicaSetImpl)entity).serverRemoved((MongoDBServer) member);
+            try {
+                ((MongoDBReplicaSetImpl) entity).serverRemoved((MongoDBServer) member);
+            } catch (Exception e) {
+                ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator((EntityLocal)member, "Failed to update replicaset", e);
+            }
         }
-    };
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/aed8448b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/ReplicaSetConfig.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/ReplicaSetConfig.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/ReplicaSetConfig.java
index 9ea240b..9da870e 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/ReplicaSetConfig.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/ReplicaSetConfig.java
@@ -148,6 +148,10 @@ public class ReplicaSetConfig {
         BasicBSONObject member = new BasicBSONObject();
         member.put("_id", id);
         member.put("host", String.format("%s:%s", hostname, port));
+        if (members.contains(member)) {
+            LOG.warn("Ignoring attempt to add entity to a set of which it is already a member");
+            return this;
+        }
         members.add(member);
         return this;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/aed8448b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBConfigServerClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBConfigServerClusterImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBConfigServerClusterImpl.java
index 70fd15e..b5bf2cc 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBConfigServerClusterImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBConfigServerClusterImpl.java
@@ -23,11 +23,13 @@ import java.util.Collection;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.location.access.BrooklynAccessUtils;
 import org.apache.brooklyn.entity.group.DynamicClusterImpl;
 
 import com.google.common.base.Function;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
+import com.google.common.net.HostAndPort;
 
 public class MongoDBConfigServerClusterImpl extends DynamicClusterImpl implements MongoDBConfigServerCluster {
     
@@ -46,10 +48,11 @@ public class MongoDBConfigServerClusterImpl extends DynamicClusterImpl implement
         Iterable<String> memberHostNamesAndPorts = Iterables.transform(getMembers(), new Function<Entity, String>() {
             @Override
             public String apply(Entity entity) {
-                return entity.getAttribute(MongoDBConfigServer.SUBNET_HOSTNAME) + ":" + entity.getAttribute(MongoDBConfigServer.PORT);
+                HostAndPort hostAndPort = BrooklynAccessUtils.getBrooklynAccessibleAddress(entity, entity.getAttribute(MongoDBConfigServer.PORT));
+                return hostAndPort.getHostText() + ":" + hostAndPort.getPort();
             }
         });
-        setAttribute(MongoDBConfigServerCluster.CONFIG_SERVER_ADDRESSES, ImmutableList.copyOf(memberHostNamesAndPorts));
+        sensors().set(MongoDBConfigServerCluster.CONFIG_SERVER_ADDRESSES, ImmutableList.copyOf(memberHostNamesAndPorts));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/aed8448b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardClusterImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardClusterImpl.java
index 31198a8..5f008ea 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardClusterImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardClusterImpl.java
@@ -141,23 +141,28 @@ public class MongoDBShardClusterImpl extends DynamicClusterImpl implements Mongo
                     } catch (UnknownHostException e) {
                         throw Exceptions.propagate(e);
                     }
-                    
-                    MongoDBServer primary = replicaSet.getAttribute(MongoDBReplicaSet.PRIMARY_ENTITY);
-                    if (primary != null) {
-                        String addr = String.format("%s:%d", primary.getAttribute(MongoDBServer.SUBNET_HOSTNAME), primary.getAttribute(MongoDBServer.PORT));
-                        String replicaSetURL = ((MongoDBReplicaSet) replicaSet).getName() + "/" + addr;
-                        boolean added = client.addShardToRouter(replicaSetURL);
-                        if (added) {
-                            LOG.info("{} added shard {} via {}", new Object[] {MongoDBShardClusterImpl.this, replicaSetURL, router});
-                            addedMembers.add(replicaSet);
-                            reschedule = false;
+
+                    try {
+                        MongoDBServer primary = replicaSet.getAttribute(MongoDBReplicaSet.PRIMARY_ENTITY);
+                        if (primary != null) {
+                            String addr = String.format("%s:%d", primary.getAttribute(MongoDBServer.SUBNET_HOSTNAME), primary.getAttribute(MongoDBServer.PORT));
+                            String replicaSetURL = ((MongoDBReplicaSet) replicaSet).getName() + "/" + addr;
+                            boolean added = client.addShardToRouter(replicaSetURL);
+                            if (added) {
+                                LOG.info("{} added shard {} via {}", new Object[]{MongoDBShardClusterImpl.this, replicaSetURL, router});
+                                addedMembers.add(replicaSet);
+                                reschedule = false;
+                            } else {
+                                LOG.debug("Rescheduling addition of shard {} because add failed via router {}", replicaSetURL, router);
+                                reschedule = true;
+                            }
                         } else {
-                            LOG.debug("Rescheduling addition of shard {} because add failed via router {}", replicaSetURL, router);
+                            LOG.debug("Rescheduling addition of shard {} because primary is null", replicaSet);
                             reschedule = true;
                         }
-                    } else {
-                        LOG.debug("Rescheduling addition of shard {} because primary is null", replicaSet);
-                        reschedule = true;
+                    } catch (Exception e) {
+                        LOG.error("Failed to add shard to router {}:  ", router,  e);
+                        throw Exceptions.propagate(e);
                     }
                 }
                 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/aed8448b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
index 0b8a1b6..198e787 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
@@ -95,13 +95,14 @@ public class MongoDBShardedDeploymentImpl extends AbstractEntity implements Mong
             final MongoDBShardCluster shards = getAttribute(SHARD_CLUSTER);
             List<DynamicCluster> clusters = ImmutableList.of(getAttribute(CONFIG_SERVER_CLUSTER), routers, shards);
             Entities.invokeEffectorList(this, clusters, Startable.START, ImmutableMap.of("locations", locations))
-                .get();
+                    .get();
 
             if (getConfigRaw(MongoDBShardedDeployment.CO_LOCATED_ROUTER_GROUP, true).isPresent()) {
                 addPolicy(PolicySpec.create(ColocatedRouterTrackingPolicy.class)
                         .displayName("Co-located router tracker")
                         .configure("group", getConfig(MongoDBShardedDeployment.CO_LOCATED_ROUTER_GROUP)));
             }
+
             ServiceNotUpLogic.clearNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL);
             ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING);
         } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/aed8448b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBTestHelper.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBTestHelper.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBTestHelper.java
index fb47895..76b2a91 100644
--- a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBTestHelper.java
+++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBTestHelper.java
@@ -115,7 +115,7 @@ public class MongoDBTestHelper {
         try {
             HostAndPort hap = BrooklynAccessUtils.getBrooklynAccessibleAddress(server, server.getAttribute(MongoDBServer.PORT));
             return new MongoClient(hap.getHostText(), hap.getPort());
-        } catch (UnknownHostException e) {
+        } catch (Exception e) {
             // Fail whatever test called this method.
             throw Throwables.propagate(e);
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/aed8448b/usage/launcher/src/test/resources/mongo-sharded-authentication.yaml
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/resources/mongo-sharded-authentication.yaml b/usage/launcher/src/test/resources/mongo-sharded-authentication.yaml
index 2d59f1c..9e594db 100644
--- a/usage/launcher/src/test/resources/mongo-sharded-authentication.yaml
+++ b/usage/launcher/src/test/resources/mongo-sharded-authentication.yaml
@@ -1,6 +1,25 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
 name: Sharded MongoDB With Web App
 description: Auto-scaling web app backed by MongoDB
-location: softlayer:ams01
+location: AWS California
 services:
 - type: org.apache.brooklyn.entity.nosql.mongodb.sharding.MongoDBShardedDeployment
   id: mongo
@@ -8,6 +27,7 @@ services:
   brooklyn.config:
     initialShardClusterSize: 5
     shardReplicaSetSize: 3
+    mongodb.router.cluster.initial.size: 0
     coLocatedRouterGroup: $brooklyn:component("webappcluster").attributeWhenReady("controlleddynamicwebappcluster.cluster")
     mongodb.keyfile.url: classpath://mongo.key
     mongodb.root.username: mongouser
@@ -19,7 +39,7 @@ services:
       $brooklyn:entitySpec:
         type: org.apache.brooklyn.entity.nosql.mongodb.sharding.CoLocatedMongoDBRouter
         brooklyn.enrichers:
-          - type: brooklyn.enricher.basic.Propagator
+          - type: org.apache.brooklyn.enricher.stock.Propagator
             brooklyn.config:
               enricher.propagating.sensorMapping:
                 $brooklyn:sensor("org.apache.brooklyn.entity.webapp.tomcat.TomcatServer", "http.port"): $brooklyn:sensor("org.apache.brooklyn.entity.webapp.tomcat.TomcatServer", "http.port")
@@ -42,4 +62,4 @@ services:
                   brooklyn.example.mongodb.password: $brooklyn:component("mongo").attributeWhenReady("mongodb.root.password")
                   brooklyn.example.mongodb.authenticationDatabase: $brooklyn:component("mongo").attributeWhenReady("mongodb.authentication.database")
           - $brooklyn:entitySpec:
-              type: brooklyn.entity.basic.EmptySoftwareProcess
+              type: org.apache.brooklyn.entity.software.base.EmptySoftwareProcess

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/aed8448b/usage/launcher/src/test/resources/mongo-sharded.yaml
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/resources/mongo-sharded.yaml b/usage/launcher/src/test/resources/mongo-sharded.yaml
index 75b5413..d453329 100644
--- a/usage/launcher/src/test/resources/mongo-sharded.yaml
+++ b/usage/launcher/src/test/resources/mongo-sharded.yaml
@@ -18,7 +18,7 @@
 #
 name: Sharded MongoDB With Web App
 description: Auto-scaling web app backed by MongoDB
-location: my-docker-cloud
+location: localhost
 services:
 - type: org.apache.brooklyn.entity.nosql.mongodb.sharding.MongoDBShardedDeployment
   id: mongo
@@ -27,8 +27,6 @@ services:
     initialShardClusterSize: 5
     shardReplicaSetSize: 3
     coLocatedRouterGroup: $brooklyn:component("webappcluster").attributeWhenReady("controlleddynamicwebappcluster.cluster")
-    mongodb.keyfile.url: classpath://mongo.key
-    mongodb.root.user: mongouser
 
 - type: org.apache.brooklyn.entity.webapp.ControlledDynamicWebAppCluster
   id: webappcluster
@@ -40,20 +38,17 @@ services:
           - type: org.apache.brooklyn.enricher.stock.Propagator
             brooklyn.config:
               enricher.propagating.sensorMapping:
-                $brooklyn:sensor("org.apache.brooklyn.entity.webapp.jboss.JBoss7Server", "http.port"): $brooklyn:sensor("org.apache.brooklyn.entity.webapp.jboss.JBoss7Server", "http.port") 
+                $brooklyn:sensor("org.apache.brooklyn.entity.webapp.tomcat.TomcatServer", "http.port"): $brooklyn:sensor("org.apache.brooklyn.entity.webapp.tomcat.TomcatServer", "http.port")
               enricher.producer: $brooklyn:component("child", "appserver")
         brooklyn.config:
           shardedDeployment: $brooklyn:component("mongo")
           siblingSpecs:
           - $brooklyn:entitySpec:
               id: appserver
-              type: org.apache.brooklyn.entity.webapp.jboss.JBoss7Server
+              type: org.apache.brooklyn.entity.webapp.tomcat.TomcatServer
               brooklyn.config:
                 war: "classpath://brooklyn-example-hello-world-sql-webapp.war"
                 java.sysprops:
                   brooklyn.example.mongodb.port: $brooklyn:component("parent", "").attributeWhenReady("mongodb.server.port")
-                  brooklyn.example.mongodb.username: $brooklyn:component("parent", "").attributeWhenReady("mongodb.root.username")
-                  brooklyn.example.mongodb.password: $brooklyn:component("parent", "").attributeWhenReady("mongodb.root.password")
-                  brooklyn.example.mongodb.authenticationDatabase: $brooklyn:component("parent", "").attributeWhenReady("mongodb.root.password")
           - $brooklyn:entitySpec:
               type: org.apache.brooklyn.entity.software.base.EmptySoftwareProcess


[6/9] incubator-brooklyn git commit: This closes #902

Posted by sj...@apache.org.
This closes #902


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

Branch: refs/heads/master
Commit: 68732cc43541628adad107e18894adcdfdeb7887
Parents: 5bb7cc6 3129a12
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Wed Sep 16 11:51:16 2015 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed Sep 16 11:51:16 2015 +0100

----------------------------------------------------------------------
 .../apache/brooklyn/util/repeat/Repeater.java   | 49 ++++++++------------
 1 file changed, 20 insertions(+), 29 deletions(-)
----------------------------------------------------------------------



[5/9] incubator-brooklyn git commit: Make Repeater implement Callable

Posted by sj...@apache.org.
Make Repeater implement Callable


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

Branch: refs/heads/master
Commit: 3129a12c6ab77728308cc0093134838490935087
Parents: 7ca2781
Author: Andrew Kennedy <gr...@apache.org>
Authored: Wed Sep 16 04:13:07 2015 +0100
Committer: Andrew Kennedy <gr...@apache.org>
Committed: Wed Sep 16 04:13:07 2015 +0100

----------------------------------------------------------------------
 .../apache/brooklyn/util/repeat/Repeater.java   | 49 ++++++++------------
 1 file changed, 20 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3129a12c/utils/common/src/main/java/org/apache/brooklyn/util/repeat/Repeater.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/repeat/Repeater.java b/utils/common/src/main/java/org/apache/brooklyn/util/repeat/Repeater.java
index d8ac013..b1df990 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/repeat/Repeater.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/repeat/Repeater.java
@@ -32,6 +32,7 @@ import org.apache.brooklyn.util.repeat.Repeater;
 import org.apache.brooklyn.util.time.CountdownTimer;
 import org.apache.brooklyn.util.time.Duration;
 import org.apache.brooklyn.util.time.Time;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -43,31 +44,15 @@ import com.google.common.base.Stopwatch;
 import com.google.common.util.concurrent.Callables;
 
 /**
- * Simple DSL to repeat a fragment of code periodically until a condition is satisfied.
- *
- * In its simplest case, it is passed two {@link groovy.lang.Closure}s / {@link Callable} - 
- * the first is executed, then the second. If the second closure returns false, the loop
- * is repeated; if true, it finishes. Further customization can be applied to set the period 
- * between loops and place a maximum limit on how long the loop should run for.
+ * Simple mechanism to repeat an operation periodically until a condition is satisfied.
  * <p>
- * It is configured in a <em>fluent</em> manner. For example, in Groovy:
- * <pre>
- * {@code
- * Repeater.create("Wait until the Frobnitzer is ready")
- *     .repeat {
- *         status = frobnitzer.getStatus()
- *     }
- *     .until {
- *         status == "Ready" || status == "Failed"
- *     }
- *     .limitIterationsTo(30)
- *     .run()
- * }
- * </pre>
- * 
- * Or in Java:
- * <pre>
- * {@code
+ * In its simplest case it is passed two {@link Callable} objects, the <em>operation</em>
+ * and the <em>condition</em> which are executed in that order. This execution is repeated
+ * until the <em>condition</em> returns {@code true}, when the loop finishes. Further customization
+ * can be applied to set the period between loops and place a maximum limit on how long the
+ * loop should run for, as well as other timing and delay properties.
+ * <p>
+ * <pre>{@code
  * Repeater.create("Wait until the Frobnitzer is ready")
  *     .until(new Callable<Boolean>() {
  *              public Boolean call() {
@@ -76,10 +61,11 @@ import com.google.common.util.concurrent.Callables;
  *              }})
  *     .limitIterationsTo(30)
  *     .run()
- * }
- * </pre>
+ * }</pre>
+ * <p>
+ * The 
  */
-public class Repeater {
+public class Repeater implements Callable<Boolean> {
 
     private static final Logger log = LoggerFactory.getLogger(Repeater.class);
 
@@ -389,7 +375,7 @@ public class Repeater {
             Time.sleep(delayThisIteration);
         }
     }
-    
+
     public String getDescription() {
         return description;
     }
@@ -397,5 +383,10 @@ public class Repeater {
     public Duration getTimeLimit() {
         return timeLimit;
     }
-    
+
+    @Override
+    public Boolean call() throws Exception {
+        return run();
+    }
+
 }


[3/9] incubator-brooklyn git commit: Misc tidies to mongoDB following PR review

Posted by sj...@apache.org.
Misc tidies to mongoDB following PR review


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

Branch: refs/heads/master
Commit: d4bb730ad4309db5be28784a61de637511bfc4ad
Parents: aed8448
Author: Martin Harris <gi...@nakomis.com>
Authored: Tue Sep 15 11:39:58 2015 +0100
Committer: Martin Harris <gi...@nakomis.com>
Committed: Tue Sep 15 15:03:01 2015 +0100

----------------------------------------------------------------------
 .../nosql/mongodb/AbstractMongoDBSshDriver.java |  10 +-
 .../mongodb/MongoDBAuthenticationMixins.java    |   4 +-
 .../mongodb/MongoDBAuthenticationUtils.java     |  16 +--
 .../nosql/mongodb/MongoDBClientSupport.java     |  60 ++++++---
 .../nosql/mongodb/MongoDBReplicaSetImpl.java    | 121 ++++++++++---------
 .../entity/nosql/mongodb/ReplicaSetConfig.java  |   4 -
 .../sharding/CoLocatedMongoDBRouterImpl.java    |  40 ++----
 .../sharding/MongoDBRouterSshDriver.java        |   4 -
 .../sharding/MongoDBShardedDeploymentImpl.java  |   1 -
 .../apache/brooklyn/util/ssh/BashCommands.java  |  12 +-
 10 files changed, 132 insertions(+), 140 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4bb730a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBSshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBSshDriver.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBSshDriver.java
index 277fafd..c182355 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBSshDriver.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBSshDriver.java
@@ -82,8 +82,11 @@ public abstract class AbstractMongoDBSshDriver extends AbstractSoftwareProcessSs
             String destinationLocation = Os.mergePaths(getRunDir(), "mongodb-keyfile");
             entity.sensors().set(AbstractMongoDBServer.MONGODB_KEYFILE_DESTINATION, destinationLocation);
             String keyfileContents = entity.config().get(AbstractMongoDBServer.MONGODB_KEYFILE_CONTENTS);
-            if (keyfileContents == null) {
+            if (Strings.isNullOrEmpty(keyfileContents)) {
                 String keyfileUrl = entity.config().get(AbstractMongoDBServer.MONGODB_KEYFILE_URL);
+                if (Strings.isNullOrEmpty(keyfileUrl)) {
+                    throw new IllegalStateException("MongoDBAuthenticationUtils.usesAuthentication returned true, but neither keyfileContents nor keyfileUrl are set");
+                }
                 copyResource(keyfileUrl, destinationLocation);
             } else {
                 commands.add(BashCommands.pipeTextToFile(keyfileContents, destinationLocation));
@@ -211,13 +214,12 @@ public abstract class AbstractMongoDBSshDriver extends AbstractSoftwareProcessSs
     
     protected void launch(ImmutableList.Builder<String> argsBuilder) {
         String args = Joiner.on(" ").join(argsBuilder.build());
-        List<String> commands = new LinkedList<String>();
-        commands.add(String.format("%s/bin/mongod %s > out.log 2> err.log < /dev/null", getExpandedInstallDir(), args));
+        String command = String.format("%s/bin/mongod %s >> out.log 2>> err.log < /dev/null", getExpandedInstallDir(), args);
 
         newScript(LAUNCHING)
                 .setFlag(SshTool.PROP_CONNECT_TIMEOUT, Duration.TEN_SECONDS.toMilliseconds())
                 .updateTaskAndFailOnNonZeroResultCode()
-                .body.append(commands).execute();
+                .body.append(command).execute();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4bb730a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationMixins.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationMixins.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationMixins.java
index a47c384..0ad885b 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationMixins.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationMixins.java
@@ -28,11 +28,11 @@ import org.apache.brooklyn.util.core.flags.SetFromFlag;
 public interface MongoDBAuthenticationMixins {
     @SetFromFlag("mongodbKeyfileContents")
     ConfigKey<String> MONGODB_KEYFILE_CONTENTS = ConfigKeys.newStringConfigKey(
-            "mongodb.keyfile.contents", "Contents of the keyfile used for authentication");
+            "mongodb.keyfile.contents", "Contents of the keyfile used for authentication. If mongodb.keyfile.contents and mongodb.keyfile.url are both set, mongodb.keyfile.contents will take precedence");
 
     @SetFromFlag("mongodbKeyfileUrl")
     ConfigKey<String> MONGODB_KEYFILE_URL = ConfigKeys.newStringConfigKey(
-            "mongodb.keyfile.url", "Location of the keyfile used for authentication");
+            "mongodb.keyfile.url", "Location of the keyfile used for authentication. If mongodb.keyfile.contents and mongodb.keyfile.url are both set, mongodb.keyfile.contents will take precedence");
 
     @SetFromFlag("rootUsername")
     BasicAttributeSensorAndConfigKey<String> ROOT_USERNAME =

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4bb730a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationUtils.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationUtils.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationUtils.java
index 0c337a0..41808ae 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationUtils.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBAuthenticationUtils.java
@@ -39,26 +39,23 @@ public class MongoDBAuthenticationUtils {
     public static boolean usesAuthentication(Entity entity) {
         String keyfileContents = entity.config().get(MongoDBAuthenticationMixins.MONGODB_KEYFILE_CONTENTS);
         String keyfileUrl = entity.config().get(MongoDBAuthenticationMixins.MONGODB_KEYFILE_URL);
-        if (!(Strings.isEmpty(keyfileContents) || Strings.isEmpty(keyfileUrl))) {
-            throw new IllegalStateException("keyfile contents and keyfile location cannot both be set");
-        }
-        if (Strings.isEmpty(keyfileContents) && Strings.isEmpty(keyfileUrl)) {
-            return false;
-        }
-        return true;
+        return Strings.isNonBlank(keyfileContents) || Strings.isNonBlank(keyfileUrl);
     }
 
     public static String getRootPassword(Entity entity) {
         String password = entity.config().get(MongoDBAuthenticationMixins.ROOT_PASSWORD);
         if (Strings.isEmpty(password)) {
             LOG.debug(entity + " has no password specified for " + MongoDBAuthenticationMixins.ROOT_PASSWORD.getName() + "; using a random string");
-            password = Strings.makeRandomId(8);
+            password = Strings.makeRandomId(16);
             entity.sensors().set(MongoDBAuthenticationMixins.ROOT_PASSWORD, password);
             entity.config().set(MongoDBAuthenticationMixins.ROOT_PASSWORD, password);
         }
         return password;
     }
 
+    /**
+     * Configures the {@code spec} with authentication configuration from {@code source}
+     */
     public static void setAuthenticationConfig(EntitySpec<?> spec, Entity source) {
         if (MongoDBAuthenticationUtils.usesAuthentication(source)) {
             spec.configure(MongoDBAuthenticationMixins.MONGODB_KEYFILE_CONTENTS, source.config().get(MongoDBAuthenticationMixins.MONGODB_KEYFILE_CONTENTS));
@@ -68,6 +65,9 @@ public class MongoDBAuthenticationUtils {
         }
     }
 
+    /**
+     * Configures the {@code spec} with authentication configuration from {@code source}
+     */
     public static void setAuthenticationConfig(Entity entity, Entity source) {
         if (MongoDBAuthenticationUtils.usesAuthentication(source)) {
             entity.config().set(MongoDBAuthenticationMixins.MONGODB_KEYFILE_CONTENTS, source.config().get(MongoDBAuthenticationMixins.MONGODB_KEYFILE_CONTENTS));

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4bb730a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClientSupport.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClientSupport.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClientSupport.java
index 32c128c..3fadd4d 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClientSupport.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClientSupport.java
@@ -19,8 +19,12 @@
 package org.apache.brooklyn.entity.nosql.mongodb;
 
 import java.net.UnknownHostException;
+import java.util.concurrent.Callable;
 
 import org.apache.brooklyn.core.location.access.BrooklynAccessUtils;
+import org.apache.brooklyn.util.exceptions.ReferenceWithError;
+import org.apache.brooklyn.util.repeat.Repeater;
+import org.apache.brooklyn.util.time.Duration;
 import org.bson.BSONObject;
 import org.bson.BasicBSONObject;
 import org.slf4j.Logger;
@@ -70,10 +74,15 @@ public class MongoDBClientSupport {
 
     private static final BasicBSONObject EMPTY_RESPONSE = new BasicBSONObject();
 
-    public MongoDBClientSupport(ServerAddress standalone, boolean usesAuthentication, String username, String password, String authenticationDatabase) {
+    public MongoDBClientSupport(ServerAddress standalone) {
+        address = standalone;
+        usesAuthentication = false;
+    }
+
+    public MongoDBClientSupport(ServerAddress standalone, String username, String password, String authenticationDatabase) {
         // We could also use a MongoClient to access an entire replica set. See MongoClient(List<ServerAddress>).
         address = standalone;
-        this.usesAuthentication = usesAuthentication;
+        this.usesAuthentication = true;
         this.username = username;
         this.password = password;
         this.authenticationDatabase = authenticationDatabase;
@@ -85,8 +94,12 @@ public class MongoDBClientSupport {
     public static MongoDBClientSupport forServer(AbstractMongoDBServer standalone) throws UnknownHostException {
         HostAndPort hostAndPort = BrooklynAccessUtils.getBrooklynAccessibleAddress(standalone, standalone.getAttribute(MongoDBServer.PORT));
         ServerAddress address = new ServerAddress(hostAndPort.getHostText(), hostAndPort.getPort());
-        return new MongoDBClientSupport(address, MongoDBAuthenticationUtils.usesAuthentication(standalone), standalone.sensors().get(MongoDBAuthenticationMixins.ROOT_USERNAME),
-                standalone.sensors().get(MongoDBAuthenticationMixins.ROOT_PASSWORD), standalone.sensors().get(MongoDBAuthenticationMixins.AUTHENTICATION_DATABASE));
+        if (MongoDBAuthenticationUtils.usesAuthentication(standalone)) {
+            return new MongoDBClientSupport(address, standalone.sensors().get(MongoDBAuthenticationMixins.ROOT_USERNAME),
+                    standalone.sensors().get(MongoDBAuthenticationMixins.ROOT_PASSWORD), standalone.sensors().get(MongoDBAuthenticationMixins.AUTHENTICATION_DATABASE));
+        } else {
+            return new MongoDBClientSupport(address);
+        }
     }
 
     private ServerAddress getServerAddress() {
@@ -107,28 +120,35 @@ public class MongoDBClientSupport {
         return runDBCommand(database, new BasicDBObject(command, Boolean.TRUE));
     }
 
-    private Optional<CommandResult> runDBCommand(String database, DBObject command) {
+    private Optional<CommandResult> runDBCommand(String database, final DBObject command) {
         MongoClient client = client();
         try {
-            DB db = client.getDB(database);
-            CommandResult status = null;
+            final DB db = client.getDB(database);
+            final CommandResult[] status = new CommandResult[1];
             // The mongoDB client can occasionally fail to connect. Try up to 5 times to run the command
-            for (int i = 0; i < 5; i++) {
-                try {
-                    status = db.command(command);
-                    break;
-                } catch (MongoException e) {
-                    LOG.warn("Command " + command + " on " + getServerAddress() + " failed", e);
-                    if (i == 4) {
-                        return Optional.absent();
-                    }
-                }
+            boolean commandResult = Repeater.create().backoff(Duration.ONE_SECOND, 1.5, null).limitIterationsTo(5)
+                    .until(new Callable<Boolean>() {
+                        @Override
+                        public Boolean call() throws Exception {
+                            try {
+                                status[0] = db.command(command);
+                                return true;
+                            } catch (Exception e) {
+                                LOG.warn("Command " + command + " on " + getServerAddress() + " failed", e);
+                                return false;
+                            }
+                        }
+            }).run();
+
+            if (!commandResult) {
+                return Optional.absent();
             }
-            if (!status.ok()) {
+
+            if (!status[0].ok()) {
                 LOG.debug("Unexpected result of {} on {}: {}",
-                        new Object[] { command, getServerAddress(), status.getErrorMessage() });
+                        new Object[] { command, getServerAddress(), status[0].getErrorMessage() });
             }
-            return Optional.of(status);
+            return Optional.of(status[0]);
         } finally {
             client.close();
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4bb730a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
index 046c716..f96a56a 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSetImpl.java
@@ -145,6 +145,7 @@ public class MongoDBReplicaSetImpl extends DynamicClusterImpl implements MongoDB
         EntitySpec<?> spec = config().get(MEMBER_SPEC);
         if (spec == null) {
             spec = EntitySpec.create(MongoDBServer.class);
+            config().set(MEMBER_SPEC, spec);
         }
         MongoDBAuthenticationUtils.setAuthenticationConfig(spec, this);
         return spec;
@@ -195,24 +196,28 @@ public class MongoDBReplicaSetImpl extends DynamicClusterImpl implements MongoDB
      * otherwise schedules the addition of a new secondary.
      */
     private void serverAdded(MongoDBServer server) {
-        LOG.debug("Server added: {}. SERVICE_UP: {}", server, server.getAttribute(MongoDBServer.SERVICE_UP));
-
-        // Set the primary if the replica set hasn't been initialised.
-        if (mustInitialise.compareAndSet(true, false)) {
-            if (LOG.isInfoEnabled())
-                LOG.info("First server up in {} is: {}", getName(), server);
-            boolean replicaSetInitialised = server.initializeReplicaSet(getName(), nextMemberId.getAndIncrement());
-            if (replicaSetInitialised) {
-                setAttribute(PRIMARY_ENTITY, server);
-                setAttribute(Startable.SERVICE_UP, true);
+        try {
+            LOG.debug("Server added: {}. SERVICE_UP: {}", server, server.getAttribute(MongoDBServer.SERVICE_UP));
+
+            // Set the primary if the replica set hasn't been initialised.
+            if (mustInitialise.compareAndSet(true, false)) {
+                if (LOG.isInfoEnabled())
+                    LOG.info("First server up in {} is: {}", getName(), server);
+                boolean replicaSetInitialised = server.initializeReplicaSet(getName(), nextMemberId.getAndIncrement());
+                if (replicaSetInitialised) {
+                    setAttribute(PRIMARY_ENTITY, server);
+                    setAttribute(Startable.SERVICE_UP, true);
+                } else {
+                    ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator(this, "initialization", "replicaset failed to initialize");
+                    ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE);
+                }
             } else {
-                ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator(this, "initialization", "replicaset failed to initialize");
-                ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE);
+                if (LOG.isDebugEnabled())
+                    LOG.debug("Scheduling addition of member to {}: {}", getName(), server);
+                addSecondaryWhenPrimaryIsNonNull(server);
             }
-        } else {
-            if (LOG.isDebugEnabled())
-                LOG.debug("Scheduling addition of member to {}: {}", getName(), server);
-            addSecondaryWhenPrimaryIsNonNull(server);
+        } catch (Exception e) {
+            ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator((EntityLocal)server, "Failed to update replicaset", e);
         }
     }
 
@@ -269,47 +274,51 @@ public class MongoDBReplicaSetImpl extends DynamicClusterImpl implements MongoDB
      * @param member The server to be removed from the replica set.
      */
     private void serverRemoved(final MongoDBServer member) {
-        if (LOG.isDebugEnabled())
-            LOG.debug("Scheduling removal of member from {}: {}", getName(), member);
-        // FIXME is there a chance of race here?
-        if (member.equals(getAttribute(PRIMARY_ENTITY)))
-            setAttribute(PRIMARY_ENTITY, null);
-        executor.submit(new Runnable() {
-            @Override
-            public void run() {
-                // Wait until the server has been stopped before reconfiguring the set. Quoth the MongoDB doc:
-                // for best results always shut down the mongod instance before removing it from a replica set.
-                Boolean isAvailable = member.getAttribute(MongoDBServer.SERVICE_UP);
-                // Wait for the replica set to elect a new primary if the set is reconfiguring itself.
-                MongoDBServer primary = getPrimary();
-                boolean reschedule;
-                
-                if (primary != null && !isAvailable) {
-                    boolean removed = primary.removeMemberFromReplicaSet(member);
-                    if (removed) {
-                        LOG.info("Removed {} from replica set {}", member, getName());
-                        reschedule = false;
+        try {
+            if (LOG.isDebugEnabled())
+                LOG.debug("Scheduling removal of member from {}: {}", getName(), member);
+            // FIXME is there a chance of race here?
+            if (member.equals(getAttribute(PRIMARY_ENTITY)))
+                setAttribute(PRIMARY_ENTITY, null);
+            executor.submit(new Runnable() {
+                @Override
+                public void run() {
+                    // Wait until the server has been stopped before reconfiguring the set. Quoth the MongoDB doc:
+                    // for best results always shut down the mongod instance before removing it from a replica set.
+                    Boolean isAvailable = member.getAttribute(MongoDBServer.SERVICE_UP);
+                    // Wait for the replica set to elect a new primary if the set is reconfiguring itself.
+                    MongoDBServer primary = getPrimary();
+                    boolean reschedule;
+
+                    if (primary != null && !isAvailable) {
+                        boolean removed = primary.removeMemberFromReplicaSet(member);
+                        if (removed) {
+                            LOG.info("Removed {} from replica set {}", member, getName());
+                            reschedule = false;
+                        } else {
+                            if (LOG.isDebugEnabled()) {
+                                LOG.debug("{} could not be removed from replica set via {}; rescheduling", member, getName());
+                            }
+                            reschedule = true;
+                        }
+
                     } else {
-                        if (LOG.isDebugEnabled()) {
-                            LOG.debug("{} could not be removed from replica set via {}; rescheduling", member, getName());
+                        if (LOG.isTraceEnabled()) {
+                            LOG.trace("Rescheduling removal of member {} from replica set {}: service_up={}, primary={}",
+                                    new Object[]{member, getName(), isAvailable, primary});
                         }
                         reschedule = true;
                     }
 
-                } else {
-                    if (LOG.isTraceEnabled()) {
-                        LOG.trace("Rescheduling removal of member {} from replica set {}: service_up={}, primary={}",
-                            new Object[]{member, getName(), isAvailable, primary});
+                    if (reschedule) {
+                        // TODO Could limit number of retries
+                        executor.schedule(this, 3, TimeUnit.SECONDS);
                     }
-                    reschedule = true;
-                }
-                
-                if (reschedule) {
-                    // TODO Could limit number of retries
-                    executor.schedule(this, 3, TimeUnit.SECONDS);
                 }
-            }
-        });
+            });
+        } catch (Exception e) {
+            ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator((EntityLocal)member, "Failed to update replicaset", e);
+        }
     }
 
     @Override
@@ -401,18 +410,10 @@ public class MongoDBReplicaSetImpl extends DynamicClusterImpl implements MongoDB
             // Ignored
         }
         @Override protected void onEntityAdded(Entity member) {
-            try {
-                ((MongoDBReplicaSetImpl) entity).serverAdded((MongoDBServer) member);
-            } catch (Exception e) {
-                ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator((EntityLocal)member, "Failed to update replicaset", e);
-            }
+            ((MongoDBReplicaSetImpl) entity).serverAdded((MongoDBServer) member);
         }
         @Override protected void onEntityRemoved(Entity member) {
-            try {
-                ((MongoDBReplicaSetImpl) entity).serverRemoved((MongoDBServer) member);
-            } catch (Exception e) {
-                ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator((EntityLocal)member, "Failed to update replicaset", e);
-            }
+            ((MongoDBReplicaSetImpl) entity).serverRemoved((MongoDBServer) member);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4bb730a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/ReplicaSetConfig.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/ReplicaSetConfig.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/ReplicaSetConfig.java
index 9da870e..9ea240b 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/ReplicaSetConfig.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/ReplicaSetConfig.java
@@ -148,10 +148,6 @@ public class ReplicaSetConfig {
         BasicBSONObject member = new BasicBSONObject();
         member.put("_id", id);
         member.put("host", String.format("%s:%s", hostname, port));
-        if (members.contains(member)) {
-            LOG.warn("Ignoring attempt to add entity to a set of which it is already a member");
-            return this;
-        }
         members.add(member);
         return this;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4bb730a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/CoLocatedMongoDBRouterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/CoLocatedMongoDBRouterImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/CoLocatedMongoDBRouterImpl.java
index 0c81de2..f96b517 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/CoLocatedMongoDBRouterImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/CoLocatedMongoDBRouterImpl.java
@@ -19,7 +19,6 @@
 package org.apache.brooklyn.entity.nosql.mongodb.sharding;
 
 import java.util.Collection;
-import java.util.concurrent.ExecutionException;
 
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.location.Location;
@@ -32,61 +31,42 @@ import org.apache.brooklyn.entity.group.AbstractGroup;
 import org.apache.brooklyn.entity.nosql.mongodb.MongoDBAuthenticationMixins;
 import org.apache.brooklyn.entity.nosql.mongodb.MongoDBAuthenticationUtils;
 import org.apache.brooklyn.entity.software.base.SameServerEntityImpl;
-import org.apache.brooklyn.util.exceptions.Exceptions;
-
-import com.google.common.base.Predicates;
-import com.google.common.collect.Iterables;
 
 public class CoLocatedMongoDBRouterImpl extends SameServerEntityImpl implements CoLocatedMongoDBRouter, MongoDBAuthenticationMixins {
 
-    private MongoDBRouter router;
-
     @Override
     public void init() {
         super.init();
-        router = addChild(EntitySpec.create(MongoDBRouter.class)
+        MongoDBRouter router = addChild(EntitySpec.create(MongoDBRouter.class)
                 .configure(MongoDBRouter.CONFIG_SERVERS,
                         DependentConfiguration.attributeWhenReady(
                                 getConfig(CoLocatedMongoDBRouter.SHARDED_DEPLOYMENT),
                                 MongoDBConfigServerCluster.CONFIG_SERVER_ADDRESSES)));
+
         for (EntitySpec<?> siblingSpec : getConfig(CoLocatedMongoDBRouter.SIBLING_SPECS)) {
             addChild(siblingSpec);
         }
-        sensors().set(ROUTER, (MongoDBRouter) Iterables.tryFind(getChildren(), Predicates.instanceOf(MongoDBRouter.class)).get());
+        sensors().set(ROUTER, router);
     }
 
     @Override
     protected void doStart(Collection<? extends Location> locations) {
+        MongoDBRouter router = sensors().get(ROUTER);
 
-        // TODO Changed to create the router child after init as a workaround.
-        // When we use `mongo-sharded.yaml`, and we call
-        // `getConfig(CoLocatedMongoDBRouter.SHARDED_DEPLOYMENT)`,
-        // the value is `$brooklyn:component("shardeddeployment")`.
-        // To look up the component, it tries to do `entity().getApplication()` to
-        // search the entities for one with the correct id. However if being done
-        // during `init()`, then this (which is returned by `entity()`) has not had its parent
-        // set, so `entity().getApplication()` returns null.
-        //
-        // We should move this code back to `init()` once we have a solution for that.
-        // We can also remove the call to Entities.manage() once this is in init() again.
+        // Do not attempt to read the configuration until after the router has been added to the cluster
+        // as it is at this point that the authentication configuration is set
+        Task<?> clusterTask = DependentConfiguration.attributeWhenReady(router, AbstractGroup.FIRST);
+        Entities.submit(this, clusterTask);
+        clusterTask.getUnchecked();
 
-        try {
-            // Do not attempt to read the configuration until after the router has been added to the cluster
-            // as it is at this point that the authentication configuration is set
-            Task<?> clusterTask = DependentConfiguration.attributeWhenReady(router, AbstractGroup.FIRST);
-            Entities.submit(this, clusterTask);
-            clusterTask.get();
-        } catch (Exception e) {
-            Exceptions.propagateIfFatal(e);
-        }
         MongoDBAuthenticationUtils.setAuthenticationConfig(router, this);
         router.sensors().set(MongoDBAuthenticationMixins.ROOT_PASSWORD, router.config().get(MongoDBAuthenticationMixins.ROOT_PASSWORD));
         router.sensors().set(MongoDBAuthenticationMixins.ROOT_USERNAME, router.config().get(MongoDBAuthenticationMixins.ROOT_USERNAME));
         router.sensors().set(MongoDBAuthenticationMixins.AUTHENTICATION_DATABASE, router.config().get(MongoDBAuthenticationMixins.AUTHENTICATION_DATABASE));
-        Entities.manage(router);
         addEnricher(Enrichers.builder().propagating(MongoDBRouter.PORT).from(router).build());
         
         super.doStart(locations);
         sensors().set(Startable.SERVICE_UP, true);
     }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4bb730a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBRouterSshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBRouterSshDriver.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBRouterSshDriver.java
index df73868..816906d 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBRouterSshDriver.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBRouterSshDriver.java
@@ -48,8 +48,4 @@ public class MongoDBRouterSshDriver extends AbstractMongoDBSshDriver implements
                 .body.append(command).execute();
     }
 
-    @Override
-    public boolean isRunning() {
-        return super.isRunning();
-    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4bb730a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
index 198e787..5cc217a 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
@@ -82,7 +82,6 @@ public class MongoDBShardedDeploymentImpl extends AbstractEntity implements Mong
         // Advertise even if default are used (root password is set in MongoDBAuthenticationUtils)
         sensors().set(MongoDBAuthenticationMixins.AUTHENTICATION_DATABASE, config().get(MongoDBAuthenticationMixins.AUTHENTICATION_DATABASE));
         sensors().set(MongoDBAuthenticationMixins.ROOT_USERNAME, config().get(MongoDBAuthenticationMixins.ROOT_USERNAME));
-        sensors().set(MongoDBAuthenticationMixins.MONGODB_KEYFILE_DESTINATION, config().get(MongoDBAuthenticationMixins.MONGODB_KEYFILE_CONTENTS));
 
         ServiceNotUpLogic.updateNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL, "stopped");
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d4bb730a/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommands.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommands.java b/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommands.java
index e91d60c..dc75c3a 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommands.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommands.java
@@ -619,17 +619,15 @@ public class BashCommands {
 
     /** cats the given text to the given command, using bash << multi-line input syntax */
     public static String pipeTextTo(String text, String command) {
-        String id = Identifiers.makeRandomId(8);
-        return "cat << EOF_"+id+" | "+command+"\n"
+        return "cat << EOL_BROOKLYN | "+command+"\n"
                 +text
-                +"\n"+"EOF_"+id+"\n";
+                +"\n"+"EOL_BROOKLYN\n";
     }
 
     public static String pipeTextToFile(String text, String filepath) {
-        String id = Identifiers.makeRandomId(8);
-        return "cat > " + filepath + " << EOL_" + id + "\n"
-                + text
-                + "EOL_" + id + "\n";
+        return "cat > \"" + filepath + "\" << EOF_BROOKLYN\n"
+                + text + "\n"
+                + "EOF_BROOKLYN\n";
     }
 
     public static String prependToEtcHosts(String ip, String... hostnames) {


[8/9] incubator-brooklyn git commit: Set MongoDB driver logging to WARN

Posted by sj...@apache.org.
Set MongoDB driver logging to WARN


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

Branch: refs/heads/master
Commit: ec1d33f79e353adf640df1adccb4bcf3916702cb
Parents: d62ed2f
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Wed Sep 16 11:51:38 2015 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed Sep 16 11:51:38 2015 +0100

----------------------------------------------------------------------
 .../src/main/resources/brooklyn/logback-logger-excludes.xml   | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ec1d33f7/usage/logback-includes/src/main/resources/brooklyn/logback-logger-excludes.xml
----------------------------------------------------------------------
diff --git a/usage/logback-includes/src/main/resources/brooklyn/logback-logger-excludes.xml b/usage/logback-includes/src/main/resources/brooklyn/logback-logger-excludes.xml
index 3416264..9f8738b 100644
--- a/usage/logback-includes/src/main/resources/brooklyn/logback-logger-excludes.xml
+++ b/usage/logback-includes/src/main/resources/brooklyn/logback-logger-excludes.xml
@@ -55,5 +55,10 @@
 		<!-- Wordnik logs errors in a few places which aren't errors at all; ignore them altogether (not even to a file, because it makes lots of ERROR lines).
 		     (Turn them back on if you need to see how API-doc gets generated, and also see https://github.com/wordnik/swagger-core/issues/58) -->
 	</logger>
-	
+
+    <!-- The MongoDB Java driver is much too noisy at INFO. -->
+    <logger name="org.mongodb.driver" level="WARN" additivity="false">
+        <appender-ref ref="FILE" />
+    </logger>
+
 </included>