From bc53abc7fc4596b03243bb76a36c65846815b9cd Mon Sep 17 00:00:00 2001 From: ashley-taylor Date: Wed, 9 Apr 2014 14:17:38 +1200 Subject: [PATCH] JCLOUDS-528: Ability to control interfaces to test for SocketFinder --- .../compute/config/ComputeServiceProperties.java | 5 ++ .../compute/util/ConcurrentOpenSocketFinder.java | 43 +++++++++++++++--- .../util/ConcurrentOpenSocketFinderTest.java | 53 ++++++++++++++++++---- 3 files changed, 84 insertions(+), 17 deletions(-) diff --git a/compute/src/main/java/org/jclouds/compute/config/ComputeServiceProperties.java b/compute/src/main/java/org/jclouds/compute/config/ComputeServiceProperties.java index 4d982da..73021c2 100644 --- a/compute/src/main/java/org/jclouds/compute/config/ComputeServiceProperties.java +++ b/compute/src/main/java/org/jclouds/compute/config/ComputeServiceProperties.java @@ -108,4 +108,9 @@ */ public static final String OS_VERSION_MAP_JSON = "jclouds.compute.os-version-map-json"; + /** + * can be set to either PRIVATE, PUBLIC, ALL (default) controls what interfaces will be used when scanning for an open connection + */ + public static final String SOCKET_FINDER_ALLOWED_INTERFACES = "jclouds.compute.socket-finder-allowed-interfaces"; + } diff --git a/compute/src/main/java/org/jclouds/compute/util/ConcurrentOpenSocketFinder.java b/compute/src/main/java/org/jclouds/compute/util/ConcurrentOpenSocketFinder.java index 5134585..cad35dd 100644 --- a/compute/src/main/java/org/jclouds/compute/util/ConcurrentOpenSocketFinder.java +++ b/compute/src/main/java/org/jclouds/compute/util/ConcurrentOpenSocketFinder.java @@ -19,13 +19,12 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Predicates.or; import static com.google.common.base.Throwables.propagate; -import static com.google.common.collect.Iterables.concat; -import static com.google.common.collect.Iterables.size; import static com.google.common.util.concurrent.Atomics.newReference; import static com.google.common.util.concurrent.MoreExecutors.listeningDecorator; import static java.lang.String.format; import static org.jclouds.Constants.PROPERTY_USER_THREADS; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING; +import static org.jclouds.compute.config.ComputeServiceProperties.SOCKET_FINDER_ALLOWED_INTERFACES; import static org.jclouds.util.Predicates2.retry; import java.util.NoSuchElementException; @@ -63,6 +62,10 @@ private final SocketOpen socketTester; private final Predicate> nodeRunning; private final ListeningExecutorService userExecutor; + + @Inject(optional = true) + @Named(SOCKET_FINDER_ALLOWED_INTERFACES) + private AllowedInterfaces allowedInterfaces = AllowedInterfaces.ALL; @Inject @VisibleForTesting @@ -76,7 +79,7 @@ @Override public HostAndPort findOpenSocketOnNode(NodeMetadata node, final int port, long timeout, TimeUnit timeUnits) { - ImmutableSet sockets = checkNodeHasIps(node).transform(new Function() { + ImmutableSet sockets = checkNodeHasIps(node, allowedInterfaces).transform(new Function() { @Override public HostAndPort apply(String from) { @@ -175,10 +178,18 @@ public String toString() { }; } - private static FluentIterable checkNodeHasIps(NodeMetadata node) { - FluentIterable ips = FluentIterable.from(concat(node.getPublicAddresses(), node.getPrivateAddresses())); - checkState(size(ips) > 0, "node does not have IP addresses configured: " + node); - return ips; + @VisibleForTesting + static FluentIterable checkNodeHasIps(NodeMetadata node, AllowedInterfaces allowedInterfaces) { + ImmutableSet.Builder ipsBuilder = ImmutableSet.builder(); + if (allowedInterfaces.scanPublic) { + ipsBuilder.addAll(node.getPublicAddresses()); + } + if (allowedInterfaces.scanPrivate) { + ipsBuilder.addAll(node.getPrivateAddresses()); + } + ImmutableSet ips = ipsBuilder.build(); + checkState(!ips.isEmpty(), "node does not have IP addresses configured: %s", node); + return FluentIterable.from(ips); } private static void blockOn(Iterable> immutableList) { @@ -191,4 +202,21 @@ private static void blockOn(Iterable> immutableList) { throw propagate(e); } } + + @VisibleForTesting + enum AllowedInterfaces { + ALL(true, true), + PUBLIC(true, false), + PRIVATE(false, true); + + private final boolean scanPublic; + private final boolean scanPrivate; + + private AllowedInterfaces(boolean scanPublic, boolean scanPrivate) { + this.scanPublic = scanPublic; + this.scanPrivate = scanPrivate; + } + + } + } diff --git a/compute/src/test/java/org/jclouds/compute/util/ConcurrentOpenSocketFinderTest.java b/compute/src/test/java/org/jclouds/compute/util/ConcurrentOpenSocketFinderTest.java index f00c153..aa4171d 100644 --- a/compute/src/test/java/org/jclouds/compute/util/ConcurrentOpenSocketFinderTest.java +++ b/compute/src/test/java/org/jclouds/compute/util/ConcurrentOpenSocketFinderTest.java @@ -26,6 +26,7 @@ import static org.jclouds.compute.domain.NodeMetadata.Status.RUNNING; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertFalse; import static org.testng.Assert.fail; import java.util.Map; @@ -36,6 +37,7 @@ import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadataBuilder; +import org.jclouds.compute.util.ConcurrentOpenSocketFinder.AllowedInterfaces; import org.jclouds.predicates.SocketOpen; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -43,6 +45,7 @@ import com.google.common.base.Predicate; import com.google.common.base.Stopwatch; +import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.net.HostAndPort; @@ -56,11 +59,14 @@ */ private static final long SLOW_GRACE = 700; private static final long EARLY_GRACE = 10; - + + private static final String PUBLIC_IP = "1.2.3.4"; + private static final String PRIVATE_IP = "1.2.3.5"; + private final NodeMetadata node = new NodeMetadataBuilder().id("myid") .status(RUNNING) - .publicAddresses(ImmutableSet.of("1.2.3.4")) - .privateAddresses(ImmutableSet.of("1.2.3.5")).build(); + .publicAddresses(ImmutableSet.of(PUBLIC_IP)) + .privateAddresses(ImmutableSet.of(PRIVATE_IP)).build(); private final SocketOpen socketAlwaysClosed = new SocketOpen() { @Override @@ -68,7 +74,12 @@ public boolean apply(HostAndPort input) { return false; } }; - + private final SocketOpen socketAlwaysOpen = new SocketOpen() { + @Override + public boolean apply(HostAndPort input) { + return true; + } + }; private final Predicate> nodeRunning = alwaysTrue(); private final Predicate> nodeNotRunning = alwaysFalse(); @@ -110,27 +121,27 @@ public void testReturnsReachable() throws Exception { SocketOpen secondSocketOpen = new SocketOpen() { @Override public boolean apply(HostAndPort input) { - return HostAndPort.fromParts("1.2.3.5", 22).equals(input); + return HostAndPort.fromParts(PRIVATE_IP, 22).equals(input); } }; OpenSocketFinder finder = new ConcurrentOpenSocketFinder(secondSocketOpen, nodeRunning, userExecutor); HostAndPort result = finder.findOpenSocketOnNode(node, 22, 2000, MILLISECONDS); - assertEquals(result, HostAndPort.fromParts("1.2.3.5", 22)); + assertEquals(result, HostAndPort.fromParts(PRIVATE_IP, 22)); } @Test public void testChecksSocketsConcurrently() throws Exception { ControllableSocketOpen socketTester = new ControllableSocketOpen(ImmutableMap.of( - HostAndPort.fromParts("1.2.3.4", 22), new SlowCallable(true, 1500), - HostAndPort.fromParts("1.2.3.5", 22), new SlowCallable(true, 1000))); + HostAndPort.fromParts(PUBLIC_IP, 22), new SlowCallable(true, 1500), + HostAndPort.fromParts(PRIVATE_IP, 22), new SlowCallable(true, 1000))); OpenSocketFinder finder = new ConcurrentOpenSocketFinder(socketTester, nodeRunning, userExecutor); HostAndPort result = finder.findOpenSocketOnNode(node, 22, 2000, MILLISECONDS); - assertEquals(result, HostAndPort.fromParts("1.2.3.5", 22)); + assertEquals(result, HostAndPort.fromParts(PRIVATE_IP, 22)); } @Test @@ -163,7 +174,29 @@ public boolean apply(T input) { // logged+swallowed by RetryablePredicate } } - + + + @Test + public void testSocketFinderAllowedInterfacesAll() throws Exception { + FluentIterable ips = ConcurrentOpenSocketFinder.checkNodeHasIps(node, AllowedInterfaces.ALL); + assertTrue(ips.contains(PUBLIC_IP)); + assertTrue(ips.contains(PRIVATE_IP)); + } + + @Test + public void testSocketFinderAllowedInterfacesPrivate() throws Exception { + FluentIterable ips = ConcurrentOpenSocketFinder.checkNodeHasIps(node, AllowedInterfaces.PRIVATE); + assertFalse(ips.contains(PUBLIC_IP)); + assertTrue(ips.contains(PRIVATE_IP)); + } + + @Test + public void testSocketFinderAllowedInterfacesPublic() throws Exception { + FluentIterable ips = ConcurrentOpenSocketFinder.checkNodeHasIps(node, AllowedInterfaces.PUBLIC); + assertTrue(ips.contains(PUBLIC_IP)); + assertFalse(ips.contains(PRIVATE_IP)); + } + private static class SlowCallable implements Callable { private final T result; private final long delay; -- 1.9.1