You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2015/10/21 14:11:58 UTC
[1/3] incubator-brooklyn git commit: Adds
MutableSet.Builder.addIfNotNull
Repository: incubator-brooklyn
Updated Branches:
refs/heads/master ee29db530 -> 61b5d7052
Adds MutableSet.Builder.addIfNotNull
- And adds MutableList.Builder.addIfNotNull
- Adds MutableSetTest
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/ddfb6e29
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/ddfb6e29
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/ddfb6e29
Branch: refs/heads/master
Commit: ddfb6e29a3df314ab4bc6c4aeefded6d61a4486d
Parents: f29b3fb
Author: Aled Sage <al...@gmail.com>
Authored: Tue Oct 20 21:35:35 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Tue Oct 20 21:37:50 2015 +0100
----------------------------------------------------------------------
.../brooklyn/util/collections/MutableList.java | 5 +
.../brooklyn/util/collections/MutableSet.java | 5 +
.../util/collections/MutableListTest.java | 6 +-
.../util/collections/MutableSetTest.java | 123 +++++++++++++++++++
4 files changed, 138 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddfb6e29/utils/common/src/main/java/org/apache/brooklyn/util/collections/MutableList.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/collections/MutableList.java b/utils/common/src/main/java/org/apache/brooklyn/util/collections/MutableList.java
index 4f8206a..9aa3a99 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/collections/MutableList.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/collections/MutableList.java
@@ -118,6 +118,11 @@ public class MutableList<V> extends ArrayList<V> {
public Builder() {}
+ public Builder<V> addIfNotNull(V value) {
+ if (value != null) result.add(value);
+ return this;
+ }
+
public Builder<V> add(V value) {
result.add(value);
return this;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddfb6e29/utils/common/src/main/java/org/apache/brooklyn/util/collections/MutableSet.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/collections/MutableSet.java b/utils/common/src/main/java/org/apache/brooklyn/util/collections/MutableSet.java
index f851305..af7f0fb 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/collections/MutableSet.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/collections/MutableSet.java
@@ -118,6 +118,11 @@ public class MutableSet<V> extends LinkedHashSet<V> {
public Builder() {}
+ public Builder<V> addIfNotNull(V value) {
+ if (value != null) result.add(value);
+ return this;
+ }
+
public Builder<V> add(V value) {
result.add(value);
return this;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddfb6e29/utils/common/src/test/java/org/apache/brooklyn/util/collections/MutableListTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/collections/MutableListTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/collections/MutableListTest.java
index 5d3a140..046d434 100644
--- a/utils/common/src/test/java/org/apache/brooklyn/util/collections/MutableListTest.java
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/collections/MutableListTest.java
@@ -21,7 +21,6 @@ package org.apache.brooklyn.util.collections;
import java.util.Arrays;
import java.util.List;
-import org.apache.brooklyn.util.collections.MutableList;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -40,6 +39,11 @@ public class MutableListTest {
Assert.assertEquals(vals, ImmutableList.of(1,2,3));
}
+ public void testBuilderAddIfNotNull() throws Exception {
+ List<Object> vals = MutableList.builder().addIfNotNull(1).addIfNotNull(null).build();
+ Assert.assertEquals(vals, ImmutableList.of(1));
+ }
+
public void testBuilderAddIterable() throws Exception {
List<Object> vals = MutableList.builder().addAll(ImmutableList.of(1,2)).addAll(ImmutableList.of(2,3)).build();
Assert.assertEquals(vals, ImmutableList.of(1,2,2,3));
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddfb6e29/utils/common/src/test/java/org/apache/brooklyn/util/collections/MutableSetTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/collections/MutableSetTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/collections/MutableSetTest.java
new file mode 100644
index 0000000..0e14464
--- /dev/null
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/collections/MutableSetTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.util.collections;
+
+import java.util.Set;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+@Test
+public class MutableSetTest {
+
+ public void testBuilderAddArray() throws Exception {
+ Set<Object> vals = MutableSet.builder().addAll(new Object[] {1,2,3}).build();
+ Assert.assertEquals(vals, ImmutableSet.of(1,2,3));
+ }
+
+ public void testBuilderAddVarargs() throws Exception {
+ Set<Object> vals = MutableSet.builder().add(1,2,3).build();
+ Assert.assertEquals(vals, ImmutableSet.of(1,2,3));
+ }
+
+ public void testBuilderAddIfNotNull() throws Exception {
+ Set<Object> vals = MutableSet.builder().addIfNotNull(1).addIfNotNull(null).build();
+ Assert.assertEquals(vals, ImmutableSet.of(1));
+ }
+
+ public void testBuilderAddIterable() throws Exception {
+ Set<Object> vals = MutableSet.builder().addAll(ImmutableSet.of(1,2)).addAll(ImmutableSet.of(2,3)).build();
+ Assert.assertEquals(vals, ImmutableSet.of(1,2,3));
+ }
+
+ public void testBuilderAddIterator() throws Exception {
+ Set<Object> vals = MutableSet.builder().addAll(ImmutableSet.of(1,2).iterator()).build();
+ Assert.assertEquals(vals, ImmutableSet.of(1,2));
+ }
+
+ public void testBuilderRemoval() throws Exception {
+ Set<Object> vals = MutableSet.builder()
+ .add(1,2,3)
+ .remove(2)
+ .add(4)
+ .build();
+ Assert.assertEquals(vals, ImmutableSet.of(1,3,4));
+ }
+
+ public void testBuilderRemoveAll() throws Exception {
+ Set<Object> vals = MutableSet.builder()
+ .add(1,2,3)
+ .removeAll(ImmutableSet.of(2,3))
+ .add(4)
+ .build();
+ Assert.assertEquals(vals, ImmutableSet.of(1,4));
+ }
+
+ public void testEqualsExact() {
+ Set<Object> a = MutableSet.<Object>of("a", 1, "b", false);
+ Set<Object> b = MutableSet.<Object>of("a", 1, "b", false);
+ Assert.assertEquals(a, b);
+ }
+
+ public void testEqualsUnordered() {
+ Set<Object> a = MutableSet.<Object>of("a", 1, "b", false);
+ Set<Object> b = MutableSet.<Object>of("b", false, "a", 1);
+ Assert.assertEquals(a, b);
+ }
+
+ public void testEqualsDifferentTypes() {
+ Set<?> a = MutableSet.<Object>of("a", 1, "b", false);
+ Set<?> b = ImmutableSet.of("a", 1, "b", false);
+ Assert.assertEquals(a, b);
+ Assert.assertEquals(b, a);
+ }
+
+ public void testEqualsDifferentTypes2() {
+ Set<Object> a = MutableSet.<Object>of("http");
+ Set<?> b = ImmutableSet.of("http");
+ Assert.assertEquals(a, b);
+ Assert.assertEquals(b, a);
+ }
+
+ public void testContainingNullAndUnmodifiable() {
+ MutableSet<Object> x = MutableSet.<Object>of("x", null);
+ Assert.assertTrue(x.contains(null));
+
+ Set<Object> x1 = x.asUnmodifiable();
+ Set<Object> x2 = x.asUnmodifiableCopy();
+ Set<Object> x3 = x.asImmutableCopy();
+
+ x.remove(null);
+ Assert.assertFalse(x.contains(null));
+ Assert.assertFalse(x1.contains(null));
+ Assert.assertTrue(x2.contains(null));
+ Assert.assertTrue(x3.contains(null));
+
+ try { x1.remove("x"); Assert.fail(); } catch (Exception e) { /* expected */ }
+ try { x2.remove("x"); Assert.fail(); } catch (Exception e) { /* expected */ }
+ try { x3.remove("x"); Assert.fail(); } catch (Exception e) { /* expected */ }
+
+ Assert.assertTrue(x1.contains("x"));
+ Assert.assertTrue(x2.contains("x"));
+ Assert.assertTrue(x3.contains("x"));
+ }
+
+}
[3/3] incubator-brooklyn git commit: This closes #977
Posted by al...@apache.org.
This closes #977
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/61b5d705
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/61b5d705
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/61b5d705
Branch: refs/heads/master
Commit: 61b5d7052caadb89b543866b2bbe89643ee3c617
Parents: ee29db5 6ca7e26
Author: Aled Sage <al...@gmail.com>
Authored: Wed Oct 21 13:11:45 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Oct 21 13:11:45 2015 +0100
----------------------------------------------------------------------
.../location/jclouds/JcloudsLocation.java | 224 +++++++++++--------
.../JcloudsLocationSecurityGroupCustomizer.java | 23 +-
.../brooklyn/util/collections/MutableList.java | 5 +
.../brooklyn/util/collections/MutableSet.java | 5 +
.../util/collections/MutableListTest.java | 6 +-
.../util/collections/MutableSetTest.java | 123 ++++++++++
6 files changed, 292 insertions(+), 94 deletions(-)
----------------------------------------------------------------------
[2/3] incubator-brooklyn git commit: BROOKLYN-186 workaround in
JcloudsLocation
Posted by al...@apache.org.
BROOKLYN-186 workaround in JcloudsLocation
If we get back a node with both a password and ssh key, and/or
if that node has a different user from the overridden loginUser,
then try all combinations of those credentials to try to login.
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/6ca7e267
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/6ca7e267
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/6ca7e267
Branch: refs/heads/master
Commit: 6ca7e26748e69365fe2d4d2d5231a3406197f877
Parents: ddfb6e2
Author: Aled Sage <al...@gmail.com>
Authored: Wed Oct 14 12:19:07 2015 +0200
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Oct 21 00:51:15 2015 +0100
----------------------------------------------------------------------
.../location/jclouds/JcloudsLocation.java | 224 +++++++++++--------
.../JcloudsLocationSecurityGroupCustomizer.java | 23 +-
2 files changed, 154 insertions(+), 93 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ca7e267/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
index 9a812b2..0705d26 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
@@ -23,8 +23,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.brooklyn.util.JavaGroovyEquivalents.elvis;
import static org.apache.brooklyn.util.JavaGroovyEquivalents.groovyTruth;
-import static org.jclouds.compute.options.RunScriptOptions.Builder.overrideLoginCredentials;
-import static org.jclouds.scriptbuilder.domain.Statements.exec;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -45,6 +43,7 @@ import java.util.concurrent.Callable;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -75,15 +74,52 @@ import org.apache.brooklyn.core.location.cloud.names.CloudMachineNamer;
import org.apache.brooklyn.core.mgmt.persist.LocationWithObjectStore;
import org.apache.brooklyn.core.mgmt.persist.PersistenceObjectStore;
import org.apache.brooklyn.core.mgmt.persist.jclouds.JcloudsBlobStoreBasedObjectStore;
+import org.apache.brooklyn.location.jclouds.JcloudsPredicates.NodeInLocation;
import org.apache.brooklyn.location.jclouds.networking.JcloudsPortForwarderExtension;
+import org.apache.brooklyn.location.jclouds.templates.PortableTemplateBuilder;
import org.apache.brooklyn.location.jclouds.zone.AwsAvailabilityZoneExtension;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.location.winrm.WinRmMachineLocation;
+import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.collections.MutableSet;
+import org.apache.brooklyn.util.core.ResourceUtils;
+import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.core.crypto.SecureKeys;
+import org.apache.brooklyn.util.core.flags.MethodCoercions;
+import org.apache.brooklyn.util.core.flags.SetFromFlag;
+import org.apache.brooklyn.util.core.flags.TypeCoercions;
+import org.apache.brooklyn.util.core.internal.ssh.ShellTool;
+import org.apache.brooklyn.util.core.internal.ssh.SshTool;
+import org.apache.brooklyn.util.core.text.TemplateProcessor;
+import org.apache.brooklyn.util.exceptions.CompoundRuntimeException;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.exceptions.ReferenceWithError;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.javalang.Enums;
+import org.apache.brooklyn.util.javalang.Reflections;
+import org.apache.brooklyn.util.net.Cidr;
+import org.apache.brooklyn.util.net.Networking;
+import org.apache.brooklyn.util.net.Protocol;
+import org.apache.brooklyn.util.os.Os;
+import org.apache.brooklyn.util.repeat.Repeater;
+import org.apache.brooklyn.util.ssh.BashCommands;
+import org.apache.brooklyn.util.ssh.IptablesCommands;
+import org.apache.brooklyn.util.ssh.IptablesCommands.Chain;
+import org.apache.brooklyn.util.ssh.IptablesCommands.Policy;
+import org.apache.brooklyn.util.stream.Streams;
+import org.apache.brooklyn.util.text.ByteSizeStrings;
+import org.apache.brooklyn.util.text.Identifiers;
+import org.apache.brooklyn.util.text.KeyValueParser;
+import org.apache.brooklyn.util.text.Strings;
+import org.apache.brooklyn.util.time.Duration;
+import org.apache.brooklyn.util.time.Time;
import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.config.AdminAccessConfiguration;
import org.jclouds.compute.domain.ComputeMetadata;
-import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
@@ -106,7 +142,6 @@ import org.jclouds.rest.AuthorizationException;
import org.jclouds.scriptbuilder.domain.LiteralStatement;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.domain.StatementList;
-import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.scriptbuilder.functions.InitAdminAccess;
import org.jclouds.scriptbuilder.statements.login.AdminAccess;
import org.jclouds.scriptbuilder.statements.login.ReplaceShadowPasswordEntry;
@@ -140,45 +175,6 @@ import com.google.common.io.Files;
import com.google.common.net.HostAndPort;
import com.google.common.primitives.Ints;
-import org.apache.brooklyn.location.jclouds.JcloudsPredicates.NodeInLocation;
-import org.apache.brooklyn.location.jclouds.templates.PortableTemplateBuilder;
-import org.apache.brooklyn.location.ssh.SshMachineLocation;
-import org.apache.brooklyn.location.winrm.WinRmMachineLocation;
-import org.apache.brooklyn.util.collections.MutableList;
-import org.apache.brooklyn.util.collections.MutableMap;
-import org.apache.brooklyn.util.collections.MutableSet;
-import org.apache.brooklyn.util.core.ResourceUtils;
-import org.apache.brooklyn.util.core.config.ConfigBag;
-import org.apache.brooklyn.util.core.crypto.SecureKeys;
-import org.apache.brooklyn.util.core.flags.MethodCoercions;
-import org.apache.brooklyn.util.core.flags.SetFromFlag;
-import org.apache.brooklyn.util.core.flags.TypeCoercions;
-import org.apache.brooklyn.util.core.internal.ssh.ShellTool;
-import org.apache.brooklyn.util.core.internal.ssh.SshTool;
-import org.apache.brooklyn.util.core.text.TemplateProcessor;
-import org.apache.brooklyn.util.exceptions.CompoundRuntimeException;
-import org.apache.brooklyn.util.exceptions.Exceptions;
-import org.apache.brooklyn.util.exceptions.ReferenceWithError;
-import org.apache.brooklyn.util.guava.Maybe;
-import org.apache.brooklyn.util.javalang.Enums;
-import org.apache.brooklyn.util.javalang.Reflections;
-import org.apache.brooklyn.util.net.Cidr;
-import org.apache.brooklyn.util.net.Networking;
-import org.apache.brooklyn.util.net.Protocol;
-import org.apache.brooklyn.util.os.Os;
-import org.apache.brooklyn.util.repeat.Repeater;
-import org.apache.brooklyn.util.ssh.BashCommands;
-import org.apache.brooklyn.util.ssh.IptablesCommands;
-import org.apache.brooklyn.util.ssh.IptablesCommands.Chain;
-import org.apache.brooklyn.util.ssh.IptablesCommands.Policy;
-import org.apache.brooklyn.util.stream.Streams;
-import org.apache.brooklyn.util.text.ByteSizeStrings;
-import org.apache.brooklyn.util.text.Identifiers;
-import org.apache.brooklyn.util.text.KeyValueParser;
-import org.apache.brooklyn.util.text.Strings;
-import org.apache.brooklyn.util.time.Duration;
-import org.apache.brooklyn.util.time.Time;
-
import io.cloudsoft.winrm4j.pywinrm.Session;
import io.cloudsoft.winrm4j.pywinrm.WinRMFactory;
@@ -749,16 +745,17 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
sshHostAndPortOverride = Optional.absent();
}
+ LoginCredentials initialCredentials = node.getCredentials();
if (skipJcloudsSshing) {
boolean waitForConnectable = (windows) ? waitForWinRmable : waitForSshable;
if (waitForConnectable) {
if (windows) {
// TODO Does jclouds support any windows user setup?
- waitForWinRmAvailable(computeService, node, sshHostAndPortOverride, node.getCredentials(), setup);
+ initialCredentials = waitForWinRmAvailable(computeService, node, sshHostAndPortOverride, setup);
} else {
- waitForSshable(computeService, node, sshHostAndPortOverride, node.getCredentials(), setup);
+ initialCredentials = waitForSshable(computeService, node, sshHostAndPortOverride, setup);
}
- userCredentials = createUser(computeService, node, sshHostAndPortOverride, setup);
+ userCredentials = createUser(computeService, node, sshHostAndPortOverride, initialCredentials, setup);
}
}
@@ -773,7 +770,8 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
if (customCredentials.getOptionalPrivateKey().isPresent()) setup.put(PRIVATE_KEY_DATA, customCredentials.getOptionalPrivateKey().get());
}
if (userCredentials == null) {
- userCredentials = extractVmCredentials(setup, node);
+ // TODO See waitForSshable, which now handles if the node.getLoginCredentials has both a password+key
+ userCredentials = extractVmCredentials(setup, node, initialCredentials);
}
if (userCredentials != null) {
node = NodeMetadataBuilder.fromNodeMetadata(node).credentials(userCredentials).build();
@@ -787,7 +785,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
// Wait for the VM to be reachable over SSH
if (waitForSshable && !windows) {
- waitForSshable(computeService, node, sshHostAndPortOverride, userCredentials, setup);
+ waitForSshable(computeService, node, sshHostAndPortOverride, ImmutableList.of(userCredentials), setup);
} else {
LOG.debug("Skipping ssh check for {} ({}) due to config waitForSshable=false", node, setup.getDescription());
}
@@ -1575,7 +1573,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
/**
* Create the user immediately - executing ssh commands as required.
*/
- protected LoginCredentials createUser(ComputeService computeService, NodeMetadata node, Optional<HostAndPort> hostAndPortOverride, ConfigBag config) {
+ protected LoginCredentials createUser(ComputeService computeService, NodeMetadata node, Optional<HostAndPort> hostAndPortOverride, LoginCredentials initialCredentials, ConfigBag config) {
Image image = (node.getImageId() != null) ? computeService.getImage(node.getImageId()) : null;
UserCreation userCreation = createUserStatements(image, config);
@@ -1601,7 +1599,6 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
commands.add(statement.render(scriptOsFamily));
}
- LoginCredentials initialCredentials = node.getCredentials();
Optional<String> initialPassword = initialCredentials.getOptionalPassword();
Optional<String> initialPrivateKey = initialCredentials.getOptionalPrivateKey();
String initialUser = initialCredentials.getUser();
@@ -2433,10 +2430,9 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
/**
* Extracts the user that jclouds tells us about (i.e. from the jclouds node).
*/
- protected LoginCredentials extractVmCredentials(ConfigBag setup, NodeMetadata node) {
+ protected LoginCredentials extractVmCredentials(ConfigBag setup, NodeMetadata node, LoginCredentials nodeCredentials) {
String user = getUser(setup);
OsCredential localCredentials = LocationConfigUtils.getOsCredential(setup).checkNoErrors();
- LoginCredentials nodeCredentials = LoginCredentials.fromCredentials(node.getCredentials());
LOG.debug("Credentials extracted for {}: {}/{} with {}/{}", new Object[] { node,
user, nodeCredentials.getUser(), localCredentials, nodeCredentials });
@@ -2470,7 +2466,11 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
return null;
}
- protected void waitForWinRmAvailable(final ComputeService computeService, final NodeMetadata node, Optional<HostAndPort> hostAndPortOverride, final LoginCredentials expectedCredentials, ConfigBag setup) {
+ protected LoginCredentials waitForWinRmAvailable(final ComputeService computeService, final NodeMetadata node, Optional<HostAndPort> hostAndPortOverride, ConfigBag setup) {
+ return waitForWinRmAvailable(computeService, node, hostAndPortOverride, node.getCredentials(), setup);
+ }
+
+ protected LoginCredentials waitForWinRmAvailable(final ComputeService computeService, final NodeMetadata node, Optional<HostAndPort> hostAndPortOverride, LoginCredentials expectedCredentials, ConfigBag setup) {
String waitForWinrmAvailable = setup.get(WAIT_FOR_WINRM_AVAILABLE);
checkArgument(!"false".equalsIgnoreCase(waitForWinrmAvailable), "waitForWinRmAvailable called despite waitForWinRmAvailable=%s", waitForWinrmAvailable);
Duration timeout = null;
@@ -2506,12 +2506,37 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
}};
String connectionDetails = user + "@" + vmIp + ":" + vmPort;
- waitForReachable(checker, connectionDetails, expectedCredentials, setup, timeout);
+ waitForReachable(checker, connectionDetails, ImmutableList.of(expectedCredentials), setup, timeout);
+
+ return expectedCredentials;
}
- protected void waitForSshable(final ComputeService computeService, final NodeMetadata node, Optional<HostAndPort> hostAndPortOverride, final LoginCredentials expectedCredentials, ConfigBag setup) {
+ protected LoginCredentials waitForSshable(final ComputeService computeService, final NodeMetadata node, Optional<HostAndPort> hostAndPortOverride, ConfigBag setup) {
+ LoginCredentials nodeCreds = node.getCredentials();
+ String nodeUser = nodeCreds.getUser();
+ String loginUserOverride = setup.get(LOGIN_USER);
+ Set<String> users = MutableSet.<String>builder().add(nodeUser).add(loginUserOverride).build();
+
+ // See https://issues.apache.org/jira/browse/BROOKLYN-186
+ // Handle where jclouds gives us the wrong login user (!) and both a password + ssh key.
+ // Try all the permutations to find the one that works.
+ List<LoginCredentials> credentialsToTry = Lists.newArrayList();
+ for (String user : users) {
+ if (nodeCreds.getOptionalPassword().isPresent() && nodeCreds.getOptionalPrivateKey().isPresent()) {
+ credentialsToTry.add(LoginCredentials.builder(nodeCreds).noPassword().user(user).build());
+ credentialsToTry.add(LoginCredentials.builder(nodeCreds).noPrivateKey().user(user).build());
+ } else {
+ credentialsToTry.add(LoginCredentials.builder(nodeCreds).user(user).build());
+ }
+ }
+
+ return waitForSshable(computeService, node, hostAndPortOverride, credentialsToTry, setup);
+ }
+
+ protected LoginCredentials waitForSshable(final ComputeService computeService, final NodeMetadata node, Optional<HostAndPort> hostAndPortOverride, List<LoginCredentials> credentialsToTry, ConfigBag setup) {
String waitForSshable = setup.get(WAIT_FOR_SSHABLE);
- checkArgument(!"false".equalsIgnoreCase(waitForSshable), "waitForReachable called despite waitForSshable=%s", waitForSshable);
+ checkArgument(!"false".equalsIgnoreCase(waitForSshable), "waitForReachable called despite waitForSshable=%s for %s", waitForSshable, node);
+ checkArgument(credentialsToTry.size() > 0, "waitForReachable called without credentials for %s", node);
Duration timeout = null;
try {
@@ -2523,53 +2548,68 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
timeout = Duration.parse(WAIT_FOR_SSHABLE.getDefaultValue());
}
- String user = expectedCredentials.getUser();
+ Set<String> users = Sets.newLinkedHashSet();
+ for (LoginCredentials creds : credentialsToTry) {
+ users.add(creds.getUser());
+ }
+ String user = (users.size() == 1) ? Iterables.getOnlyElement(users) : "{" + Joiner.on(",").join(users) + "}";
String vmIp = hostAndPortOverride.isPresent() ? hostAndPortOverride.get().getHostText() : JcloudsUtil.getFirstReachableAddress(computeService.getContext(), node);
if (vmIp==null) LOG.warn("Unable to extract IP for "+node+" ("+setup.getDescription()+"): subsequent connection attempt will likely fail");
int vmPort = hostAndPortOverride.isPresent() ? hostAndPortOverride.get().getPortOrDefault(22) : 22;
String connectionDetails = user + "@" + vmIp + ":" + vmPort;
-
- Callable<Boolean> checker;
- if (hostAndPortOverride.isPresent()) {
- final SshMachineLocation machine = createTemporarySshMachineLocation(hostAndPortOverride.get(), expectedCredentials, setup);
- checker = new Callable<Boolean>() {
- public Boolean call() {
- int exitstatus = machine.execScript("check-connectivity", ImmutableList.of("hostname"));
- return exitstatus == 0;
- }};
- } else {
- checker = new Callable<Boolean>() {
- public Boolean call() {
- Statement statement = Statements.newStatementList(exec("hostname"));
- ExecResponse response = computeService.runScriptOnNode(node.getId(), statement,
- overrideLoginCredentials(expectedCredentials).runAsRoot(false));
- return response.getExitStatus() == 0;
- }};
+ final HostAndPort hostAndPort = hostAndPortOverride.isPresent() ? hostAndPortOverride.get() : HostAndPort.fromParts(vmIp, vmPort);
+ final AtomicReference<LoginCredentials> credsSuccessful = new AtomicReference<LoginCredentials>();
+
+ final Map<SshMachineLocation, LoginCredentials> machinesToTry = Maps.newLinkedHashMap();
+ for (LoginCredentials creds : credentialsToTry) {
+ machinesToTry.put(createTemporarySshMachineLocation(hostAndPort, creds, setup), creds);
}
+ Callable<Boolean> checker = new Callable<Boolean>() {
+ public Boolean call() {
+ for (Map.Entry<SshMachineLocation, LoginCredentials> entry : machinesToTry.entrySet()) {
+ SshMachineLocation machine = entry.getKey();
+ int exitstatus = machine.execScript(
+ ImmutableMap.of(
+ SshTool.PROP_SSH_TRIES_TIMEOUT.getName(), Duration.THIRTY_SECONDS.toMilliseconds(),
+ SshTool.PROP_SSH_TRIES.getName(), 1),
+ "check-connectivity",
+ ImmutableList.of("true"));
+ boolean success = (exitstatus == 0);
+ if (success) {
+ credsSuccessful.set(entry.getValue());
+ return true;
+ }
+ }
+ return false;
+ }};
- waitForReachable(checker, connectionDetails, expectedCredentials, setup, timeout);
+ waitForReachable(checker, connectionDetails, credentialsToTry, setup, timeout);
+ return credsSuccessful.get();
}
- protected void waitForReachable(Callable<Boolean> checker, String connectionDetails, LoginCredentials expectedCredentials, ConfigBag setup, Duration timeout) {
- String user = expectedCredentials.getUser();
+ protected void waitForReachable(Callable<Boolean> checker, String hostAndPort, List<LoginCredentials> credentialsToLog, ConfigBag setup, Duration timeout) {
if (LOG.isDebugEnabled()) {
- Optional<String> password;
- Optional<String> key;
- if (Boolean.TRUE.equals(setup.get(LOG_CREDENTIALS))) {
- password = expectedCredentials.getOptionalPassword();
- key = expectedCredentials.getOptionalPrivateKey();
- } else {
- password = expectedCredentials.getOptionalPassword().isPresent() ? Optional.of("******") : Optional.<String>absent();
- key = expectedCredentials.getOptionalPrivateKey().isPresent() ? Optional.of("******") : Optional.<String>absent();
+ List<String> credsToString = Lists.newArrayList();
+ for (LoginCredentials creds : credentialsToLog) {
+ String user = creds.getUser();
+ String password;
+ String key;
+ if (Boolean.TRUE.equals(setup.get(LOG_CREDENTIALS))) {
+ password = creds.getOptionalPassword().or("<absent>");
+ key = creds.getOptionalPrivateKey().or("<absent>");
+ } else {
+ password = creds.getOptionalPassword().isPresent() ? "******" : "<absent>";
+ key = creds.getOptionalPrivateKey().isPresent() ? "******" : "<absent>";
+ }
+ credsToString.add("user="+user+", password="+password+", key="+key);
}
- LOG.debug("VM {}: reported online, now waiting {} for it to be contactable on {}{}; using credentials password={}; key={}",
+
+ LOG.debug("VM {}: reported online, now waiting {} for it to be contactable on {}; using credentials {}",
new Object[] {
setup.getDescription(), timeout,
- connectionDetails,
- Objects.equal(user, getUser(setup)) ? "" : " (setup user is different: "+getUser(setup)+")",
- password.or("<absent>"),
- key.or("<absent>")
+ hostAndPort,
+ (credsToString.size() == 1) ? credsToString.get(0) : "(multiple!):" + Joiner.on("\n\t").join(credsToString)
});
}
@@ -2583,13 +2623,13 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
if (!reachable.getWithoutError()) {
throw new IllegalStateException("Connection failed for "
- +connectionDetails+" ("+setup.getDescription()+") after waiting "
+ +hostAndPort+" ("+setup.getDescription()+") after waiting "
+Time.makeTimeStringRounded(timeout), reachable.getError());
}
LOG.debug("VM {}: connection succeeded after {} on {}",new Object[] {
setup.getDescription(), Time.makeTimeStringRounded(stopwatch),
- connectionDetails});
+ hostAndPort});
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ca7e267/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 60a5271..ba5ce64 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
@@ -463,7 +463,28 @@ public class JcloudsLocationSecurityGroupCustomizer extends BasicJcloudsLocation
Callable<SecurityGroup> callable = new Callable<SecurityGroup>() {
@Override
public SecurityGroup call() throws Exception {
- return securityApi.addIpPermission(permission, group);
+ try {
+ return securityApi.addIpPermission(permission, group);
+ } catch (AWSResponseException e) {
+ if ("InvalidPermission.Duplicate".equals(e.getError().getCode())) {
+ // already exists
+ LOG.info("Permission already exists for security group; continuing (logging underlying exception at debug): permission="+permission+"; group="+group);
+ LOG.debug("Permission already exists for security group; continuing: permission="+permission+"; group="+group, e);
+ return null;
+ } else {
+ throw e;
+ }
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ if (e.toString().contains("InvalidPermission.Duplicate")) {
+ // belt-and-braces, in case
+ // already exists
+ LOG.info("Permission already exists for security group; continuing (but unexpected exception type): permission="+permission+"; group="+group, e);
+ return null;
+ } else {
+ throw Exceptions.propagate(e);
+ }
+ }
}
};
return runOperationWithRetry(callable);