You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by dr...@apache.org on 2017/07/24 14:37:39 UTC

[2/6] brooklyn-server git commit: improve how we find localhost

improve how we find localhost

increasingly i'm getting unusable NICs preferred by the method we used to use,
InetAddress.getLocalhost(), and comments elsewhere eg https://stackoverflow.com/questions/5813194/inetaddress-getlocalhost-does-not-return-expected-ip-address-from-c-windows-s
suggest that wasn't a good method in any case

update most places to require a _reachable_ localhost address


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

Branch: refs/heads/master
Commit: 3647d1f245c36386ef17cf6a75954c0801e95e9a
Parents: 9795c47
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Jul 19 10:27:36 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Sat Jul 22 03:10:08 2017 +0100

----------------------------------------------------------------------
 .../LocalhostMachineProvisioningLocation.java   |  8 +-
 .../util/core/BrooklynNetworkUtils.java         |  2 +-
 .../core/location/SimulatedLocation.java        |  2 +-
 ...ocalhostMachineProvisioningLocationTest.java |  7 +-
 .../ssh/SshMachineLocationIntegrationTest.java  |  6 +-
 .../ssh/SshMachineLocationPerformanceTest.java  |  2 +-
 .../SshMachineLocationReuseIntegrationTest.java |  4 +-
 .../location/ssh/SshMachineLocationTest.java    |  6 +-
 .../usage/JcloudsLocationUsageTrackingTest.java |  2 +-
 .../winrm/WinRmMachineLocationTest.java         |  2 +-
 .../framework/TestEndpointReachableTest.java    |  4 +-
 .../apache/brooklyn/util/net/Networking.java    | 89 ++++++++++++++++----
 .../brooklyn/util/net/NetworkingUtilsTest.java  | 22 ++++-
 .../util/net/ReachableSocketFinderTest.java     |  2 +-
 14 files changed, 115 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3647d1f2/core/src/main/java/org/apache/brooklyn/location/localhost/LocalhostMachineProvisioningLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/localhost/LocalhostMachineProvisioningLocation.java b/core/src/main/java/org/apache/brooklyn/location/localhost/LocalhostMachineProvisioningLocation.java
