This is an automated email from the ASF dual-hosted git repository.
ishan pushed a commit to branch jira/SOLR15694
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/jira/SOLR15694 by this push:
new 0f3ff02 Adding Roles API to ref guide
new 360e9ce Merge branch 'jira/SOLR15694' of
https://gitbox.apache.org/repos/asf/solr into jira/SOLR15694
0f3ff02 is described below
commit 0f3ff02357cc573a02665b0bd9d618e988e62958
Author: Ishan Chattopadhyaya <[email protected]>
AuthorDate: Sat Dec 18 15:12:13 2021 +0530
Adding Roles API to ref guide
---
.../java/org/apache/solr/handler/ClusterAPI.java | 42 ++++++++--
.../test/org/apache/solr/cloud/NodeRolesTest.java | 18 ++--
solr/solr-ref-guide/src/node-roles.adoc | 97 +++++++++++++++++++++-
3 files changed, 140 insertions(+), 17 deletions(-)
diff --git a/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
b/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
index 9f93c39..39f4750 100644
--- a/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
@@ -103,10 +103,8 @@ public class ClusterAPI {
}
for (String child : children) {
Object c = readRecursive(path + "/" + child, zk, depth - 1);
-
result.put(child, c);
}
-
} catch (Exception e) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
}
@@ -115,7 +113,6 @@ public class ClusterAPI {
} else {
return result;
}
-
}
@EndPoint(method = GET,
@@ -123,16 +120,45 @@ public class ClusterAPI {
permission = COLL_READ_PERM)
public void nodesWithRole(SolrQueryRequest req, SolrQueryResponse rsp)
throws Exception {
String role = req.getPathTemplateValues().get("role");
- rsp.add(role,
+ rsp.add("node-roles", Map.of(role,
readRecursive(ZkStateReader.NODE_ROLES + "/"+ role,
-
collectionsHandler.getCoreContainer().getZkController().getSolrCloudManager().getDistribStateManager(),
2));
+
collectionsHandler.getCoreContainer().getZkController().getSolrCloudManager().getDistribStateManager(),
2)));
+ }
+
+ @EndPoint(method = GET,
+ path = "/cluster/node-roles/nodes/{node}",
+ permission = COLL_READ_PERM)
+ @SuppressWarnings("unchecked")
+ public void rolesForNode(SolrQueryRequest req, SolrQueryResponse rsp) throws
Exception {
+ String node = req.getPathTemplateValues().get("node");
+ Map<String, String> ret = new HashMap<String, String>();
+ Map<String, Map<String, Set<String>>> roles = (Map<String, Map<String,
Set<String>>>) readRecursive(ZkStateReader.NODE_ROLES,
+
collectionsHandler.getCoreContainer().getZkController().getSolrCloudManager().getDistribStateManager(),
3);
+ for (String role: roles.keySet()) {
+ for (String mode : roles.get(role).keySet()) {
+ if (roles.get(role).get(mode) instanceof List && ((List)
roles.get(role).get(mode)).size() == 0) {
+ continue;
+ }
+ Set<String> nodes = roles.get(role).get(mode);
+ if (nodes.contains(node)) ret.put(role, mode);
+ }
+ }
+ for (String role: ret.keySet()) {
+ rsp.add(role, ret.get(role));
+ }
}
+
@EndPoint(method = GET,
path = "/cluster/node-roles/supported",
permission = COLL_READ_PERM)
public void supportedRoles(SolrQueryRequest req, SolrQueryResponse rsp)
throws Exception {
- rsp.add("supported-roles",
-
collectionsHandler.getCoreContainer().getZkController().getSolrCloudManager().getDistribStateManager().listData(ZkStateReader.NODE_ROLES));
+ //rsp.add("supported-roles",
+ //
collectionsHandler.getCoreContainer().getZkController().getSolrCloudManager().getDistribStateManager().listData(ZkStateReader.NODE_ROLES));
+ Map<String, Object> roleModesSupportedMap = new HashMap<>();
+ for (NodeRoles.Role role: NodeRoles.Role.values()) {
+ roleModesSupportedMap.put(role.toString(), Map.of("modes",
role.supportedModes(), "defaultIfAbsent", role.defaultIfAbsent()));
+ }
+ rsp.add("supported-roles", roleModesSupportedMap);
}
@EndPoint(method = GET,
@@ -143,7 +169,7 @@ public class ClusterAPI {
String roleVal = req.getPathTemplateValues().get("role-val");
List<String> nodes =
collectionsHandler.getCoreContainer().getZkController().getSolrCloudManager()
.getDistribStateManager().listData(ZkStateReader.NODE_ROLES + "/"+
role+"/"+roleVal);
- rsp.add( role, Collections.singletonMap(roleVal, nodes));
+ rsp.add( "node-roles", Map.of(role, Collections.singletonMap(roleVal,
nodes)));
}
public static List<String> getNodesByRole(NodeRoles.Role role, String val,
DistribStateManager zk)
diff --git a/solr/core/src/test/org/apache/solr/cloud/NodeRolesTest.java
b/solr/core/src/test/org/apache/solr/cloud/NodeRolesTest.java
index cda83ad..1970f6c 100644
--- a/solr/core/src/test/org/apache/solr/cloud/NodeRolesTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/NodeRolesTest.java
@@ -22,6 +22,8 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
+
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.V2Request;
@@ -52,9 +54,9 @@ public class NodeRolesTest extends SolrCloudTestCase {
JettySolrRunner j0 = cluster.getJettySolrRunner(0);
JettySolrRunner j1 = null, j2 = null;
V2Response rsp = new
V2Request.Builder("/cluster/node-roles/supported").GET().build().process(cluster.getSolrClient());
- List<String> l = (List<String>) rsp._get("supported-roles",
Collections.emptyList());
- assertTrue(l.contains("data"));
- assertTrue(l.contains("overseer"));
+ Map<String, Object> l = (Map<String, Object>) rsp._get("supported-roles",
Collections.emptyMap());
+ assertTrue(l.containsKey("data"));
+ assertTrue(l.containsKey("overseer"));
j1 = startNodeWithRoles("overseer:preferred,data:off");
@@ -72,12 +74,12 @@ public class NodeRolesTest extends SolrCloudTestCase {
rsp = new
V2Request.Builder("/cluster/node-roles/overseer").GET().build().process(cluster.getSolrClient());
- assertTrue( ((Collection)rsp._get("overseer/preferred",
Collections.emptyList())).contains(j2.getNodeName()));
- assertTrue( ((Collection)rsp._get("overseer/preferred",
Collections.emptyList())).contains(j1.getNodeName()));
+ assertTrue( ((Collection)rsp._get("node-roles/overseer/preferred",
Collections.emptyList())).contains(j2.getNodeName()));
+ assertTrue( ((Collection)rsp._get("node-roles/overseer/preferred",
Collections.emptyList())).contains(j1.getNodeName()));
rsp = new
V2Request.Builder("/cluster/node-roles/overseer/preferred").GET().build().process(cluster.getSolrClient());
- assertTrue( ((Collection)rsp._get("overseer/preferred",
Collections.emptyList())).contains(j2.getNodeName()));
- assertTrue( ((Collection)rsp._get("overseer/preferred",
Collections.emptyList())).contains(j1.getNodeName()));
+ assertTrue( ((Collection)rsp._get("node-roles/overseer/preferred",
Collections.emptyList())).contains(j2.getNodeName()));
+ assertTrue( ((Collection)rsp._get("node-roles/overseer/preferred",
Collections.emptyList())).contains(j1.getNodeName()));
String COLLECTION_NAME = "TEST_ROLES";
CollectionAdminRequest
@@ -93,7 +95,7 @@ public class NodeRolesTest extends SolrCloudTestCase {
// Shutdown the dedicated overseer, make sure that node disappears from
the roles output
j1.stop();
rsp = new
V2Request.Builder("/cluster/node-roles/overseer/preferred").GET().build().process(cluster.getSolrClient());
- assertFalse (((Collection) rsp._get("overseer/preferred" , null)).
contains(j1.getNodeName()));
+ assertFalse (((Collection) rsp._get("node-roles/overseer/preferred" ,
null)). contains(j1.getNodeName()));
}
private JettySolrRunner startNodeWithRoles(String roles) throws Exception {
diff --git a/solr/solr-ref-guide/src/node-roles.adoc
b/solr/solr-ref-guide/src/node-roles.adoc
index f3e5969..ed2c07a 100644
--- a/solr/solr-ref-guide/src/node-roles.adoc
+++ b/solr/solr-ref-guide/src/node-roles.adoc
@@ -62,4 +62,99 @@ A common situation arises when the nodes in a cluster is
under heavy querying or
* Most nodes, say 10 of them, in the cluster start with
`-Dsolr.node.roles=data:on,overseer:allowed` (or with no parameter, since the
default value for `solr.node.roles` is the same).
* One or more nodes can start with `-Dsolr.node.roles=overseer:preferred` (or
`-Dsolr.node.roles=overseer:preferred,data:off`)
-In this arrangement, such dedicated nodes can have lesser resources than other
data nodes (since these are stateless nodes) and yet the cluster will behave
optimally. In case the dedicated overseer nodes go down for some reason, the
overseer leader will be elected from one of the data nodes (since they have
overseer in "allowed" mode), and once one of the dedicated overseer nodes are
back up, it will assume the overseer leadership again.
\ No newline at end of file
+In this arrangement, such dedicated nodes can have lesser resources than other
data nodes (since these are stateless nodes) and yet the cluster will behave
optimally. In case the dedicated overseer nodes go down for some reason, the
overseer leader will be elected from one of the data nodes (since they have
overseer in "allowed" mode), and once one of the dedicated overseer nodes are
back up, it will assume the overseer leadership again.
+
+== Roles API
+
+=== GET /api/cluster/node-roles/supported
+
+*Input*
+[source,text]
+----
+curl http://localhost:8983/api/cluster/node-roles/supported
+----
+
+*Output*
+[source,text]
+----
+{
+ "supported-roles":{
+ "data":{
+ "defaultIfAbsent":"off",
+ "modes":["off",
+ "on"]
+ },
+ "overseer":{
+ "defaultIfAbsent":"disallowed",
+ "modes":["disallowed",
+ "allowed",
+ "preferred"]
+ }
+ }
+}
+----
+
+=== GET /api/cluster/node-roles
+
+*Input*
+[source,text]
+----
+curl http://localhost:8983/api/cluster/node-roles
+----
+
+*Output*
+[source,text]
+----
+{
+ "node-roles":{
+ "data":{
+ "off":["solr2:8983_solr"],
+ "on":["solr1:8983_solr"]
+ },
+ "overseer":{
+ "allowed":["solr1:8983_solr"],
+ "disallowed":[],
+ "preferred":["solr2:8983_solr"]
+ }
+ }
+}
+----
+
+=== GET /api/cluster/node-roles/{role}
+
+*Input*
+[source,text]
+----
+http://localhost:8983/api/node-roles/data
+----
+
+*Output*
+[source,text]
+----
+{
+ "node-roles":{
+ "data":{
+ "off":["solr2:8983_solr"],
+ "on":["solr1:8983_solr"]
+ }
+ }
+}
+----
+
+
+=== GET /api/cluster/node-roles/nodes/{node}
+
+*Input*
+[source,text]
+----
+curl http://localhost:8983/api/cluster/node-roles/nodes/solr1:8983_solr
+----
+
+*Output*
+[source,text]
+----
+{
+ "data":"on",
+ "overseer":"allowed"
+}
+----