Repository: jclouds
Updated Branches:
  refs/heads/master c18371a79 -> d649c90d9


fix for issue if SL machine has multiple credentials registered

now just pick the best one. it matters only when we are going to log in to a 
machine.
the only time the problem has been observed has been with pre-existing machines 
set up
outwith jclouds with multiple password.


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

Branch: refs/heads/master
Commit: d649c90d988cab6fa90f34a7d87037a33e36654a
Parents: c18371a
Author: Alex Heneveld <[email protected]>
Authored: Tue Mar 8 09:54:40 2016 +0000
Committer: Andrea Turli <[email protected]>
Committed: Tue Mar 8 14:59:20 2016 +0100

----------------------------------------------------------------------
 .../functions/VirtualGuestToNodeMetadata.java   | 54 ++++++++++++++++++-
 .../VirtualGuestToNodeMetadataTest.java         | 55 ++++++++++++++++++++
 2 files changed, 108 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/d649c90d/providers/softlayer/src/main/java/org/jclouds/softlayer/compute/functions/VirtualGuestToNodeMetadata.java
----------------------------------------------------------------------
diff --git 
a/providers/softlayer/src/main/java/org/jclouds/softlayer/compute/functions/VirtualGuestToNodeMetadata.java
 
b/providers/softlayer/src/main/java/org/jclouds/softlayer/compute/functions/VirtualGuestToNodeMetadata.java
index 470fb76..0a76c70 100644
--- 
a/providers/softlayer/src/main/java/org/jclouds/softlayer/compute/functions/VirtualGuestToNodeMetadata.java
+++ 
b/providers/softlayer/src/main/java/org/jclouds/softlayer/compute/functions/VirtualGuestToNodeMetadata.java
@@ -18,10 +18,12 @@ package org.jclouds.softlayer.compute.functions;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.collect.FluentIterable.from;
+
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import javax.annotation.Resource;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
@@ -34,20 +36,26 @@ import org.jclouds.compute.functions.GroupNamingConvention;
 import org.jclouds.domain.Location;
 import org.jclouds.domain.LoginCredentials;
 import org.jclouds.location.predicates.LocationPredicates;
+import org.jclouds.logging.Logger;
 import org.jclouds.softlayer.domain.Password;
 import org.jclouds.softlayer.domain.TagReference;
 import org.jclouds.softlayer.domain.VirtualGuest;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 
 @Singleton
 public class VirtualGuestToNodeMetadata implements Function<VirtualGuest, 