index 014535b..b73fd37 100644
--- a/core/src/main/java/org/apache/brooklyn/location/localhost/LocalhostMachineProvisioningLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/location/localhost/LocalhostMachineProvisioningLocation.java
@@ -177,7 +177,7 @@ public class LocalhostMachineProvisioningLocation extends FixedListMachineProvis
         for (int i=0; i<size; i++) {
             Map<Object,Object> flags2 = MutableMap.<Object,Object>builder()
                     .putAll(flags)
-                    .put("address", elvis(address, Networking.getLocalHost()))
+                    .put("address", elvis(address, getLocalhostInetAddress()))
                     .build();
             
             // copy inherited keys for ssh; 
@@ -309,17 +309,17 @@ public class LocalhostMachineProvisioningLocation extends FixedListMachineProvis
         @Override
         public LocalhostMachine configure(Map<?,?> properties) {
             if (address==null || !properties.containsKey("address"))
-                address = Networking.getLocalHost();
+                address = getLocalhostInetAddress();
             super.configure(properties);
             return this;
         }
         @Override
         public String getSubnetHostname() {
-           return Networking.getLocalHost().getHostName();
+           return Networking.getReachableLocalHost().getHostName();
         }
         @Override
         public String getSubnetIp() {
-            return Networking.getLocalHost().getHostAddress();
+            return Networking.getReachableLocalHost().getHostAddress();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3647d1f2/core/src/main/java/org/apache/brooklyn/util/core/BrooklynNetworkUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/BrooklynNetworkUtils.java b/core/src/main/java/org/apache/brooklyn/util/core/BrooklynNetworkUtils.java
index 33733b1..b1cd49a 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/BrooklynNetworkUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/BrooklynNetworkUtils.java
@@ -42,6 +42,6 @@ public class BrooklynNetworkUtils {
     /** returns a IP address for localhost paying attention to a system property to prevent lookup in some cases */
     public static InetAddress getLocalhostInetAddress() {
         return TypeCoercions.coerce(JavaGroovyEquivalents.elvis(BrooklynServiceAttributes.LOCALHOST_IP_ADDRESS.getValue(),
-                Networking.getLocalHost()), InetAddress.class);
+                Networking.getReachableLocalHost()), InetAddress.class);
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3647d1f2/core/src/test/java/org/apache/brooklyn/core/location/SimulatedLocation.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/location/SimulatedLocation.java b/core/src/test/java/org/apache/brooklyn/core/location/SimulatedLocation.java
index e9062f2..bfb48e2 100644
--- a/core/src/test/java/org/apache/brooklyn/core/location/SimulatedLocation.java
+++ b/core/src/test/java/org/apache/brooklyn/core/location/SimulatedLocation.java
@@ -51,7 +51,7 @@ public class SimulatedLocation extends AbstractLocation implements MachineProvis
 
     private static final InetAddress address;
     static {
-        address = Networking.getLocalHost();
+        address = Networking.getReachableLocalHost();
     }
 
     Iterable<Integer> permittedPorts = PortRanges.fromString("1+");

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3647d1f2/core/src/test/java/org/apache/brooklyn/location/localhost/LocalhostMachineProvisioningLocationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/localhost/LocalhostMachineProvisioningLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/localhost/LocalhostMachineProvisioningLocationTest.java
index 6839afa..320c6d7 100644
--- a/core/src/test/java/org/apache/brooklyn/location/localhost/LocalhostMachineProvisioningLocationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/localhost/LocalhostMachineProvisioningLocationTest.java
@@ -33,6 +33,7 @@ import org.apache.brooklyn.core.location.geo.HostGeoInfo;
 import org.apache.brooklyn.core.test.BrooklynMgmtUnitTestSupport;
 import org.apache.brooklyn.location.ssh.SshMachineLocation;
 import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.core.BrooklynNetworkUtils;
 import org.apache.brooklyn.util.net.Networking;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -76,7 +77,7 @@ public class LocalhostMachineProvisioningLocationTest extends BrooklynMgmtUnitTe
         LocalhostMachineProvisioningLocation provisioner = mgmt.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class));
         SshMachineLocation machine = provisioner.obtain();
         assertNotNull(machine);
-        assertEquals(machine.getAddress(), Networking.getLocalHost());
+        assertEquals(machine.getAddress(), BrooklynNetworkUtils.getLocalhostInetAddress());
     }
 
     @Test
@@ -98,12 +99,12 @@ public class LocalhostMachineProvisioningLocationTest extends BrooklynMgmtUnitTe
         // first machine
         SshMachineLocation first = provisioner.obtain();
         assertNotNull(first);
-        assertEquals(first.getAddress(), Networking.getLocalHost());
+        assertEquals(first.getAddress(), Networking.getReachableLocalHost());
 
         // second machine
         SshMachineLocation second = provisioner.obtain();
         assertNotNull(second);
-        assertEquals(second.getAddress(), Networking.getLocalHost());
+        assertEquals(second.getAddress(), Networking.getReachableLocalHost());
 
         // third machine - fails
         try {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3647d1f2/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationIntegrationTest.java
index 6f7b324..9ff39c1 100644
--- a/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationIntegrationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationIntegrationTest.java
@@ -87,7 +87,7 @@ public class SshMachineLocationIntegrationTest extends SshMachineLocationTest {
     @Override
     protected SshMachineLocation newHost() {
         return mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)
-                .configure("address", Networking.getLocalHost()));
+                .configure("address", Networking.getReachableLocalHost()));
     }
 
     // Overridden just to make it integration (because `newHost()` returns a real ssh'ing host)
