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
commit 1af10d4da8193a4ed8a6fd46b5f9f67b80a8c027 Author: Noble Paul <[email protected]> AuthorDate: Sat Dec 11 11:20:54 2021 +1100 supportedroles and overseer:disallowed supported --- .../java/org/apache/solr/cloud/ZkController.java | 14 +++++++---- .../src/java/org/apache/solr/core/NodeRoles.java | 8 ++++++- .../java/org/apache/solr/handler/ClusterAPI.java | 27 +++++++++++----------- .../test/org/apache/solr/cloud/NodeRolesTest.java | 8 ++++++- 4 files changed, 37 insertions(+), 20 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/cloud/ZkController.java b/solr/core/src/java/org/apache/solr/cloud/ZkController.java index 5e71098..33ea43d 100644 --- a/solr/core/src/java/org/apache/solr/cloud/ZkController.java +++ b/solr/core/src/java/org/apache/solr/cloud/ZkController.java @@ -352,7 +352,9 @@ public class ZkController implements Closeable { overseerElector.setup(context); - overseerElector.joinElection(context, true); + if(cc.nodeRoles.isOverseerAllowed()) { + overseerElector.joinElection(context, true); + } } cc.cancelCoreRecoveries(); @@ -683,7 +685,9 @@ public class ZkController implements Closeable { } finally { // just in case the OverseerElectionContext managed to start another Overseer - IOUtils.closeQuietly(overseer); + if(overseer != null) { + IOUtils.closeQuietly(overseer); + } ExecutorUtil.shutdownAndAwaitTermination(customThreadPool); } @@ -909,14 +913,16 @@ public class ZkController implements Closeable { registerLiveNodesListener(); // start the overseer first as following code may need it's processing - if (!zkRunOnly) { + if (!zkRunOnly && cc.nodeRoles.isOverseerAllowed()) { overseerElector = new LeaderElector(zkClient); this.overseer = new Overseer((HttpShardHandler) cc.getShardHandlerFactory().getShardHandler(), cc.getUpdateShardHandler(), CommonParams.CORES_HANDLER_PATH, zkStateReader, this, cloudConfig); ElectionContext context = new OverseerElectionContext(zkClient, overseer, getNodeName()); overseerElector.setup(context); - overseerElector.joinElection(context, false); + if(cc.nodeRoles.isOverseerAllowed()) { + overseerElector.joinElection(context, false); + } } Stat stat = zkClient.exists(ZkStateReader.LIVE_NODES_ZKNODE, null, true); diff --git a/solr/core/src/java/org/apache/solr/core/NodeRoles.java b/solr/core/src/java/org/apache/solr/core/NodeRoles.java index b72e5ec..4bb04e0 100644 --- a/solr/core/src/java/org/apache/solr/core/NodeRoles.java +++ b/solr/core/src/java/org/apache/solr/core/NodeRoles.java @@ -35,6 +35,7 @@ public class NodeRoles implements MapWriter { public static final String ALLOWED = "allowed"; public static final String DISALLOWED = "disallowed"; public static final String PREFERRED = "preferred"; + public static final Set<String> OVERSEER_MODES = Set.of(ALLOWED, PREFERRED, DISALLOWED); public static final String DEFAULT_ROLES_STRING = "data:on,overseer:allowed"; @@ -77,12 +78,17 @@ public class NodeRoles implements MapWriter { nodeRoles.forEach((role, s) -> ew.putNoEx(role.roleName, s)); } + public boolean isOverseerAllowed() { + String roleMode = nodeRoles.get(Role.OVERSEER); + return ALLOWED.equals(roleMode) || PREFERRED.equals(roleMode); + } + public enum Role { DATA("data"), OVERSEER("overseer") { @Override public Set<String> supportedModes() { - return Set.of(ALLOWED, PREFERRED, DISALLOWED); + return OVERSEER_MODES; } @Override public String defaultIfAbsent() { 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 796ac49..446cd9b 100644 --- a/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java +++ b/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java @@ -84,41 +84,32 @@ public class ClusterAPI { @EndPoint(method = GET, path = "/cluster/node-roles", permission = COLL_READ_PERM) - @SuppressWarnings("unchecked") // nocommit: it must also output all data nodes that didn't start with -Dsolr.node.roles public void roles(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception { Map<String, Object> result = new LinkedHashMap<>(); - rsp.add("node-roles", readRecursive(ZkStateReader.NODE_ROLES, collectionsHandler.getCoreContainer().getZkController().getSolrCloudManager().getDistribStateManager(), 3)); + rsp.add("node-roles", readRecursive(ZkStateReader.NODE_ROLES, + collectionsHandler.getCoreContainer().getZkController().getSolrCloudManager().getDistribStateManager(), 3)); } Object readRecursive(String path, DistribStateManager zk, int depth) { if (depth == 0) return null; Map<String, Object> result = null; - boolean hasSubValues = false; try { List<String> children = zk.listData(path); if (children != null && !children.isEmpty()) { result = new HashMap<>(); } else { - return depth >=1 ? Collections.emptyList(): null; + return depth >= 1 ? Collections.emptyList() : null; } for (String child : children) { Object c = readRecursive(path + "/" + child, zk, depth - 1); - if (c != null) { - hasSubValues = true; - } + result.put(child, c); } - } catch (Exception e) { - } - - - - if (result == null) { - return null; + throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e); } if (depth == 1) { return result.keySet(); @@ -138,6 +129,14 @@ public class ClusterAPI { collectionsHandler.getCoreContainer().getZkController().getSolrCloudManager().getDistribStateManager(), 2)); } @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)); + } + + @EndPoint(method = GET, path = "/cluster/node-roles/{role}/{role-val}", permission = COLL_READ_PERM) public void nodesWithRoleVal(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception { 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 a2e3651..cda83ad 100644 --- a/solr/core/src/test/org/apache/solr/cloud/NodeRolesTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/NodeRolesTest.java @@ -21,6 +21,7 @@ import java.lang.invoke.MethodHandles; import java.util.Collection; import java.util.Collections; +import java.util.List; import org.apache.solr.client.solrj.embedded.JettySolrRunner; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.V2Request; @@ -50,9 +51,14 @@ public class NodeRolesTest extends SolrCloudTestCase { public void testRoleIntegration() throws Exception { 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")); + j1 = startNodeWithRoles("overseer:preferred,data:off"); - V2Response rsp = new V2Request.Builder("/cluster/node-roles").GET().build().process(cluster.getSolrClient()); + rsp = new V2Request.Builder("/cluster/node-roles").GET().build().process(cluster.getSolrClient()); assertEquals(j1.getNodeName(), rsp._getStr("node-roles/overseer/preferred[0]", null)); assertEquals(j1.getNodeName(), rsp._getStr("node-roles/data/off[0]", null)); OverseerRolesTest.waitForNewOverseer(20, j1.getNodeName(), false);
