aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeir Storli <geirst@oath.com>2018-03-15 16:58:51 +0100
committerGeir Storli <geirst@oath.com>2018-03-15 16:58:51 +0100
commita1946bc5279d09e8f41717f2ab5ed590aab5ab67 (patch)
treee3bc4b46fcda1e79e1546f6664033f9d311c8c1e
parent42ed2f6d0954acd25a9cd3fb3367710f77144d42 (diff)
Extend cluster v2 to output the published distribution state.
This is the baseline cluster state + per bucket space states.
-rw-r--r--clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/FleetController.java3
-rw-r--r--clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/RemoteClusterControllerTask.java3
-rw-r--r--clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/Response.java16
-rw-r--r--clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/ClusterStateRequest.java13
-rw-r--r--clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/NodeStateRequest.java2
-rw-r--r--clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/PartitionStateRequest.java2
-rw-r--r--clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStateRequest.java2
-rw-r--r--clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStatesForClusterRequest.java11
-rw-r--r--clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/ClusterControllerMock.java4
-rw-r--r--clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/ClusterListTest.java21
-rw-r--r--clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/ClusterTest.java27
-rw-r--r--clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/NodeTest.java2
-rw-r--r--clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/StateRestApiTest.java20
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/response/DistributionState.java26
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/response/DistributionStates.java10
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/response/UnitResponse.java1
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonWriter.java41
-rw-r--r--clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/DummyStateApi.java12
18 files changed, 178 insertions, 38 deletions
diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/FleetController.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/FleetController.java
index 2edebd17700..2e2534916a7 100644
--- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/FleetController.java
+++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/FleetController.java
@@ -698,7 +698,8 @@ public class FleetController implements NodeStateOrHostInfoChangeHandler, NodeAd
private RemoteClusterControllerTask.Context createRemoteTaskProcessingContext() {
final RemoteClusterControllerTask.Context context = new RemoteClusterControllerTask.Context();
context.cluster = cluster;
- context.currentState = consolidatedClusterState();
+ context.currentConsolidatedState = consolidatedClusterState();
+ context.publishedClusterStateBundle = stateVersionTracker.getVersionedClusterStateBundle();
context.masterInfo = masterElectionHandler;
context.nodeStateOrHostInfoChangeHandler = this;
context.nodeAddedOrRemovedListener = this;
diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/RemoteClusterControllerTask.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/RemoteClusterControllerTask.java
index d082158edc7..e96209c083a 100644
--- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/RemoteClusterControllerTask.java
+++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/RemoteClusterControllerTask.java
@@ -9,7 +9,8 @@ public abstract class RemoteClusterControllerTask {
public static class Context {
public ContentCluster cluster;
- public ClusterState currentState;
+ public ClusterState currentConsolidatedState;
+ public ClusterStateBundle publishedClusterStateBundle;
public MasterInterface masterInfo;
public NodeStateOrHostInfoChangeHandler nodeStateOrHostInfoChangeHandler;
public NodeAddedOrRemovedListener nodeAddedOrRemovedListener;
diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/Response.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/Response.java
index 26c66fea165..90cbd80f18c 100644
--- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/Response.java
+++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/Response.java
@@ -68,12 +68,13 @@ public class Response {
}
public static abstract class EmptyResponse<T extends UnitResponse>
- implements UnitResponse, UnitMetrics, UnitAttributes, CurrentUnitState
+ implements UnitResponse, UnitMetrics, UnitAttributes, CurrentUnitState, DistributionStates
{
protected final Map<String, String> attributes = new LinkedHashMap<>();
protected final Map<String, SubUnitList> subUnits = new LinkedHashMap<>();
protected final Map<String, Number> metrics = new LinkedHashMap<>();
protected final Map<String, UnitState> stateMap = new LinkedHashMap<>();
+ protected DistributionState publishedState = null;
@Override
public UnitAttributes getAttributes() { return attributes.isEmpty() ? null : this; }
@@ -84,11 +85,20 @@ public class Response {
@Override
public UnitMetrics getMetrics() { return metrics.isEmpty() ? null : this; }
@Override
+ public DistributionStates getDistributionStates() {
+ return (publishedState == null) ? null : this;
+ }
+
+ @Override
public Map<String, Number> getMetricMap() { return metrics; }
@Override
public Map<String, UnitState> getStatePerType() { return stateMap; }
@Override
public Map<String, String> getAttributeValues() { return attributes; }
+ @Override
+ public DistributionState getPublishedState() {
+ return publishedState;
+ }
public EmptyResponse<T> addLink(String type, String unit, String link) {
Link list = (Link) subUnits.get(type);
@@ -120,6 +130,10 @@ public class Response {
attributes.put(name, value);
return this;
}
+ public EmptyResponse<T> setPublishedState(DistributionState publishedState) {
+ this.publishedState = publishedState;
+ return this;
+ }
}
public static class ClusterListResponse extends EmptyResponse<ClusterResponse> {}
diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/ClusterStateRequest.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/ClusterStateRequest.java
index 2ecc62c303a..122b9d24d40 100644
--- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/ClusterStateRequest.java
+++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/ClusterStateRequest.java
@@ -2,11 +2,15 @@
package com.yahoo.vespa.clustercontroller.core.restapiv2.requests;
import com.yahoo.vdslib.state.NodeType;
+import com.yahoo.vespa.clustercontroller.core.ClusterStateBundle;
import com.yahoo.vespa.clustercontroller.core.RemoteClusterControllerTask;
import com.yahoo.vespa.clustercontroller.core.restapiv2.Id;
import com.yahoo.vespa.clustercontroller.core.restapiv2.Request;
import com.yahoo.vespa.clustercontroller.core.restapiv2.Response;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.StateRestApiException;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.response.DistributionState;
+
+import java.util.stream.Collectors;
public class ClusterStateRequest extends Request<Response.ClusterResponse> {
private final Id.Cluster id;
@@ -21,7 +25,7 @@ public class ClusterStateRequest extends Request<Response.ClusterResponse> {
@Override
public Response.ClusterResponse calculateResult(RemoteClusterControllerTask.Context context) throws StateRestApiException {
Response.ClusterResponse result = new Response.ClusterResponse();
- result.addState("generated", new Response.UnitStateImpl(context.currentState.getClusterState()));
+ result.addState("generated", new Response.UnitStateImpl(context.currentConsolidatedState.getClusterState()));
for (NodeType type : NodeType.getTypes()) {
Id.Service serviceId = new Id.Service(id, type);
if (recursive > 0) {
@@ -31,6 +35,13 @@ public class ClusterStateRequest extends Request<Response.ClusterResponse> {
result.addLink("service", type.toString(), serviceId.toString());
}
}
+ result.setPublishedState(bundleToDistributionState(context.publishedClusterStateBundle));
return result;
}
+
+ private static DistributionState bundleToDistributionState(ClusterStateBundle bundle) {
+ return new DistributionState(bundle.getBaselineClusterState().toString(),
+ bundle.getDerivedBucketSpaceStates().entrySet().stream()
+ .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue().getClusterState().toString())));
+ }
}
diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/NodeStateRequest.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/NodeStateRequest.java
index 669042c2fd8..7f1bfd20124 100644
--- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/NodeStateRequest.java
+++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/NodeStateRequest.java
@@ -35,7 +35,7 @@ public class NodeStateRequest extends Request<Response.NodeResponse> {
result.addAttribute("hierarchical-group", info.getGroup().getPath());
}
- result.addState("generated", new Response.UnitStateImpl(context.currentState.getNodeState(id.getNode())));
+ result.addState("generated", new Response.UnitStateImpl(context.currentConsolidatedState.getNodeState(id.getNode())));
result.addState("unit", new Response.UnitStateImpl(info.getReportedState()));
result.addState("user", new Response.UnitStateImpl(info.getWantedState()));
diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/PartitionStateRequest.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/PartitionStateRequest.java
index f8387984263..b7bcca345e2 100644
--- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/PartitionStateRequest.java
+++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/PartitionStateRequest.java
@@ -31,7 +31,7 @@ public class PartitionStateRequest extends Request<Response.PartitionResponse> {
if (verboseReports.contains(VerboseReport.STATISTICS)) {
fillInMetrics(context.cluster.getNodeInfo(id.getNode()).getHostInfo().getMetrics(), result);
}
- NodeState nodeState = context.currentState.getNodeState(id.getNode());
+ NodeState nodeState = context.currentConsolidatedState.getNodeState(id.getNode());
DiskState diskState = nodeState.getDiskState(id.getPartitionIndex());
result.addState("generated", new Response.UnitStateImpl(diskState));
diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStateRequest.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStateRequest.java
index 5b140ee2d87..ada068808f7 100644
--- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStateRequest.java
+++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStateRequest.java
@@ -50,7 +50,7 @@ public class SetNodeStateRequest extends Request<SetResponse> {
newStates,
id.getNode(),
context.nodeStateOrHostInfoChangeHandler,
- context.currentState);
+ context.currentConsolidatedState);
return setResponse;
}
diff --git a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStatesForClusterRequest.java b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStatesForClusterRequest.java
index a9667042499..3f9e2b48eb5 100644
--- a/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStatesForClusterRequest.java
+++ b/clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/restapiv2/requests/SetNodeStatesForClusterRequest.java
@@ -1,17 +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.restapiv2.requests;
-import com.yahoo.log.LogLevel;
import com.yahoo.vdslib.distribution.ConfiguredNode;
import com.yahoo.vdslib.state.*;
-import com.yahoo.vespa.clustercontroller.core.ContentCluster;
-import com.yahoo.vespa.clustercontroller.core.NodeInfo;
-import com.yahoo.vespa.clustercontroller.core.NodeStateChangeChecker;
import com.yahoo.vespa.clustercontroller.core.RemoteClusterControllerTask;
-import com.yahoo.vespa.clustercontroller.core.listeners.NodeAddedOrRemovedListener;
-import com.yahoo.vespa.clustercontroller.core.listeners.NodeStateOrHostInfoChangeHandler;
import com.yahoo.vespa.clustercontroller.core.restapiv2.Id;
-import com.yahoo.vespa.clustercontroller.core.restapiv2.MissingIdException;
import com.yahoo.vespa.clustercontroller.core.restapiv2.Request;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.InternalFailure;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.InvalidContentException;
@@ -70,14 +63,14 @@ public class SetNodeStatesForClusterRequest extends Request<SetResponse> {
newStates,
node,
context.nodeStateOrHostInfoChangeHandler,
- context.currentState);
+ context.currentConsolidatedState);
if (!setResponse.getWasModified()) {
throw new InternalFailure("We have not yet implemented the meaning of " +
"failing to set the wanted state for a subset of nodes: " +
"condition = " + condition +
", newStates = " + newStates +
- ", currentState = " + context.currentState);
+ ", currentConsolidatedState = " + context.currentConsolidatedState);
}
}
diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/ClusterControllerMock.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/ClusterControllerMock.java
index 2aac8a94f52..472301e1dfc 100644
--- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/ClusterControllerMock.java
+++ b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/ClusterControllerMock.java
@@ -16,11 +16,13 @@ public class ClusterControllerMock implements RemoteClusterControllerTaskSchedul
public StringBuilder events = new StringBuilder();
public ClusterControllerMock(ContentCluster cluster, ClusterState state,
+ ClusterStateBundle publishedClusterStateBundle,
int fcIndex, Integer fcMaster) {
this.fleetControllerIndex = fcIndex;
this.fleetControllerMaster = fcMaster;
context.cluster = cluster;
- context.currentState = state;
+ context.currentConsolidatedState = state;
+ context.publishedClusterStateBundle = publishedClusterStateBundle;
context.masterInfo = new MasterInterface() {
@Override
public boolean isMaster() {
diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/ClusterListTest.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/ClusterListTest.java
index 55e8f6bf84b..813b3780091 100644
--- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/ClusterListTest.java
+++ b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/ClusterListTest.java
@@ -33,7 +33,20 @@ public class ClusterListTest extends StateRestApiTest {
" \"service\": {\n" +
" \"storage\": {\"link\": \"\\/cluster\\/v2\\/books\\/storage\"},\n" +
" \"distributor\": {\"link\": \"\\/cluster\\/v2\\/books\\/distributor\"}\n" +
- " }\n" +
+ " },\n" +
+ " \"distribution-states\": {\"published\": {\n" +
+ " \"baseline\": \"distributor:4 storage:4\",\n" +
+ " \"bucket-spaces\": [\n" +
+ " {\n" +
+ " \"name\": \"default\",\n" +
+ " \"state\": \"distributor:4 storage:4 .3.s:m\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name\": \"global\",\n" +
+ " \"state\": \"distributor:4 storage:4\"\n" +
+ " }\n" +
+ " ]\n" +
+ " }}\n" +
" },\n" +
" \"music\": {\n" +
" \"state\": {\"generated\": {\n" +
@@ -43,7 +56,11 @@ public class ClusterListTest extends StateRestApiTest {
" \"service\": {\n" +
" \"storage\": {\"link\": \"\\/cluster\\/v2\\/music\\/storage\"},\n" +
" \"distributor\": {\"link\": \"\\/cluster\\/v2\\/music\\/distributor\"}\n" +
- " }\n" +
+ " },\n" +
+ " \"distribution-states\": {\"published\": {\n" +
+ " \"baseline\": \"distributor:8 .0.s:d .2.s:d .4.s:d .6.s:d storage:8 .0.s:d .2.s:d .4.s:d .6.s:d\",\n" +
+ " \"bucket-spaces\": []\n" +
+ " }}\n" +
" }\n" +
"}}";
assertEquals(expected, jsonWriter.createJson(response).toString(2));
diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/ClusterTest.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/ClusterTest.java
index 7f088abce12..635ab1f37b3 100644
--- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/ClusterTest.java
+++ b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/ClusterTest.java
@@ -11,7 +11,7 @@ public class ClusterTest extends StateRestApiTest {
@Test
public void testCluster() throws Exception {
setUp(true);
- UnitResponse response = restAPI.getState(new StateRequest("music", 0));
+ UnitResponse response = restAPI.getState(new StateRequest("books", 0));
String expected =
"{\n" +
" \"state\": {\"generated\": {\n" +
@@ -19,9 +19,22 @@ public class ClusterTest extends StateRestApiTest {
" \"reason\": \"\"\n" +
" }},\n" +
" \"service\": {\n" +
- " \"storage\": {\"link\": \"\\/cluster\\/v2\\/music\\/storage\"},\n" +
- " \"distributor\": {\"link\": \"\\/cluster\\/v2\\/music\\/distributor\"}\n" +
- " }\n" +
+ " \"storage\": {\"link\": \"\\/cluster\\/v2\\/books\\/storage\"},\n" +
+ " \"distributor\": {\"link\": \"\\/cluster\\/v2\\/books\\/distributor\"}\n" +
+ " },\n" +
+ " \"distribution-states\": {\"published\": {\n" +
+ " \"baseline\": \"distributor:4 storage:4\",\n" +
+ " \"bucket-spaces\": [\n" +
+ " {\n" +
+ " \"name\": \"default\",\n" +
+ " \"state\": \"distributor:4 storage:4 .3.s:m\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name\": \"global\",\n" +
+ " \"state\": \"distributor:4 storage:4\"\n" +
+ " }\n" +
+ " ]\n" +
+ " }}\n" +
"}";
assertEquals(expected, jsonWriter.createJson(response).toString(2));
}
@@ -51,7 +64,11 @@ public class ClusterTest extends StateRestApiTest {
" \"5\": {\"link\": \"\\/cluster\\/v2\\/music\\/distributor\\/5\"},\n" +
" \"7\": {\"link\": \"\\/cluster\\/v2\\/music\\/distributor\\/7\"}\n" +
" }}\n" +
- " }\n" +
+ " },\n" +
+ " \"distribution-states\": {\"published\": {\n" +
+ " \"baseline\": \"distributor:8 .0.s:d .2.s:d .4.s:d .6.s:d storage:8 .0.s:d .2.s:d .4.s:d .6.s:d\",\n" +
+ " \"bucket-spaces\": []\n" +
+ " }}\n" +
"}";
assertEquals(expected, jsonWriter.createJson(response).toString(2));
}
diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/NodeTest.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/NodeTest.java
index de28867520b..6bd7f086249 100644
--- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/NodeTest.java
+++ b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/NodeTest.java
@@ -124,7 +124,7 @@ public class NodeTest extends StateRestApiTest {
music.context.cluster = new ContentCluster(old.getName(), old.getConfiguredNodes().values(), old.getDistribution(), 0, 0.0);
NodeState currentState = new NodeState(NodeType.STORAGE, State.DOWN);
currentState.setDescription("Not seen");
- music.context.currentState.setNodeState(new Node(NodeType.STORAGE, 1), currentState);
+ music.context.currentConsolidatedState.setNodeState(new Node(NodeType.STORAGE, 1), currentState);
UnitResponse response = restAPI.getState(new StateRequest("music/storage/1", 0));
String expected =
"{\n" +
diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/StateRestApiTest.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/StateRestApiTest.java
index 46a50800c53..5160ecad8b3 100644
--- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/StateRestApiTest.java
+++ b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/restapiv2/StateRestApiTest.java
@@ -4,10 +4,7 @@ package com.yahoo.vespa.clustercontroller.core.restapiv2;
import com.yahoo.vdslib.distribution.ConfiguredNode;
import com.yahoo.vdslib.distribution.Distribution;
import com.yahoo.vdslib.state.*;
-import com.yahoo.vespa.clustercontroller.core.FleetControllerTest;
-import com.yahoo.vespa.clustercontroller.core.NodeInfo;
-import com.yahoo.vespa.clustercontroller.core.RemoteClusterControllerTaskScheduler;
-import com.yahoo.vespa.clustercontroller.core.ContentCluster;
+import com.yahoo.vespa.clustercontroller.core.*;
import com.yahoo.vespa.clustercontroller.core.hostinfo.HostInfo;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.StateRestAPI;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.requests.UnitStateRequest;
@@ -47,8 +44,12 @@ public abstract class StateRestApiTest {
ContentCluster cluster = new ContentCluster(
"books", nodes, distribution, 6 /* minStorageNodesUp*/, 0.9 /* minRatioOfStorageNodesUp */);
initializeCluster(cluster, nodes);
- ClusterState state = new ClusterState("distributor:4 storage:4");
- books = new ClusterControllerMock(cluster, state, 0, 0);
+ AnnotatedClusterState baselineState = AnnotatedClusterState.withoutAnnotations(ClusterState.stateFromString("distributor:4 storage:4"));
+ Map<String, AnnotatedClusterState> bucketSpaceStates = new HashMap<>();
+ bucketSpaceStates.put("default", AnnotatedClusterState.withoutAnnotations(ClusterState.stateFromString("distributor:4 storage:4 .3.s:m")));
+ bucketSpaceStates.put("global", baselineState);
+ books = new ClusterControllerMock(cluster, baselineState.getClusterState(),
+ ClusterStateBundle.of(baselineState, bucketSpaceStates), 0, 0);
}
{
Set<ConfiguredNode> nodes = FleetControllerTest.toNodes(1, 2, 3, 5, 7);
@@ -64,9 +65,10 @@ public abstract class StateRestApiTest {
else {
initializeCluster(cluster, nodes);
}
- ClusterState state = new ClusterState("distributor:8 .0.s:d .2.s:d .4.s:d .6.s:d "
- + "storage:8 .0.s:d .2.s:d .4.s:d .6.s:d");
- music = new ClusterControllerMock(cluster, state, 0, 0);
+ AnnotatedClusterState baselineState = AnnotatedClusterState.withoutAnnotations(ClusterState.stateFromString("distributor:8 .0.s:d .2.s:d .4.s:d .6.s:d "
+ + "storage:8 .0.s:d .2.s:d .4.s:d .6.s:d"));
+ music = new ClusterControllerMock(cluster, baselineState.getClusterState(),
+ ClusterStateBundle.ofBaselineOnly(baselineState), 0, 0);
}
ccSockets = new TreeMap<>();
ccSockets.put(0, new ClusterControllerStateRestAPI.Socket("localhost", 80));
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/response/DistributionState.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/response/DistributionState.java
new file mode 100644
index 00000000000..53a4a07fa76
--- /dev/null
+++ b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/response/DistributionState.java
@@ -0,0 +1,26 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.clustercontroller.utils.staterestapi.response;
+
+import java.util.Map;
+
+/**
+ * A distribution state representing the baseline cluster state and per bucket space states.
+ */
+public class DistributionState {
+ private final String baselineState;
+ private final Map<String, String> bucketSpaceStates;
+
+ public DistributionState(String baselineState,
+ Map<String, String> bucketSpaceStates) {
+ this.baselineState = baselineState;
+ this.bucketSpaceStates = bucketSpaceStates;
+ }
+
+ public String getBaselineState() {
+ return baselineState;
+ }
+
+ public Map<String, String> getBucketSpaceStates() {
+ return bucketSpaceStates;
+ }
+}
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/response/DistributionStates.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/response/DistributionStates.java
new file mode 100644
index 00000000000..e7de760bb64
--- /dev/null
+++ b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/response/DistributionStates.java
@@ -0,0 +1,10 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.clustercontroller.utils.staterestapi.response;
+
+/**
+ * Interface to get the published distribution state.
+ */
+public interface DistributionStates {
+
+ DistributionState getPublishedState();
+}
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/response/UnitResponse.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/response/UnitResponse.java
index 583820f5535..61ed6662493 100644
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/response/UnitResponse.java
+++ b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/response/UnitResponse.java
@@ -9,5 +9,6 @@ public interface UnitResponse {
CurrentUnitState getCurrentState();
Map<String, SubUnitList> getSubUnits();
UnitMetrics getMetrics();
+ DistributionStates getDistributionStates();
}
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonWriter.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonWriter.java
index 11b0dc33610..a5a0e6cbe3d 100644
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonWriter.java
+++ b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonWriter.java
@@ -2,6 +2,7 @@
package com.yahoo.vespa.clustercontroller.utils.staterestapi.server;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.response.*;
+import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
@@ -29,13 +30,25 @@ public class JsonWriter {
public void fillInJson(UnitResponse data, JSONObject json) throws Exception {
UnitAttributes attributes = data.getAttributes();
- if (attributes != null) fillInJson(attributes, json);
+ if (attributes != null) {
+ fillInJson(attributes, json);
+ }
CurrentUnitState stateData = data.getCurrentState();
- if (stateData != null) fillInJson(stateData, json);
+ if (stateData != null) {
+ fillInJson(stateData, json);
+ }
UnitMetrics metrics = data.getMetrics();
- if (metrics != null) fillInJson(metrics, json);
+ if (metrics != null) {
+ fillInJson(metrics, json);
+ }
Map<String, SubUnitList> subUnits = data.getSubUnits();
- if (subUnits != null) fillInJson(subUnits, json);
+ if (subUnits != null) {
+ fillInJson(subUnits, json);
+ }
+ DistributionStates distributionStates = data.getDistributionStates();
+ if (distributionStates != null) {
+ fillInJson(distributionStates, json);
+ }
}
public void fillInJson(CurrentUnitState stateData, JSONObject json) throws Exception {
@@ -85,6 +98,26 @@ public class JsonWriter {
}
}
+ private static void fillInJson(DistributionStates states, JSONObject json) throws Exception {
+ JSONObject statesJson = new JSONObject();
+ statesJson.put("published", distributionStateToJson(states.getPublishedState()));
+ json.put("distribution-states", statesJson);
+ }
+
+ private static JSONObject distributionStateToJson(DistributionState state) throws Exception {
+ JSONObject result = new JSONObject();
+ result.put("baseline", state.getBaselineState());
+ JSONArray bucketSpacesJson = new JSONArray();
+ result.put("bucket-spaces", bucketSpacesJson);
+ for (Map.Entry<String, String> entry : state.getBucketSpaceStates().entrySet()) {
+ JSONObject bucketSpaceJson = new JSONObject();
+ bucketSpaceJson.put("name", entry.getKey());
+ bucketSpaceJson.put("state", entry.getValue());
+ bucketSpacesJson.put(bucketSpaceJson);
+ }
+ return result;
+ }
+
public JSONObject createErrorJson(String description) {
JSONObject o = new JSONObject();
try{
diff --git a/clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/DummyStateApi.java b/clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/DummyStateApi.java
index a54653ddd13..3c120f031d3 100644
--- a/clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/DummyStateApi.java
+++ b/clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/DummyStateApi.java
@@ -71,6 +71,10 @@ public class DummyStateApi implements StateRestAPI {
}
return result;
}
+ @Override
+ public DistributionStates getDistributionStates() {
+ return null;
+ }
};
}
private UnitResponse getClusterState(final DummyBackend.Cluster cluster, final int recursive) {
@@ -91,6 +95,10 @@ public class DummyStateApi implements StateRestAPI {
}
return result;
}
+ @Override
+ public DistributionStates getDistributionStates() {
+ return null;
+ }
};
}
private UnitResponse getNodeState(final DummyBackend.Node node) {
@@ -135,6 +143,10 @@ public class DummyStateApi implements StateRestAPI {
}
};
}
+ @Override
+ public DistributionStates getDistributionStates() {
+ return null;
+ }
};
}