aboutsummaryrefslogtreecommitdiffstats
path: root/clustercontroller-core
diff options
context:
space:
mode:
authorHarald Musum <musum@verizonmedia.com>2020-11-19 13:08:04 +0100
committerHarald Musum <musum@verizonmedia.com>2020-11-19 13:08:04 +0100
commit8cf510b52c3ad9da66dac723d0e9c4097755ac7a (patch)
tree78c2ae881605d29df14d37bdb5770689e9bb1942 /clustercontroller-core
parent5fd44d7a3e068bdb230b055511ecc66dcc1999e6 (diff)
Remove code in StatusPageServer, keep some inner classes temporarily
Diffstat (limited to 'clustercontroller-core')
-rw-r--r--clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/status/statuspage/StatusPageServer.java270
-rw-r--r--clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/FleetControllerTest.java13
-rw-r--r--clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/MasterElectionTest.java12
-rw-r--r--clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/StatusPagesTest.java374
4 files changed, 14 insertions, 655 deletions
diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/status/statuspage/StatusPageServer.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/status/statuspage/StatusPageServer.java
index 3d3de32c356..5920a7d651a 100644
--- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/status/statuspage/StatusPageServer.java
+++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/status/statuspage/StatusPageServer.java
@@ -1,25 +1,10 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.clustercontroller.core.status.statuspage;
-import com.yahoo.exception.ExceptionUtils;
-import java.util.logging.Level;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketTimeoutException;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
-import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.TimeZone;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -27,238 +12,10 @@ import java.util.regex.Pattern;
/**
* Shows status pages with debug information through a very simple HTTP interface.
*/
-public class StatusPageServer implements Runnable, StatusPageServerInterface {
+public class StatusPageServer {
public static Logger log = Logger.getLogger(StatusPageServer.class.getName());
- private final com.yahoo.vespa.clustercontroller.core.Timer timer;
- private final Object monitor;
- private ServerSocket ssocket;
- private final Thread runner;
- private int port = 0;
- private boolean running = true;
- private boolean shouldBeConnected = false;
- private HttpRequest currentHttpRequest = null;
- private StatusPageResponse currentResponse = null;
- private long lastConnectErrorTime = 0;
- private String lastConnectError = "";
- private PatternRequestRouter staticContentRouter = new PatternRequestRouter();
- private Date startTime = new Date();
-
- public StatusPageServer(com.yahoo.vespa.clustercontroller.core.Timer timer, Object monitor, int port) throws java.io.IOException, InterruptedException {
- this.timer = timer;
- this.monitor = monitor;
- this.port = port;
- connect();
- runner = new Thread(this);
- runner.start();
- }
-
- public boolean isConnected() {
- if (ssocket != null && ssocket.isBound() && (ssocket.getLocalPort() == port || port == 0)) {
- return true;
- } else {
- log.log(Level.FINEST, "Status page server socket is no longer connected: "+ (ssocket != null) + " " + ssocket.isBound() + " " + ssocket.getLocalPort() + " " + port);
- return false;
- }
- }
-
- public void connect() throws java.io.IOException, InterruptedException {
- synchronized(monitor) {
- if (ssocket != null) {
- if (ssocket.isBound() && ssocket.getLocalPort() == port) {
- return;
- }
- disconnect();
- }
- ssocket = new ServerSocket();
- if (port != 0) {
- ssocket.setReuseAddress(true);
- }
- ssocket.setSoTimeout(100);
- ssocket.bind(new InetSocketAddress(port));
- shouldBeConnected = true;
- for (int i=0; i<200; ++i) {
- if (isConnected()) break;
- Thread.sleep(10);
- }
- if (!isConnected()) {
- log.log(Level.INFO, "Fleetcontroller: Server Socket not ready after connect()");
- }
- log.log(Level.FINE, "Fleet controller status page viewer listening to " + ssocket.getLocalSocketAddress());
- monitor.notifyAll();
- }
- }
-
- public void disconnect() throws java.io.IOException {
- synchronized(monitor) {
- shouldBeConnected = false;
- if (ssocket != null) ssocket.close();
- ssocket = null;
- monitor.notifyAll();
- }
- }
-
- public void setPort(int port) throws java.io.IOException, InterruptedException {
- // Only bother to reconnect if we were connected to begin with, we care about what port it runs on, and it's not already running there
- if (port != 0 && isConnected() && port != ((InetSocketAddress) ssocket.getLocalSocketAddress()).getPort()) {
- log.log(Level.INFO, "Exchanging port used by status server. Moving from port "
- + ((InetSocketAddress) ssocket.getLocalSocketAddress()).getPort() + " to port " + port);
- disconnect();
- this.port = port;
- if (ssocket == null || !ssocket.isBound() || ssocket.getLocalPort() != port) {
- connect();
- }
- } else {
- this.port = port;
- }
- }
-
- public int getPort() {
- // Cannot use this.port, because of tests using port 0 to get any address
- if (ssocket == null || !ssocket.isBound()) {
- throw new IllegalStateException("Cannot ask for port before server socket is bound");
- }
- return ((InetSocketAddress) ssocket.getLocalSocketAddress()).getPort();
- }
-
- public void shutdown() throws InterruptedException, java.io.IOException {
- running = false;
- runner.interrupt();
- runner.join();
- disconnect();
- }
-
- public void run() {
- try{
- while (running) {
- Socket connection = null;
- ServerSocket serverSocket = null;
- synchronized(monitor) {
- if (ssocket == null || !ssocket.isBound()) {
- monitor.wait(1000);
- continue;
- }
- serverSocket = ssocket;
- }
- try{
- connection = serverSocket.accept();
- } catch (SocketTimeoutException e) {
- // Ignore, since timeout is set to 100 ms
- } catch (java.io.IOException e) {
- log.log(shouldBeConnected ? Level.WARNING : Level.FINE, "Caught IO exception in ServerSocket.accept(): " + e.getMessage());
- }
- if (connection == null) continue;
- log.log(Level.FINE, "Got a status page request.");
- String requestString = "";
- OutputStream output = null;
- try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
- StringBuilder sb = new StringBuilder();
- while (true) {
- String s = br.readLine();
- if (s == null) throw new java.io.IOException("No data in HTTP request on socket " + connection.toString());
- if (s.length() > 4 && s.substring(0,4).equals("GET ")) {
- int nextSpace = s.indexOf(' ', 4);
- if (nextSpace == -1) {
- requestString = s.substring(4);
- } else {
- requestString = s.substring(4, nextSpace);
- }
- }
- if (s == null || s.equals("")) break;
- sb.append(s).append("\n");
- }
- log.log(Level.FINE, "Got HTTP request: " + sb.toString());
-
- HttpRequest httpRequest = null;
- StatusPageResponse response = null;
- try {
- httpRequest = new HttpRequest(requestString);
- // Static files are served directly by the HTTP server thread, since
- // it makes no sense to go via the fleetcontroller logic for these.
- RequestHandler contentHandler = staticContentRouter.resolveHandler(httpRequest);
- if (contentHandler != null) {
- response = contentHandler.handle(httpRequest);
- }
- } catch (Exception e) {
- response = new StatusPageResponse();
- response.setResponseCode(StatusPageResponse.ResponseCode.INTERNAL_SERVER_ERROR);
- StringBuilder content = new StringBuilder();
- response.writeHtmlHeader(content, "Internal Server Error");
- response.writeHtmlFooter(content, ExceptionUtils.getStackTraceAsString(e));
- response.writeContent(content.toString());
- }
- if (response == null) {
- synchronized(monitor) {
- currentHttpRequest = httpRequest;
- currentResponse = null;
- while (running) {
- if (currentResponse != null) {
- response = currentResponse;
- break;
- }
- monitor.wait(100);
- }
- }
- }
- if (response == null) {
- response = new StatusPageResponse();
- StringBuilder content = new StringBuilder();
- response.setContentType("text/html");
- response.writeHtmlHeader(content, "Failed to get response. Fleet controller probably in the process of shutting down.");
- response.writeHtmlFooter(content, "");
- response.writeContent(content.toString());
- }
-
- output = connection.getOutputStream();
- StringBuilder header = new StringBuilder();
- // TODO: per-response cache control
- header.append("HTTP/1.1 ")
- .append(response.getResponseCode().getCode())
- .append(" ")
- .append(response.getResponseCode().getMessage())
- .append("\r\n")
- .append("Date: ").append(new Date().toString()).append("\r\n")
- .append("Connection: Close\r\n")
- .append("Content-type: ").append(response.getContentType()).append("\r\n");
- if (response.isClientCachingEnabled()) {
- // TODO(vekterli): would be better to let HTTP handlers set header values in response
- DateFormat df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z");
- df.setTimeZone(TimeZone.getTimeZone("GMT"));
- header.append("Last-Modified: ").append(df.format(startTime)).append("\r\n");
- } else {
- header.append("Expires: Fri, 01 Jan 1990 00:00:00 GMT\r\n")
- .append("Pragma: no-cache\r\n")
- .append("Cache-control: no-cache, must-revalidate\r\n");
- }
- header.append("\r\n");
- output.write(header.toString().getBytes());
- output.write(response.getOutputStream().toByteArray());
- } catch (java.io.IOException e) {
- log.log(e.getMessage().indexOf("Broken pipe") >= 0 ? Level.FINE : Level.INFO,
- "Failed to process HTTP request : " + e.getMessage());
- } catch (Exception e) {
- log.log(Level.WARNING, "Caught exception in HTTP server thread: "
- + e.getClass().getName() + ": " + e.getMessage());
- } finally {
- if (output != null) try {
- output.close();
- } catch (IOException e) {
- log.log(e.getMessage().indexOf("Broken pipe") >= 0 ? Level.FINE : Level.INFO,
- "Failed to close output stream on socket " + connection + ": " + e.getMessage());
- }
- if (connection != null) try{
- connection.close();
- } catch (IOException e) {
- log.log(Level.INFO, "Failed to close socket " + connection + ": " + e.getMessage());
- }
- }
- }
- } catch (InterruptedException e) {
- log.log(Level.FINE, "Status processing thread shut down by interrupt exception: " + e);
- }
- }
-
/**
* Very simple HTTP request class. This should be replaced the second
* the fleetcontroller e.g. moves into the container.
@@ -377,29 +134,4 @@ public class StatusPageServer implements Runnable, StatusPageServerInterface {
}
}
- public HttpRequest getCurrentHttpRequest() {
- synchronized (monitor) {
- return currentHttpRequest;
- }
- }
-
- public void answerCurrentStatusRequest(StatusPageResponse r) {
- if (!isConnected()) {
- long time = timer.getCurrentTimeInMillis();
- try{
- connect();
- } catch (Exception e) {
- if (!e.getMessage().equals(lastConnectError) || time - lastConnectErrorTime > 60 * 1000) {
- lastConnectError = e.getMessage();
- lastConnectErrorTime = time;
- log.log(Level.WARNING, "Failed to initialize HTTP status server server socket: " + e.getMessage());
- }
- }
- }
- synchronized (monitor) {
- currentResponse = r;
- currentHttpRequest = null; // Avoid fleetcontroller processing request more than once
- }
- }
-
}
diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/FleetControllerTest.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/FleetControllerTest.java
index 1587e2696b8..f8bf387ce41 100644
--- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/FleetControllerTest.java
+++ b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/FleetControllerTest.java
@@ -9,7 +9,6 @@ import com.yahoo.jrt.Target;
import com.yahoo.jrt.Transport;
import com.yahoo.jrt.slobrok.api.BackOffPolicy;
import com.yahoo.jrt.slobrok.server.Slobrok;
-import java.util.logging.Level;
import com.yahoo.log.LogSetup;
import com.yahoo.vdslib.distribution.ConfiguredNode;
import com.yahoo.vdslib.state.ClusterState;
@@ -22,7 +21,7 @@ import com.yahoo.vespa.clustercontroller.core.database.ZooKeeperDatabaseFactory;
import com.yahoo.vespa.clustercontroller.core.rpc.RPCCommunicator;
import com.yahoo.vespa.clustercontroller.core.rpc.RpcServer;
import com.yahoo.vespa.clustercontroller.core.rpc.SlobrokClient;
-import com.yahoo.vespa.clustercontroller.core.status.statuspage.StatusPageServer;
+import com.yahoo.vespa.clustercontroller.core.status.StatusHandler;
import com.yahoo.vespa.clustercontroller.core.status.statuspage.StatusPageServerInterface;
import com.yahoo.vespa.clustercontroller.core.testutils.WaitCondition;
import com.yahoo.vespa.clustercontroller.core.testutils.WaitTask;
@@ -40,9 +39,11 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
+import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -149,6 +150,7 @@ public abstract class FleetControllerTest implements Waiter {
}
FleetController createFleetController(boolean useFakeTimer, FleetControllerOptions options, boolean startThread, StatusPageServerInterface status) throws Exception {
+ Objects.requireNonNull(status, "status server cannot be null");
Timer timer = useFakeTimer ? this.timer : new RealTimer();
MetricUpdater metricUpdater = new MetricUpdater(new NoMetricReporter(), options.fleetControllerIndex);
EventLog log = new EventLog(timer, metricUpdater);
@@ -169,9 +171,6 @@ public abstract class FleetControllerTest implements Waiter {
options.nodeStateRequestRoundTripTimeMaxSeconds);
SlobrokClient lookUp = new SlobrokClient(timer);
lookUp.setSlobrokConnectionSpecs(new String[0]);
- if (status == null) {
- status = new StatusPageServer(timer, timer, options.httpPort);
- }
RpcServer rpcServer = new RpcServer(timer, timer, options.clusterName, options.fleetControllerIndex, options.slobrokBackOffPolicy);
DatabaseHandler database = new DatabaseHandler(new ZooKeeperDatabaseFactory(), timer, options.zooKeeperServerAddress, options.fleetControllerIndex, timer);
StateChangeHandler stateGenerator = new StateChangeHandler(timer, log, metricUpdater);
@@ -189,7 +188,7 @@ public abstract class FleetControllerTest implements Waiter {
}
protected void setUpFleetController(boolean useFakeTimer, FleetControllerOptions options, boolean startThread) throws Exception {
- setUpFleetController(useFakeTimer, options, startThread, null);
+ setUpFleetController(useFakeTimer, options, startThread, new StatusHandler.ContainerStatusPageServer());
}
protected void setUpFleetController(boolean useFakeTimer, FleetControllerOptions options, boolean startThread, StatusPageServerInterface status) throws Exception {
if (slobrok == null) setUpSystem(useFakeTimer, options);
@@ -209,7 +208,7 @@ public abstract class FleetControllerTest implements Waiter {
void startFleetController() throws Exception {
if (fleetController == null) {
- fleetController = createFleetController(usingFakeTimer, options, true, null);
+ fleetController = createFleetController(usingFakeTimer, options, true, new StatusHandler.ContainerStatusPageServer());
} else {
log.log(Level.WARNING, "already started fleetcontroller, not starting another");
}
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 d14f6701288..896f73ce6bf 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
@@ -12,6 +12,7 @@ import com.yahoo.vdslib.state.ClusterState;
import com.yahoo.vdslib.state.NodeState;
import com.yahoo.vdslib.state.NodeType;
import com.yahoo.vdslib.state.State;
+import com.yahoo.vespa.clustercontroller.core.status.StatusHandler;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
@@ -60,7 +61,7 @@ public class MasterElectionTest extends FleetControllerTest {
for (int i=0; i<count; ++i) {
FleetControllerOptions nodeOptions = options.clone();
nodeOptions.fleetControllerIndex = i;
- fleetControllers.add(createFleetController(usingFakeTimer, nodeOptions, true, null));
+ fleetControllers.add(createFleetController(usingFakeTimer, nodeOptions, true, new StatusHandler.ContainerStatusPageServer()));
}
}
@@ -143,14 +144,15 @@ public class MasterElectionTest extends FleetControllerTest {
assertFalse("Fleet controller " + i, fleetControllers.get(i).isMaster());
}
+ StatusHandler.ContainerStatusPageServer statusPageServer = new StatusHandler.ContainerStatusPageServer();
log.log(Level.INFO, "STARTING FLEET CONTROLLER 2");
- fleetControllers.set(2, createFleetController(usingFakeTimer, fleetControllers.get(2).getOptions(), true, null));
+ fleetControllers.set(2, createFleetController(usingFakeTimer, fleetControllers.get(2).getOptions(), true, statusPageServer));
waitForMaster(2);
log.log(Level.INFO, "STARTING FLEET CONTROLLER 0");
- fleetControllers.set(0, createFleetController(usingFakeTimer, fleetControllers.get(0).getOptions(), true, null));
+ fleetControllers.set(0, createFleetController(usingFakeTimer, fleetControllers.get(0).getOptions(), true, statusPageServer));
waitForMaster(0);
log.log(Level.INFO, "STARTING FLEET CONTROLLER 1");
- fleetControllers.set(1, createFleetController(usingFakeTimer, fleetControllers.get(1).getOptions(), true, null));
+ fleetControllers.set(1, createFleetController(usingFakeTimer, fleetControllers.get(1).getOptions(), true, statusPageServer));
waitForMaster(0);
log.log(Level.INFO, "SHUTTING DOWN FLEET CONTROLLER 4");
@@ -538,7 +540,7 @@ public class MasterElectionTest extends FleetControllerTest {
waitForMaster(1);
waitForCompleteCycle(1);
- fleetControllers.set(0, createFleetController(usingFakeTimer, fleetControllers.get(0).getOptions(), true, null));
+ fleetControllers.set(0, createFleetController(usingFakeTimer, fleetControllers.get(0).getOptions(), true, new StatusHandler.ContainerStatusPageServer()));
waitForMaster(0);
waitForCompleteCycle(0);
diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/StatusPagesTest.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/StatusPagesTest.java
deleted file mode 100644
index f761538cf1e..00000000000
--- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/StatusPagesTest.java
+++ /dev/null
@@ -1,374 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.vdslib.distribution.Distribution;
-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.status.StatusHandler;
-import com.yahoo.vespa.clustercontroller.core.status.statuspage.StatusPageResponse;
-import com.yahoo.vespa.clustercontroller.core.status.statuspage.StatusPageServer;
-import com.yahoo.vespa.clustercontroller.utils.communication.http.HttpRequest;
-import com.yahoo.vespa.clustercontroller.utils.communication.http.HttpResult;
-import org.codehaus.jettison.json.JSONObject;
-import org.junit.Test;
-
-import java.io.BufferedWriter;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
-import java.net.Socket;
-import java.nio.charset.StandardCharsets;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.TimeZone;
-import java.util.logging.Logger;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-public class StatusPagesTest extends FleetControllerTest {
-
- public static Logger log = Logger.getLogger(StatusPagesTest.class.getName());
-
- private String doHttpGetRequest(String request, Date ifModifiedSince) throws IOException {
- int statusPort = fleetController.getHttpPort();
- Socket socket = new Socket("localhost", statusPort);
-
- BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
- bw.write("GET " + request + " HTTP/1.1\r\n");
- if (ifModifiedSince != null) {
- DateFormat df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z");
- df.setTimeZone(TimeZone.getTimeZone("GMT"));
- bw.write("If-Modified-Since: " + df.format(ifModifiedSince) + "\r\n");
- }
- bw.write("\r\n");
- bw.flush();
-
- InputStream stream = socket.getInputStream();
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- try {
- byte [] buf = new byte[4096];
- while (true) {
- int read = stream.read(buf);
- if (read<=0) {
- break;
- }
- output.write(buf, 0, read);
- }
- output.close();
- return output.toString();
- } finally {
- stream.close();
- bw.close();
- }
- }
-
- private String doHttpGetRequest(String request) throws IOException {
- return doHttpGetRequest(request, null);
- }
-
- @Test
- public void testStatusThroughContainer() throws Exception {
- startingTest("StatusPagesTest::testStatusThroughContainer()");
- FleetControllerOptions options = defaultOptions("mycluster");
- options.setStorageDistribution(new Distribution(Distribution.getDefaultDistributionConfig(3, 10)));
- final StatusHandler.ContainerStatusPageServer statusServer = new StatusHandler.ContainerStatusPageServer();
- setUpFleetController(true, options, true, statusServer);
- setUpVdsNodes(true, new DummyVdsNodeOptions());
- waitForStableSystem();
-
- //ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 100, 100, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1000));
- //FleetControllerComponent fcComp = new FleetControllerComponent();
- //fcComp.addFleetController("mycluster", fleetController, statusServer);
- StatusHandler comp = new StatusHandler(new StatusHandler.ClusterStatusPageServerSet() {
- @Override
- public StatusHandler.ContainerStatusPageServer get(String cluster) {
- return ("mycluster".equals(cluster) ? statusServer : null);
- }
-
- @Override
- public Map<String, StatusHandler.ContainerStatusPageServer> getAll() {
- Map<String, StatusHandler.ContainerStatusPageServer> map = new HashMap<>();
- map.put("mycluster", statusServer);
- return map;
- }
- });
-
- {
- HttpRequest request = new HttpRequest().setPath("/clustercontroller-status/v1");
- HttpResult result = comp.handleRequest(request);
- assertEquals(result.toString(true), 200, result.getHttpReturnCode());
- assertEquals("<title>clusters</title>\n<a href=\"./mycluster\">mycluster</a><br>\n", result.getContent().toString());
- }
- {
- HttpRequest request = new HttpRequest().setPath("/clustercontroller-status/v1/");
- HttpResult result = comp.handleRequest(request);
- assertEquals(result.toString(true), 200, result.getHttpReturnCode());
- assertEquals("<title>clusters</title>\n<a href=\"./mycluster\">mycluster</a><br>\n", result.getContent().toString());
- }
- {
- HttpRequest request = new HttpRequest().setPath("/clustercontroller-status/v1/mycluster");
- HttpResult result = comp.handleRequest(request);
- assertEquals(result.toString(true), 200, result.getHttpReturnCode());
- assertTrue(result.toString(true), result.getContent().toString().contains(
- "mycluster Cluster Controller 0 Status Page"));
- }
- {
- HttpRequest request = new HttpRequest().setPath("/clustercontroller-status/v1/mycluster/");
- HttpResult result = comp.handleRequest(request);
- assertEquals(result.toString(true), 200, result.getHttpReturnCode());
- assertTrue(result.toString(true), result.getContent().toString().contains(
- "mycluster Cluster Controller 0 Status Page"));
- assertTrue(result.toString(true), result.getContent().toString().contains(
- "href=\"mycluster/node=distributor.0\""));
- assertTrue(result.toString(true), result.getContent().toString().contains(
- "href=\"mycluster/node=storage.0\""));
- }
- {
- HttpRequest request = new HttpRequest().setPath("/clustercontroller-status/v1/mycluster/node=storage.0");
- HttpResult result = comp.handleRequest(request);
- assertEquals(result.toString(true), 200, result.getHttpReturnCode());
- assertTrue(result.toString(true), result.getContent().toString().contains(
- "Node status for storage.0"));
- assertTrue(result.toString(true), result.getContent().toString().contains(
- "href=\"..\""));
- }
- {
- HttpRequest request = new HttpRequest().setPath("/clustercontroller-status/v1/foo");
- HttpResult result = comp.handleRequest(request);
- assertEquals(result.toString(true), 404, result.getHttpReturnCode());
- }
- {
- HttpRequest request = new HttpRequest().setPath("/foobar/v1/mycluster/");
- HttpResult result = comp.handleRequest(request);
- assertEquals(result.toString(true), 404, result.getHttpReturnCode());
- }
- {
- HttpRequest request = new HttpRequest().setPath("/clustercontroller-status/v2/");
- HttpResult result = comp.handleRequest(request);
- assertEquals(result.toString(true), 404, result.getHttpReturnCode());
- }
- //executor.shutdown();
- }
-
- @Test
- public void testZooKeeperAddressSplitting() {
- String rawAddress = "conc1.foo.yahoo.com:2181,conc2.foo.yahoo.com:2181,"
- + "dp1.foo.yahoo.com:2181,dp2.foo.yahoo.com:2181,"
- + "dp3.foo.yahoo.com:2181";
- String result = "conc1.foo.yahoo.com:2181, conc2.foo.yahoo.com:2181, "
- + "dp1.foo.yahoo.com:2181, dp2.foo.yahoo.com:2181, "
- + "dp3.foo.yahoo.com:2181";
- String split = FleetControllerOptions.splitZooKeeperAddress(rawAddress);
- assertEquals(result, split);
- }
-
- @Test
- public void testSimpleConnectionWithSomeContent() throws Exception {
- // Set this to true temporary if you want to check status page from browser. Should be false in checked in code always.
- boolean haltTestToViewStatusPage = false;
- startingTest("StatusPagesTest::testSimpleConnectionWithSomeContent()");
- FleetControllerOptions options = defaultOptions("mycluster");
- options.setStorageDistribution(new Distribution(Distribution.getDefaultDistributionConfig(3, 10)));
- //options.minRatioOfStorageNodesUp = 0.99;
- if (haltTestToViewStatusPage) {
- options.httpPort = 19234;
- }
- setUpFleetController(true, options);
- setUpVdsNodes(true, new DummyVdsNodeOptions());
- waitForStableSystem();
-
- nodes.get(2).disconnectBreakConnection();
- nodes.get(5).disconnectAsShutdown();
- nodes.get(7).disconnectSlobrok();
-
- fleetController.getCluster().getNodeInfo(new Node(NodeType.STORAGE, 3)).setWantedState(new NodeState(NodeType.STORAGE, State.MAINTENANCE).setDescription("Test&<>special"));
-
- String content = doHttpGetRequest("/");
-
- assertTrue(content, content.contains("<html>"));
- assertTrue(content, content.contains("</html>"));
- assertTrue(content, content.contains("Baseline cluster state"));
- assertTrue(content, content.contains("Cluster states"));
- assertTrue(content, content.contains("Event log"));
-
- if (haltTestToViewStatusPage) {
- System.err.println(content);
- try{
- Thread.sleep(1000000);
- } catch (InterruptedException e) {}
- }
- }
-
- @Test
- public void testNodePage() throws Exception {
- startingTest("StatusPagesTest::testNodePage()");
- FleetControllerOptions options = defaultOptions("mycluster");
- options.setStorageDistribution(new Distribution(Distribution.getDefaultDistributionConfig(3, 10)));
- setUpFleetController(true, options);
- setUpVdsNodes(true, new DummyVdsNodeOptions());
- waitForStableSystem();
-
- String content = doHttpGetRequest("/node=storage.0");
-
- assertTrue(content, content.contains("<html>"));
- assertTrue(content, content.contains("</html>"));
- assertTrue(content, content.contains("Node status for storage.0"));
- assertTrue(content, content.contains("REPORTED"));
- assertTrue(content, content.contains("Altered node state in cluster state from"));
- //System.err.println(sb.toString());
- }
-
- @Test
- public void testErrorResponseCode() throws Exception {
- startingTest("StatusPagesTest::testNodePage()");
- FleetControllerOptions options = defaultOptions("mycluster");
- options.setStorageDistribution(new Distribution(Distribution.getDefaultDistributionConfig(3, 10)));
- setUpFleetController(true, options);
- setUpVdsNodes(true, new DummyVdsNodeOptions());
- waitForStableSystem();
-
- String content = doHttpGetRequest("/fraggle/rock");
-
- assertTrue(content.contains("404 Not Found"));
- //System.err.println(sb.toString());
- }
-
- private StatusPageServer.HttpRequest makeHttpRequest(String request) {
- return new StatusPageServer.HttpRequest(request);
- }
-
- @Test
- public void testHttpRequestParsing() {
- {
- StatusPageServer.HttpRequest request = makeHttpRequest("/") ;
- assertEquals("/", request.getPath());
- assertFalse(request.hasQueryParameters());
- }
- {
- StatusPageServer.HttpRequest request = makeHttpRequest("/foo/bar");
- assertEquals("/foo/bar", request.getPath());
- assertFalse(request.hasQueryParameters());
- }
- {
- StatusPageServer.HttpRequest request = makeHttpRequest("/foo/bar?baz=baff");
- assertEquals("/foo/bar", request.getPath());
- assertTrue(request.hasQueryParameters());
- assertEquals("baff", request.getQueryParameter("baz"));
- }
- {
- StatusPageServer.HttpRequest request = makeHttpRequest("/?baz=baff&blarg=blee");
- assertEquals("/", request.getPath());
- assertTrue(request.hasQueryParameters());
- assertEquals("baff", request.getQueryParameter("baz"));
- assertEquals("blee", request.getQueryParameter("blarg"));
- }
- {
- StatusPageServer.HttpRequest request = makeHttpRequest("/node=storage.101?showlocal");
- assertEquals("/node=storage.101", request.getPath());
- assertTrue(request.hasQueryParameters());
- assertTrue(request.hasQueryParameter("showlocal"));
- assertNull(request.getQueryParameter("showlocal"));
- }
- }
-
- private static class DummyRequestHandler implements StatusPageServer.RequestHandler {
- private String returnData;
- DummyRequestHandler(String returnData) {
- this.returnData = returnData;
- }
-
- @Override
- public StatusPageResponse handle(StatusPageServer.HttpRequest request) {
- StatusPageResponse response = new StatusPageResponse();
- response.writeContent(returnData);
- return response;
- }
- }
-
- private String invokeHandler(StatusPageServer.RequestRouter router, String request) {
- StatusPageServer.HttpRequest httpRequest = makeHttpRequest(request);
- StatusPageServer.RequestHandler handler = router.resolveHandler(httpRequest);
- if (handler == null) {
- return null;
- }
- return handler.handle(httpRequest).getOutputStream().toString(StandardCharsets.UTF_8);
- }
-
- @Test
- public void testRequestRouting() {
- StatusPageServer.PatternRequestRouter router = new StatusPageServer.PatternRequestRouter();
- router.addHandler("^/alerts/red.*", new DummyRequestHandler("red alert!"));
- router.addHandler("^/alerts.*", new DummyRequestHandler("beige alert"));
- router.addHandler("^/$", new DummyRequestHandler("root"));
- assertEquals("root", invokeHandler(router, "/"));
- assertEquals("beige alert", invokeHandler(router, "/alerts"));
- assertEquals("beige alert", invokeHandler(router, "/alerts?foo"));
- assertEquals("red alert!", invokeHandler(router, "/alerts/red"));
- assertEquals("red alert!", invokeHandler(router, "/alerts/red/blue"));
- assertNull(invokeHandler(router, "/blarg"));
- }
-
- private String[] getResponseParts(String response) {
- int offset = response.indexOf("\r\n\r\n");
- if (offset == -1) {
- throw new IllegalStateException("No HTTP header delimiter found");
- }
- return new String[] {
- response.substring(0, offset + 2), // all header lines must have linebreaks
- response.substring(offset + 4)
- };
- }
-
- @Test
- public void testStateServing() throws Exception {
- startingTest("StatusPagesTest::testStateServing()");
- FleetControllerOptions options = defaultOptions("mycluster");
- setUpFleetController(true, options);
- fleetController.updateOptions(options, 5);
- waitForCompleteCycle();
- {
- String content = doHttpGetRequest("/state/v1/health");
- String[] parts = getResponseParts(content);
- String body = parts[1];
- String expected =
- "{\n" +
- " \"status\" : {\n" +
- " \"code\" : \"up\"\n" +
- " },\n" +
- " \"config\" : {\n" +
- " \"component\" : {\n" +
- " \"generation\" : 5\n" +
- " }\n" +
- " }\n" +
- "}";
- assertEquals(expected, body);
- // Check that it actually parses
- new JSONObject(expected);
- }
- }
-
- @Test
- public void testClusterStateServing() throws Exception {
- startingTest("StatusPagesTest::testClusterStateServing()");
- FleetControllerOptions options = defaultOptions("mycluster");
- setUpFleetController(true, options);
- fleetController.updateOptions(options, 5);
- waitForCompleteCycle();
- {
- String content = doHttpGetRequest("/clusterstate");
- String[] parts = getResponseParts(content);
- String body = parts[1];
- String expected = "version:2 cluster:d";
- assertEquals(expected, body);
- }
- }
-}