NodeMetadata> {
 
+   @Resource
+   protected Logger logger = Logger.NULL;
+    
    public static final Map<VirtualGuest.State, Status> serverStateToNodeStatus 
= ImmutableMap
          .<VirtualGuest.State, Status> 
builder().put(VirtualGuest.State.HALTED, Status.PENDING)
          .put(VirtualGuest.State.PAUSED, 
Status.SUSPENDED).put(VirtualGuest.State.RUNNING, Status.RUNNING)
@@ -95,7 +103,7 @@ public class VirtualGuestToNodeMetadata implements 
Function<VirtualGuest, NodeMe
          
builder.privateAddresses(ImmutableSet.of(from.getPrimaryBackendIpAddress()));
       // TODO simplify once we move domain classes to AutoValue
       if (from.getOperatingSystem() != null && 
from.getOperatingSystem().getPasswords() != null && 
!from.getOperatingSystem().getPasswords().isEmpty()) {
-         Password password = 
Iterables.getOnlyElement(from.getOperatingSystem().getPasswords());
+         Password password = 
getBestPassword(from.getOperatingSystem().getPasswords(), from);
          
builder.credentials(LoginCredentials.builder().identity(password.getUsername()).credential(password.getPassword()).build());
       }
       if (from.getTagReferences() != null && 
!from.getTagReferences().isEmpty()) {
@@ -110,4 +118,48 @@ public class VirtualGuestToNodeMetadata implements 
Function<VirtualGuest, NodeMe
       return builder.build();
    }
 
+   @VisibleForTesting
+   Password getBestPassword(Set<Password> passwords, VirtualGuest context) {
+      if (passwords == null || passwords.isEmpty()) {
+         throw new IllegalStateException("No credentials declared for " + 
context);
+      }
+      if (passwords.size() == 1) {
+          // usual path
+          return Iterables.getOnlyElement(passwords);
+      }
+      // in some setups a there may be multiple passwords; pick the best
+      Password bestPassword = null;
+      Set<Password> alternates = Sets.newLinkedHashSet();
+      int bestScore = -1;
+      for (Password p : passwords) {
+         int score = -1;
+         if ("root".equals(p.getUsername())) score = 10;
+         else if ("root".equalsIgnoreCase(p.getUsername())) score = 4;
+         else if ("ubuntu".equals(p.getUsername())) score = 8;
+         else if ("ubuntu".equalsIgnoreCase(p.getUsername())) score = 3;
+         else if ("administrator".equals(p.getUsername())) score = 5;
+         else if ("administrator".equalsIgnoreCase(p.getUsername())) score = 2;
+         else if (p.getUsername() != null && p.getUsername().length() > 1) 
score = 1;
+         
+         if (score > 0) {
+            if (score > bestScore) {
+                bestPassword = p;
+                alternates.clear();
+                bestScore = score;
+            } else if (score == bestScore) {
+                alternates.add(p);
+            }
+         }
+      }
+      if (bestPassword == null) {
+          throw new IllegalStateException("No valid credentials available for 
" + context + "; found: " + passwords);
+      }
+      if (!alternates.isEmpty()) {
+         logger.warn("Multiple credentials for " + bestPassword.getUsername() 
+ "@" + context + "; using first declared " + bestPassword + " and ignoring " + 
alternates);
+      } else {
+         logger.debug("Multiple credentials for " + context + "; using 
preferred username " + bestPassword.getUsername());
+      }
+      return bestPassword;
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/d649c90d/providers/softlayer/src/test/java/org/jclouds/softlayer/compute/functions/VirtualGuestToNodeMetadataTest.java
----------------------------------------------------------------------
diff --git 
a/providers/softlayer/src/test/java/org/jclouds/softlayer/compute/functions/VirtualGuestToNodeMetadataTest.java
 
b/providers/softlayer/src/test/java/org/jclouds/softlayer/compute/functions/VirtualGuestToNodeMetadataTest.java
index 868e788..86c4cb8 100644
--- 
a/providers/softlayer/src/test/java/org/jclouds/softlayer/compute/functions/VirtualGuestToNodeMetadataTest.java
+++ 
b/providers/softlayer/src/test/java/org/jclouds/softlayer/compute/functions/VirtualGuestToNodeMetadataTest.java
@@ -19,6 +19,7 @@ package org.jclouds.softlayer.compute.functions;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
+
 import java.util.Set;
 
 import org.jclouds.compute.domain.NodeMetadata;
@@ -29,6 +30,7 @@ import org.jclouds.domain.LocationBuilder;
 import org.jclouds.domain.LocationScope;
 import org.jclouds.softlayer.domain.Datacenter;
 import org.jclouds.softlayer.domain.OperatingSystem;
+import org.jclouds.softlayer.domain.Password;
 import org.jclouds.softlayer.domain.PowerState;
 import org.jclouds.softlayer.domain.SoftwareDescription;
 import org.jclouds.softlayer.domain.SoftwareLicense;
@@ -39,6 +41,7 @@ import com.google.common.base.Supplier;
 import com.google.common.base.Suppliers;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
 import com.google.inject.Guice;
 
 /**
@@ -100,4 +103,56 @@ public class VirtualGuestToNodeMetadataTest {
               .build();
    }
 
+   @Test(expectedExceptions = { IllegalStateException.class })
+   public void testGetBestPasswordNone() {
+      Set<Password> passwords = Sets.newLinkedHashSet();
+      VirtualGuestToNodeMetadata f = new 
VirtualGuestToNodeMetadata(locationSupplier, namingConvention, 
+         virtualGuestToImage, virtualGuestToHardware);
+      f.getBestPassword(passwords, null);
+   }
+   
+   @Test
+   public void testGetBestPasswordOneRoot() {
+      Set<Password> passwords = Sets.newLinkedHashSet();
+      passwords.add(new Password(1, "root", "pass"));
+      VirtualGuestToNodeMetadata f = new 
VirtualGuestToNodeMetadata(locationSupplier, namingConvention, 
+         virtualGuestToImage, virtualGuestToHardware);
+      Password best = f.getBestPassword(passwords, null);
+      assertEquals(best.getUsername(), "root");
+   }
+   
+   @Test
+   public void testGetBestPasswordOneNonRoot() {
+      Set<Password> passwords = Sets.newLinkedHashSet();
+      passwords.add(new Password(1, "nonroot", "word"));
+      VirtualGuestToNodeMetadata f = new 
VirtualGuestToNodeMetadata(locationSupplier, namingConvention, 
+         virtualGuestToImage, virtualGuestToHardware);
+      Password best = f.getBestPassword(passwords, null);
+      assertEquals(best.getUsername(), "nonroot");
+   }
+   
+   @Test
+   public void testGetBestPasswordTwoDifferent() {
+      Set<Password> passwords = Sets.newLinkedHashSet();
+      passwords.add(new Password(1, "nonroot", "word"));
+      passwords.add(new Password(2, "root", "pass"));
+      VirtualGuestToNodeMetadata f = new 
VirtualGuestToNodeMetadata(locationSupplier, namingConvention, 
+         virtualGuestToImage, virtualGuestToHardware);
+      Password best = f.getBestPassword(passwords, null);
+      assertEquals(best.getUsername(), "root");
+   }
+   
+   @Test
+   public void testGetBestPasswordTwoSame() {
+      Set<Password> passwords = Sets.newLinkedHashSet();
+      passwords.add(new Password(1, "root", "word"));
+      passwords.add(new Password(2, "root", "pass"));
+      VirtualGuestToNodeMetadata f = new 
VirtualGuestToNodeMetadata(locationSupplier, namingConvention, 
+         virtualGuestToImage, virtualGuestToHardware);
+      Password best = f.getBestPassword(passwords, null);
+      assertEquals(best.getUsername(), "root");
+      // should take the first
+      assertEquals(best.getPassword(), "word");
+   }
+   
 }

Reply via email to