diff options
author | Håkon Hallingstad <hakon@yahoo-inc.com> | 2017-02-20 17:13:18 +0100 |
---|---|---|
committer | Håkon Hallingstad <hakon@yahoo-inc.com> | 2017-02-20 17:13:18 +0100 |
commit | d27e86bcd396d64a92d4742083235ee6768dc6b9 (patch) | |
tree | f2daf9230f2575792e58f8abe76aeeeb8f8a0d86 | |
parent | 24eab4fe4b661526f327fcb32a045dfbc7f3c998 (diff) |
Makes clustercontroller-core work on WiFi
11 files changed, 134 insertions, 71 deletions
diff --git a/.gitignore b/.gitignore index 610eda0fd67..d1c452b4084 100644 --- a/.gitignore +++ b/.gitignore @@ -36,4 +36,5 @@ Testing /.ninja_log /build.ninja /rules.ninja -*_test_app
\ No newline at end of file +*_test_app +/hadoop/dependency-reduced-pom.xml diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/rpc/RpcServer.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/rpc/RpcServer.java index 9619a15de3c..d846bba1ad1 100644 --- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/rpc/RpcServer.java +++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/rpc/RpcServer.java @@ -1,25 +1,41 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.clustercontroller.core.rpc; -import com.yahoo.jrt.*; +import com.yahoo.jrt.Acceptor; +import com.yahoo.jrt.ErrorCode; +import com.yahoo.jrt.Int32Value; +import com.yahoo.jrt.ListenFailedException; +import com.yahoo.jrt.Method; +import com.yahoo.jrt.Request; +import com.yahoo.jrt.Spec; +import com.yahoo.jrt.StringArray; +import com.yahoo.jrt.StringValue; +import com.yahoo.jrt.Supervisor; +import com.yahoo.jrt.Transport; +import com.yahoo.jrt.slobrok.api.BackOffPolicy; import com.yahoo.jrt.slobrok.api.Register; import com.yahoo.jrt.slobrok.api.SlobrokList; -import com.yahoo.jrt.slobrok.api.BackOffPolicy; import com.yahoo.log.LogLevel; -import com.yahoo.vdslib.state.*; +import com.yahoo.vdslib.state.ClusterState; +import com.yahoo.vdslib.state.Node; +import com.yahoo.vdslib.state.NodeState; +import com.yahoo.vdslib.state.NodeType; +import com.yahoo.vdslib.state.State; +import com.yahoo.vespa.clustercontroller.core.ContentCluster; import com.yahoo.vespa.clustercontroller.core.MasterElectionHandler; import com.yahoo.vespa.clustercontroller.core.NodeInfo; -import com.yahoo.vespa.clustercontroller.core.ContentCluster; +import com.yahoo.vespa.clustercontroller.core.Timer; import com.yahoo.vespa.clustercontroller.core.listeners.NodeAddedOrRemovedListener; import com.yahoo.vespa.clustercontroller.core.listeners.NodeStateOrHostInfoChangeHandler; -import com.yahoo.vespa.clustercontroller.core.Timer; -import java.util.logging.Logger; -import java.util.*; -import java.net.UnknownHostException; -import java.net.InetAddress; -import java.io.StringWriter; import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.logging.Logger; public class RpcServer { @@ -94,13 +110,12 @@ public class RpcServer { slobroks.append(" )"); SlobrokList slist = new SlobrokList(); slist.setup(slobrokConnectionSpecs); - log.log(LogLevel.DEBUG, "Trying to connect to slobrok using local address " + InetAddress.getLocalHost().getHostName() - + ", port " + acceptor.port() + " using slobrok connection spec " + slobroks); + Spec spec = Spec.fromLocalHostName(acceptor.port()); + log.log(LogLevel.INFO, "Connecting to slobrok at " + spec + " using connection spec " + slobroks); if (slobrokBackOffPolicy != null) { - register = new Register(supervisor, slist, - new Spec(InetAddress.getLocalHost().getHostName(), acceptor.port()), slobrokBackOffPolicy); + register = new Register(supervisor, slist, spec, slobrokBackOffPolicy); } else { - register = new Register(supervisor, slist, InetAddress.getLocalHost().getHostName(), acceptor.port()); + register = new Register(supervisor, slist, spec); } register.registerName(getSlobrokName()); } diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/MasterElectionTest.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/MasterElectionTest.java index 80435ee7c7d..03eddd86615 100644 --- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/MasterElectionTest.java +++ b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/MasterElectionTest.java @@ -1,26 +1,28 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.clustercontroller.core; -import com.yahoo.jrt.*; +import com.yahoo.jrt.Request; +import com.yahoo.jrt.Spec; +import com.yahoo.jrt.Supervisor; +import com.yahoo.jrt.Target; +import com.yahoo.jrt.Transport; import com.yahoo.jrt.slobrok.server.Slobrok; import com.yahoo.log.LogLevel; +import com.yahoo.vdslib.state.ClusterState; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; -import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeoutException; import java.util.logging.Logger; -import com.yahoo.vdslib.state.ClusterState; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestRule; - import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class MasterElectionTest extends FleetControllerTest { @@ -42,7 +44,7 @@ public class MasterElectionTest extends FleetControllerTest { this.options.zooKeeperSessionTimeout = 10 * timeoutMS; this.options.zooKeeperServerAddress = zooKeeperServer.getAddress(); this.options.slobrokConnectionSpecs = new String[1]; - this.options.slobrokConnectionSpecs[0] = "tcp/"+ InetAddress.getLocalHost().getHostName()+":" + slobrok.port(); + this.options.slobrokConnectionSpecs[0] = Spec.fromLocalHostName(slobrok.port()).toString(); this.options.fleetControllerCount = count; for (int i=0; i<count; ++i) { FleetControllerOptions nodeOptions = options.clone(); @@ -58,7 +60,7 @@ public class MasterElectionTest extends FleetControllerTest { options.zooKeeperSessionTimeout = 10 * timeoutMS; options.zooKeeperServerAddress = zooKeeperServer.getAddress(); options.slobrokConnectionSpecs = new String[1]; - options.slobrokConnectionSpecs[0] = "tcp/"+ InetAddress.getLocalHost().getHostName()+":" + slobrok.port(); + options.slobrokConnectionSpecs[0] = Spec.fromLocalHostName(slobrok.port()).toString(); options.fleetControllerIndex = fleetControllerIndex; options.fleetControllerCount = fleetControllerCount; return options; diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/RpcServerTest.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/RpcServerTest.java index f7f86907205..33145644d23 100644 --- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/RpcServerTest.java +++ b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/RpcServerTest.java @@ -1,26 +1,41 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.clustercontroller.core; +import com.yahoo.jrt.ErrorCode; +import com.yahoo.jrt.Int32Value; +import com.yahoo.jrt.Request; +import com.yahoo.jrt.Spec; +import com.yahoo.jrt.StringValue; +import com.yahoo.jrt.Supervisor; +import com.yahoo.jrt.Target; +import com.yahoo.jrt.Transport; +import com.yahoo.jrt.slobrok.server.Slobrok; +import com.yahoo.log.LogLevel; import com.yahoo.vdslib.distribution.ConfiguredNode; +import com.yahoo.vdslib.distribution.Distribution; +import com.yahoo.vdslib.state.ClusterState; +import com.yahoo.vdslib.state.Node; +import com.yahoo.vdslib.state.NodeState; +import com.yahoo.vdslib.state.NodeType; +import com.yahoo.vdslib.state.State; import com.yahoo.vespa.clustercontroller.core.rpc.RpcServer; import com.yahoo.vespa.clustercontroller.core.testutils.LogFormatter; import com.yahoo.vespa.clustercontroller.core.testutils.WaitCondition; import com.yahoo.vespa.config.content.StorDistributionConfig; -import com.yahoo.jrt.*; -import com.yahoo.jrt.StringValue; -import com.yahoo.jrt.slobrok.server.Slobrok; -import com.yahoo.log.LogLevel; -import com.yahoo.vdslib.distribution.Distribution; -import com.yahoo.vdslib.state.*; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertFalse; -import java.net.InetAddress; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; import java.util.logging.Logger; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + /** * @author humbe */ @@ -42,7 +57,7 @@ public class RpcServerTest extends FleetControllerTest { startingTest("RpcServerTest::testRebinding"); Slobrok slobrok = new Slobrok(); String slobrokConnectionSpecs[] = new String[1]; - slobrokConnectionSpecs[0] = "tcp/"+ InetAddress.getLocalHost().getHostName()+":" + slobrok.port(); + slobrokConnectionSpecs[0] = Spec.fromLocalHostName(slobrok.port()).toString(); RpcServer server = new RpcServer(timer, new Object(), "mycluster", 0, new BackOff()); server.setSlobrokConnectionSpecs(slobrokConnectionSpecs, 0); int portUsed = server.getPort(); @@ -112,7 +127,7 @@ public class RpcServerTest extends FleetControllerTest { int rpcPort = fleetController.getRpcPort(); supervisor = new Supervisor(new Transport()); - Target connection = supervisor.connect(new Spec(rpcPort)); + Target connection = supervisor.connect(Spec.fromLocalHostName(rpcPort)); assertTrue(connection.isValid()); Request req = new Request("getSystemState"); @@ -130,7 +145,7 @@ public class RpcServerTest extends FleetControllerTest { if (supervisor == null) { supervisor = new Supervisor(new Transport()); } - Target connection = supervisor.connect(new Spec(rpcPort)); + Target connection = supervisor.connect(Spec.fromLocalHostName(rpcPort)); assertTrue(connection.isValid()); Node node = new Node(nodeType, nodeIndex); diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/StateGatherTest.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/StateGatherTest.java index cf3a47b1add..194b51aa440 100644 --- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/StateGatherTest.java +++ b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/StateGatherTest.java @@ -1,14 +1,15 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.clustercontroller.core; +import com.yahoo.jrt.Spec; import com.yahoo.log.LogLevel; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import java.net.InetAddress; import java.util.concurrent.TimeoutException; import java.util.logging.Logger; +import static org.junit.Assert.assertEquals; + public class StateGatherTest extends FleetControllerTest { public static Logger log = Logger.getLogger(StateGatherTest.class.getName()); @@ -34,7 +35,7 @@ public class StateGatherTest extends FleetControllerTest { options.nodeStateRequestTimeoutLatestPercentage = 80; setUpFleetController(true, options); String connectionSpecs[] = new String[1]; - connectionSpecs[0] = "tcp/" + InetAddress.getLocalHost().getHostName() + ":" + slobrok.port(); + connectionSpecs[0] = Spec.fromLocalHostName(slobrok.port()).toString(); DummyVdsNodeOptions dummyOptions = new DummyVdsNodeOptions(); DummyVdsNode dnode = new DummyVdsNode(timer, dummyOptions, connectionSpecs, this.options.clusterName, true, 0); DummyVdsNode snode = new DummyVdsNode(timer, dummyOptions, connectionSpecs, this.options.clusterName, false, 0); diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/ZooKeeperTestServer.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/ZooKeeperTestServer.java index a5191df5f73..c5f3d2caafe 100644 --- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/ZooKeeperTestServer.java +++ b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/ZooKeeperTestServer.java @@ -1,8 +1,9 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.clustercontroller.core; -import org.apache.zookeeper.server.ZooKeeperServer; +import com.yahoo.net.HostName; import org.apache.zookeeper.server.NIOServerCnxnFactory; +import org.apache.zookeeper.server.ZooKeeperServer; import java.io.File; import java.io.IOException; @@ -50,7 +51,7 @@ public class ZooKeeperTestServer { } public String getAddress() { - return factory.getLocalAddress().getHostName() + ":" + getPort(); + return HostName.getLocalhost() + ":" + getPort(); } public void shutdown(boolean cleanupZooKeeperDir) { diff --git a/jrt/src/com/yahoo/jrt/Acceptor.java b/jrt/src/com/yahoo/jrt/Acceptor.java index 7316f8c620b..0f40c6c8e55 100644 --- a/jrt/src/com/yahoo/jrt/Acceptor.java +++ b/jrt/src/com/yahoo/jrt/Acceptor.java @@ -47,7 +47,7 @@ public class Acceptor { if (spec.port() != 0) { serverChannel.socket().setReuseAddress(true); } - serverChannel.socket().bind(spec.address(), 500); + serverChannel.socket().bind(spec.listenAddress(), 500); } catch (Exception e) { if (serverChannel != null) { try { serverChannel.socket().close(); } catch (Exception x) {} diff --git a/jrt/src/com/yahoo/jrt/Connection.java b/jrt/src/com/yahoo/jrt/Connection.java index 52964726eb7..24efdf46087 100644 --- a/jrt/src/com/yahoo/jrt/Connection.java +++ b/jrt/src/com/yahoo/jrt/Connection.java @@ -163,7 +163,7 @@ class Connection extends Target { return this; } try { - channel = SocketChannel.open(spec.address()); + channel = SocketChannel.open(spec.connectAddress()); } catch (Exception e) { setLostReason(e); } diff --git a/jrt/src/com/yahoo/jrt/Spec.java b/jrt/src/com/yahoo/jrt/Spec.java index 4c1f07b98a2..d40e773df68 100644 --- a/jrt/src/com/yahoo/jrt/Spec.java +++ b/jrt/src/com/yahoo/jrt/Spec.java @@ -4,8 +4,8 @@ package com.yahoo.jrt; import com.yahoo.net.HostName; -import java.net.SocketAddress; import java.net.InetSocketAddress; +import java.net.SocketAddress; /** @@ -70,6 +70,15 @@ public class Spec { } /** + * Creates a Spec with the hostname of the current/local host and given port + * + * @param port port number + */ + public static Spec fromLocalHostName(int port) { + return new Spec(HostName.getLocalhost(), port); + } + + /** * Obtain the host name of this address * * @return host name @@ -98,25 +107,44 @@ public class Spec { } /** - * Resolve the socket address for this Spec. If this Spec is + * Resolve the listening socket address for this Spec. If this Spec is + * malformed, this method will return null. + * + * @return listening socket address + */ + SocketAddress listenAddress() { + return address(host); + } + + /** + * Resolve the connect socket address for this Spec. If this Spec is * malformed, this method will return null. * - * @return socket address + * Why is this different than listenAddress()? If no host is given, a SocketAddress will be bound + * to the wildcard address (INADDR_ANY or 0.0.0.0 assuming IPv4) by InetSocketAddress. A wildcard + * address used to connect (at least SocketChannel::open) is interpreted as InetAddress::getLocalHost, + * which is wrong for the reasons stated in HostName::getLocalhost. + * + * @return connect socket address */ - SocketAddress address() { + SocketAddress connectAddress() { + return address(HostName.getLocalhost()); + } + + private SocketAddress address(String hostOverride) { if (malformed) { return null; } if (address == null) { - if (host == null) { + if (hostOverride == null) { address = new InetSocketAddress(port); } else { - address = new InetSocketAddress(host, port); + address = new InetSocketAddress(hostOverride, port); } } return address; } - + /** * Obtain a string representation of this address. The return * value from this method may be used to create a new Spec. diff --git a/jrt/tests/com/yahoo/jrt/SpecTest.java b/jrt/tests/com/yahoo/jrt/SpecTest.java index d15b8f95d30..ec88f164a7a 100644 --- a/jrt/tests/com/yahoo/jrt/SpecTest.java +++ b/jrt/tests/com/yahoo/jrt/SpecTest.java @@ -17,7 +17,7 @@ public class SpecTest extends junit.framework.TestCase { assertFalse(spec.malformed()); assertEquals(457, spec.port()); assertNull(spec.host()); - assertTrue(addr.equals(spec.address())); + assertTrue(addr.equals(spec.listenAddress())); } public void testHostPort() { @@ -29,7 +29,7 @@ public class SpecTest extends junit.framework.TestCase { assertFalse(spec.malformed()); assertEquals(457, spec.port()); assertEquals(host, spec.host()); - assertTrue(addr.equals(spec.address())); + assertTrue(addr.equals(spec.listenAddress())); } public void testBogusHostPort() { @@ -41,7 +41,7 @@ public class SpecTest extends junit.framework.TestCase { assertFalse(spec.malformed()); assertEquals(457, spec.port()); assertEquals(host, spec.host()); - assertTrue(addr.equals(spec.address())); + assertTrue(addr.equals(spec.listenAddress())); } public void testSpec1() { @@ -52,7 +52,7 @@ public class SpecTest extends junit.framework.TestCase { assertFalse(spec.malformed()); assertEquals(8080, spec.port()); assertEquals("localhost", spec.host()); - assertTrue(addr.equals(spec.address())); + assertTrue(addr.equals(spec.listenAddress())); } public void testSpec2() { @@ -63,7 +63,7 @@ public class SpecTest extends junit.framework.TestCase { assertFalse(spec.malformed()); assertEquals(8080, spec.port()); assertNull(spec.host()); - assertTrue(addr.equals(spec.address())); + assertTrue(addr.equals(spec.listenAddress())); } public void testBogusSpec1() { @@ -73,7 +73,7 @@ public class SpecTest extends junit.framework.TestCase { assertTrue(spec.malformed()); assertEquals(0, spec.port()); assertNull(spec.host()); - assertNull(spec.address()); + assertNull(spec.listenAddress()); } public void testBogusSpec2() { @@ -83,7 +83,7 @@ public class SpecTest extends junit.framework.TestCase { assertTrue(spec.malformed()); assertEquals(0, spec.port()); assertNull(spec.host()); - assertNull(spec.address()); + assertNull(spec.listenAddress()); } public void testBogusSpec3() { @@ -93,6 +93,6 @@ public class SpecTest extends junit.framework.TestCase { assertTrue(spec.malformed()); assertEquals(0, spec.port()); assertNull(spec.host()); - assertNull(spec.address()); + assertNull(spec.listenAddress()); } } diff --git a/vespajlib/src/main/java/com/yahoo/net/HostName.java b/vespajlib/src/main/java/com/yahoo/net/HostName.java index 3c87b6c112c..a2782b7a2b3 100644 --- a/vespajlib/src/main/java/com/yahoo/net/HostName.java +++ b/vespajlib/src/main/java/com/yahoo/net/HostName.java @@ -30,11 +30,9 @@ public class HostName { private static String cachedHostName = null; /** - * Return a fully qualified hostname that resolves to an IP address on a network interface. - * Normally this is the same as the 'hostname' command, but if that's not reachable a hostname - * for a reachable IP address is returned which is reachable , but on dev machines on WiFi, - * that IP isn't configured so we prefer a WiFi network interface IP address which is both reachable and - * has a DNS entry. + * Return a public and fully qualified hostname for localhost that resolves to an IP address on + * a network interface. Normally this is the same as the 'hostname' command, but on dev machines on WiFi + * that IP isn't configured, so we find the DNS entry corresponding to the WiFi IP address. * * @return the preferred name of localhost * @throws RuntimeException if accessing the network or the 'hostname' command fails @@ -93,7 +91,7 @@ public class HostName { return reachableNonLocalIp6Addresses.get(0).getHostName(); } - // Fall back to localhost. + // Fall back to InetAddress' localhost. return InetAddress.getLocalHost().getCanonicalHostName(); } @@ -116,8 +114,10 @@ public class HostName { return Optional.empty(); } - // public for testing purposes (all testing machines should have a hostname - public static String getSystemHostName() throws Exception { + /** + * DO NOT USE: Package-private for testing purposes (all testing machines should have a hostname) + */ + static String getSystemHostName() throws Exception { Process process = Runtime.getRuntime().exec("hostname"); BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream())); String hostname = in.readLine(); |