@@ -222,7 +222,7 @@ public class SshMachineLocationIntegrationTest extends SshMachineLocationTest {
     // For issue #230
     @Test(groups = "Integration")
     public void testOverridingPropertyOnExec() throws Exception {
-        SshMachineLocation host = new SshMachineLocation(MutableMap.of("address", Networking.getLocalHost(), "sshPrivateKeyData", "wrongdata"));
+        SshMachineLocation host = new SshMachineLocation(MutableMap.of("address", Networking.getReachableLocalHost(), "sshPrivateKeyData", "wrongdata"));
         
         OutputStream outStream = new ByteArrayOutputStream();
         String expectedName = Os.user();
@@ -234,7 +234,7 @@ public class SshMachineLocationIntegrationTest extends SshMachineLocationTest {
 
     @Test(groups = "Integration", expectedExceptions={IllegalStateException.class, SshException.class})
     public void testSshRunWithInvalidUserFails() throws Exception {
-        SshMachineLocation badHost = new SshMachineLocation(MutableMap.of("user", "doesnotexist", "address", Networking.getLocalHost()));
+        SshMachineLocation badHost = new SshMachineLocation(MutableMap.of("user", "doesnotexist", "address", Networking.getReachableLocalHost()));
         badHost.execScript("mysummary", ImmutableList.of("whoami; exit"));
     }
     

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3647d1f2/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationPerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationPerformanceTest.java b/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationPerformanceTest.java
index c4d7d7d..795f87f 100644
--- a/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationPerformanceTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationPerformanceTest.java
@@ -111,7 +111,7 @@ public class SshMachineLocationPerformanceTest {
     public void testConsecutiveSmallCommandsWithDifferentProperties() throws Exception {
         final Map<String, ?> emptyProperties = Collections.emptyMap();
         final Map<String, ?> customProperties = MutableMap.of(
-                "address", Networking.getLocalHost(),
+                "address", Networking.getReachableLocalHost(),
                 SshTool.PROP_SESSION_TIMEOUT.getName(), 20000,
                 SshTool.PROP_CONNECT_TIMEOUT.getName(), 50000,
                 SshTool.PROP_SCRIPT_HEADER.getName(), "#!/bin/bash");

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3647d1f2/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationReuseIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationReuseIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationReuseIntegrationTest.java
index cebd2f4..924c9c7 100644
--- a/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationReuseIntegrationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationReuseIntegrationTest.java
@@ -102,7 +102,7 @@ public class SshMachineLocationReuseIntegrationTest {
     public void setUp() throws Exception {
         managementContext = new LocalManagementContext();
         host = managementContext.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)
-                .configure("address", Networking.getLocalHost())
+                .configure("address", Networking.getReachableLocalHost())
                 .configure(SshMachineLocation.SSH_TOOL_CLASS, RecordingSshjTool.class.getName()));
     }
 
@@ -163,7 +163,7 @@ public class SshMachineLocationReuseIntegrationTest {
 
     public Map<String, Object> customSshConfigKeys() throws UnknownHostException {
         return MutableMap.<String, Object>of(
-                "address", Networking.getLocalHost(),
+                "address", Networking.getReachableLocalHost(),
                 SshTool.PROP_SESSION_TIMEOUT.getName(), 20000,
                 SshTool.PROP_CONNECT_TIMEOUT.getName(), 50000,
                 SshTool.PROP_SCRIPT_HEADER.getName(), "#!/bin/bash");

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3647d1f2/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationTest.java
index e610fd2..5c6e918 100644
--- a/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationTest.java
@@ -196,7 +196,7 @@ public class SshMachineLocationTest extends BrooklynAppUnitTestSupport {
     @Test
     public void testConfigurePrivateAddresses() throws Exception {
         SshMachineLocation host2 = mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)
-                .configure("address", Networking.getLocalHost())
+                .configure("address", Networking.getReachableLocalHost())
                 .configure(SshMachineLocation.PRIVATE_ADDRESSES, ImmutableList.of("1.2.3.4"))
                 .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, true));
 
@@ -211,7 +211,7 @@ public class SshMachineLocationTest extends BrooklynAppUnitTestSupport {
     @Test
     public void testGetMachineIsInessentialOnFailure() throws Exception {
         SshMachineLocation host2 = mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)
-                .configure("address", Networking.getLocalHost())
+                .configure("address", Networking.getReachableLocalHost())
                 .configure(SshMachineLocation.SSH_TOOL_CLASS, FailingSshTool.class.getName()));
 
         final Effector<MachineDetails> GET_MACHINE_DETAILS = Effectors.effector(MachineDetails.class, "getMachineDetails")
@@ -314,7 +314,7 @@ public class SshMachineLocationTest extends BrooklynAppUnitTestSupport {
     
     @Test
     public void testObtainPortDoesNotUsePreReservedPorts() {
-        host = new SshMachineLocation(MutableMap.of("address", Networking.getLocalHost(), "usedPorts", ImmutableSet.of(8000)));
+        host = new SshMachineLocation(MutableMap.of("address", Networking.getReachableLocalHost(), "usedPorts", ImmutableSet.of(8000)));
         assertEquals(host.obtainPort(PortRanges.fromString("8000")), -1);
         assertEquals(host.obtainPort(PortRanges.fromString("8000+")), 8001);
     }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3647d1f2/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/core/mgmt/usage/JcloudsLocationUsageTrackingTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/core/mgmt/usage/JcloudsLocationUsageTrackingTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/core/mgmt/usage/JcloudsLocationUsageTrackingTest.java
index 333d181..21acbc2 100644
--- a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/core/mgmt/usage/JcloudsLocationUsageTrackingTest.java
+++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/core/mgmt/usage/JcloudsLocationUsageTrackingTest.java
@@ -110,7 +110,7 @@ public class JcloudsLocationUsageTrackingTest extends AbstractJcloudsStubbedLive
         entity = app.createAndManageChild(EntitySpec.create(SoftwareProcessEntityTest.MyService.class));
         
         serverSocket = new ServerSocket();
-        serverSocket.bind(new InetSocketAddress(Networking.getLocalHost(), 0), 0);
+        serverSocket.bind(new InetSocketAddress(Networking.getReachableLocalHost(), 0), 0);
     }
 
     @AfterMethod(alwaysRun=true)

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3647d1f2/software/winrm/src/test/java/org/apache/brooklyn/location/winrm/WinRmMachineLocationTest.java
----------------------------------------------------------------------
diff --git a/software/winrm/src/test/java/org/apache/brooklyn/location/winrm/WinRmMachineLocationTest.java b/software/winrm/src/test/java/org/apache/brooklyn/location/winrm/WinRmMachineLocationTest.java
index 9fa0fe7..a258aeb 100644
--- a/software/winrm/src/test/java/org/apache/brooklyn/location/winrm/WinRmMachineLocationTest.java
+++ b/software/winrm/src/test/java/org/apache/brooklyn/location/winrm/WinRmMachineLocationTest.java
@@ -34,7 +34,7 @@ public class WinRmMachineLocationTest extends BrooklynAppUnitTestSupport {
     @Test
     public void testConfigurePrivateAddresses() throws Exception {
         WinRmMachineLocation host = mgmt.getLocationManager().createLocation(LocationSpec.create(WinRmMachineLocation.class)
-                .configure("address", Networking.getLocalHost())
+                .configure("address", Networking.getReachableLocalHost())
                 .configure(WinRmMachineLocation.PRIVATE_ADDRESSES, ImmutableList.of("1.2.3.4"))
                 .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, true));
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3647d1f2/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEndpointReachableTest.java
----------------------------------------------------------------------
diff --git a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEndpointReachableTest.java b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEndpointReachableTest.java
index efeb7eb..42c35dc 100644
--- a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEndpointReachableTest.java
+++ b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEndpointReachableTest.java
@@ -227,7 +227,7 @@ public class TestEndpointReachableTest extends BrooklynAppUnitTestSupport {
     }
 
     protected ServerSocket openServerPort() throws IOException {
-        InetAddress localAddress = Networking.getLocalHost();
+        InetAddress localAddress = Networking.getReachableLocalHost();
         return new ServerSocket(0, 1024, localAddress);
     }
 
@@ -235,7 +235,7 @@ public class TestEndpointReachableTest extends BrooklynAppUnitTestSupport {
         int startPort = 58767;
         int endPort = 60000;
         int port = startPort;
-        InetAddress localAddress = Networking.getLocalHost();
+        InetAddress localAddress = Networking.getReachableLocalHost();
         do {
             if (Networking.isPortAvailable(localAddress, port)) {
                 return HostAndPort.fromParts(localAddress.getHostAddress(), port);

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3647d1f2/utils/common/src/main/java/org/apache/brooklyn/util/net/Networking.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/net/Networking.java b/utils/common/src/main/java/org/apache/brooklyn/util/net/Networking.java
index f944b77..f0728dd 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/net/Networking.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/net/Networking.java
@@ -38,10 +38,7 @@ import java.util.Map;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Pattern;
 
-import com.google.common.base.Predicate;
-import com.google.common.collect.Range;
-import com.google.common.collect.RangeSet;
-import com.google.common.collect.TreeRangeSet;
+import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.text.Identifiers;
 import org.apache.brooklyn.util.text.Strings;
@@ -50,8 +47,12 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
 import com.google.common.base.Stopwatch;
 import com.google.common.base.Throwables;
+import com.google.common.collect.Range;
+import com.google.common.collect.RangeSet;
+import com.google.common.collect.TreeRangeSet;
 import com.google.common.net.HostAndPort;
 import com.google.common.primitives.UnsignedBytes;
 
@@ -427,13 +428,62 @@ public class Networking {
         }
     }
 
-    /** returns local IP address, or 127.0.0.1 if it cannot be parsed */
+    /** returns local IP address, or 127.0.0.1 if it cannot be parsed
+     * @deprecated since 0.12.0, as this method has bad defaults (fails on some machines);
+     * use {@link #getLocalHost(boolean, boolean, boolean, int)} for full control or
+     * {@link #getReachableLocalHost()} for a method with better defaults and errors */
     public static InetAddress getLocalHost() {
-        try {
-            return InetAddress.getLocalHost();
-        } catch (UnknownHostException e) {
-            InetAddress result = null;
-            result = getInetAddressWithFixedName("127.0.0.1");
+        return getLocalHost(false, true, false, 0);
+    }
+    
+    /** returns a validated local IP address, preferring 127.0.0.1 if it works, and failing if none found */
+    public static InetAddress getReachableLocalHost() {
+        return getLocalHost(true, true, true, 250);
+    }
+    
+    /**
+     * returns a local IP address, using some heuristics to determine the best one 
+     * in the case of multiple possibilities, as follows 
+     * @param checkReachable whether to ensure that the address is bindable and reachable
+     * @param prefer127 whether to prefer standard loopback address 127.0.0.1 if listed
+     * @param failIfNone whether to fail if none or simply return 127.0.0.1
+     * @param timeout how long to wait for each address (if doing checkReachable)
+     * @return an {@link InetAddress} corresponding to localhost
+     */
+    public static InetAddress getLocalHost(boolean checkReachable, boolean prefer127, boolean failIfNone, int timeout) {
+        Map<String, InetAddress> addrs = getLocalAddresses();
+        MutableSet<InetAddress> candidates = new MutableSet<>();
+        if (prefer127) {
+            candidates.addIfNotNull(addrs.get("127.0.0.1"));
+        }
+        candidates.addAll(addrs.values());
+        if (checkReachable) {
+            for (InetAddress a: candidates) {
+                try (ServerSocket ss = new ServerSocket()) {
+                    ss.bind(new InetSocketAddress(a, 0));
+                    if (isReachable(HostAndPort.fromParts(a.getHostAddress(), ss.getLocalPort()), true, timeout)) {
+                        return a;
+                    }
+                } catch (Exception e) {
+                    Exceptions.propagateIfFatal(e);
+                    // swallow and continue
+                }
+            }
+        } else {
+            if (!candidates.isEmpty()) {
+                return candidates.iterator().next();
+            }
+        }
+        if (failIfNone) {
+            throw new IllegalStateException("No reachable local addresses could be found; ensure that localhost is correctly configured on this machine"
+                + ", and if required that network security permits local access to localhost ports");
+        } else {
+            InetAddress result;
+            try {
+                result = InetAddress.getLocalHost();
+            } catch (UnknownHostException e2) {
+                result = getInetAddressWithFixedName("127.0.0.1");
+            }
             log.warn("Localhost is not resolvable; using "+result);
             return result;
         }
@@ -527,14 +577,19 @@ public class Networking {
     }
     
     public static boolean isReachable(HostAndPort endpoint) {
-        // TODO Should we create an unconnected socket, and then use the calls below (see jclouds' InetSocketAddressConnect):
-        //      socket.setReuseAddress(false);
-        //      socket.setSoLinger(false, 1);
-        //      socket.setSoTimeout(timeout);
-        //      socket.connect(socketAddress, timeout);
-        
+        return isReachable(endpoint, false, 0);
+    }
+    public static boolean isReachable(HostAndPort endpoint, boolean noReuseOrLinger, int timeout) {
         try {
-            Socket s = new Socket(endpoint.getHostText(), endpoint.getPort());
+            Socket s = new Socket();
+            if (noReuseOrLinger) {
+                s.setReuseAddress(false);
+                s.setSoLinger(false, 1);
+            }
+            if (timeout>0) {
+                s.setSoTimeout(timeout);
+            }
+            s.connect(new InetSocketAddress(endpoint.getHostText(), endpoint.getPort()));
             closeQuietly(s);
             return true;
         } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3647d1f2/utils/common/src/test/java/org/apache/brooklyn/util/net/NetworkingUtilsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/net/NetworkingUtilsTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/net/NetworkingUtilsTest.java
index 1afffd7..c56ac66 100644
--- a/utils/common/src/test/java/org/apache/brooklyn/util/net/NetworkingUtilsTest.java
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/net/NetworkingUtilsTest.java
@@ -29,6 +29,7 @@ import java.io.IOException;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
+import java.net.Socket;
 import java.net.UnknownHostException;
 import java.util.Collection;
 import java.util.concurrent.TimeUnit;
@@ -217,13 +218,28 @@ public class NetworkingUtilsTest {
     }
 
     @Test
-    public void testIsPortAvailableValidatesAddress() throws Exception {
+    public void testCanConnectToLocalhost() throws Exception {
+        try (ServerSocket ss = new ServerSocket()) {
+            ss.bind(new InetSocketAddress(Networking.getReachableLocalHost(), 0));
+            // check we can connect to it
+            try (Socket s = new Socket()) {
+                s.setSoTimeout(500);
+                try {
+                    s.connect(ss.getLocalSocketAddress(), 500);
+                } catch (Exception e) {
+                    Assert.fail("Localhost as "+ss.getInetAddress()+" is not reachable; ensure localhost is correctly configured and addressible to use Brooklyn", e);
+                }
+            }
+        }
+    }
+        
+    @Test
+    public void testBindToLocalhostAndIsPortAvailableDetectsExplicitLocalhostBinding() throws Exception {
         ServerSocket ss = new ServerSocket();
-        ss.bind(new InetSocketAddress(InetAddress.getLocalHost(), 0));
+        ss.bind(new InetSocketAddress(Networking.getReachableLocalHost(), 0));
         int boundPort = ss.getLocalPort();
         assertTrue(ss.isBound());
         assertNotEquals(boundPort, 0);
-        //will run isAddressValid before returning
         assertFalse(Networking.isPortAvailable(boundPort));
         ss.close();
     }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3647d1f2/utils/common/src/test/java/org/apache/brooklyn/util/net/ReachableSocketFinderTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/net/ReachableSocketFinderTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/net/ReachableSocketFinderTest.java
index cd1dc00..fe8a90f 100644
--- a/utils/common/src/test/java/org/apache/brooklyn/util/net/ReachableSocketFinderTest.java
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/net/ReachableSocketFinderTest.java
@@ -173,7 +173,7 @@ public class ReachableSocketFinderTest {
     @Test(groups="Integration")
     public void testFailsIfRealSocketUnreachable() throws Exception {
         ReachableSocketFinder realFinder = new ReachableSocketFinder();
-        HostAndPort wrongAddr = HostAndPort.fromParts(Networking.getLocalHost().getHostAddress(), findAvailablePort());
+        HostAndPort wrongAddr = HostAndPort.fromParts(Networking.getReachableLocalHost().getHostAddress(), findAvailablePort());
         
         try {
             HostAndPort result = realFinder.findOpenSocketOnNode(ImmutableList.of(wrongAddr), Duration.FIVE_SECONDS);