You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ab...@apache.org on 2018/01/29 11:16:23 UTC

lucene-solr:master: SOLR-11376: Support computing plans for only specific collections.

Repository: lucene-solr
Updated Branches:
  refs/heads/master f7a75dcc1 -> d3d7b0034


SOLR-11376: Support computing plans for only specific collections.


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/d3d7b003
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/d3d7b003
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/d3d7b003

Branch: refs/heads/master
Commit: d3d7b0034d497acb7e1230322600a712e068c8d2
Parents: f7a75dc
Author: Andrzej Bialecki <ab...@apache.org>
Authored: Mon Jan 29 11:54:51 2018 +0100
Committer: Andrzej Bialecki <ab...@apache.org>
Committed: Mon Jan 29 12:16:16 2018 +0100

----------------------------------------------------------------------
 solr/CHANGES.txt                                |   2 +
 .../cloud/autoscaling/ComputePlanAction.java    |  23 +++++
 .../autoscaling/ComputePlanActionTest.java      | 103 ++++++++++++++++---
 .../solrcloud-autoscaling-trigger-actions.adoc  |  35 ++++++-
 .../solrj/request/CollectionAdminRequest.java   | 102 +++++++++---------
 .../common/params/CollectionAdminParams.java    |   2 +
 6 files changed, 200 insertions(+), 67 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3d7b003/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 3d707e5..19d42a1 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -119,6 +119,8 @@ New Features
 
 * SOLR-11702: Redesign current LIR implementation (Cao Manh Dat, shalin)
 
+* SOLR-11376: Support computing plans for only specific collections. (ab)
+
 Bug Fixes
 ----------------------
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3d7b003/solr/core/src/java/org/apache/solr/cloud/autoscaling/ComputePlanAction.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/ComputePlanAction.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/ComputePlanAction.java
index e913440..45b0ddf 100644
--- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/ComputePlanAction.java
+++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/ComputePlanAction.java
@@ -21,8 +21,10 @@ import java.lang.invoke.MethodHandles;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.solr.client.solrj.SolrRequest;
@@ -36,6 +38,8 @@ import org.apache.solr.common.SolrException;
 import org.apache.solr.common.cloud.ClusterState;
 import org.apache.solr.common.params.AutoScalingParams;
 import org.apache.solr.common.params.CollectionParams;
+import org.apache.solr.common.params.CoreAdminParams;
+import org.apache.solr.common.util.StrUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -49,6 +53,17 @@ import org.slf4j.LoggerFactory;
 public class ComputePlanAction extends TriggerActionBase {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
+  Set<String> collections = new HashSet<>();
+
+  @Override
+  public void init(Map<String, String> args) {
+    super.init(args);
+    String colString = args.get("collections");
+    if (colString != null && !colString.isEmpty()) {
+      collections.addAll(StrUtils.splitSmart(colString, ','));
+    }
+  }
+
   @Override
   public void process(TriggerEvent event, ActionContext context) throws Exception {
     log.debug("-- processing event: {} with context properties: {}", event, context.getProperties());
@@ -98,6 +113,14 @@ public class ComputePlanAction extends TriggerActionBase {
             }
           }
           log.info("Computed Plan: {}", operation.getParams());
+          if (!collections.isEmpty()) {
+            String coll = operation.getParams().get(CoreAdminParams.COLLECTION);
+            if (coll != null && !collections.contains(coll)) {
+              // discard an op that doesn't affect our collections
+              log.debug("-- discarding due to collection={} not in {}", coll, collections);
+              continue;
+            }
+          }
           Map<String, Object> props = context.getProperties();
           props.compute("operations", (k, v) -> {
             List<SolrRequest> operations = (List<SolrRequest>) v;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3d7b003/solr/core/src/test/org/apache/solr/cloud/autoscaling/ComputePlanActionTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/autoscaling/ComputePlanActionTest.java b/solr/core/src/test/org/apache/solr/cloud/autoscaling/ComputePlanActionTest.java
index 2b80ec3..579d2f6 100644
--- a/solr/core/src/test/org/apache/solr/cloud/autoscaling/ComputePlanActionTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/autoscaling/ComputePlanActionTest.java
@@ -19,6 +19,7 @@ package org.apache.solr.cloud.autoscaling;
 
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -28,6 +29,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.cloud.autoscaling.NodeStateProvider;
+import org.apache.solr.client.solrj.cloud.autoscaling.ReplicaInfo;
 import org.apache.solr.client.solrj.cloud.autoscaling.SolrCloudManager;
 import org.apache.solr.client.solrj.cloud.autoscaling.TriggerEventType;
 import org.apache.solr.client.solrj.embedded.JettySolrRunner;
@@ -103,23 +106,9 @@ public class ComputePlanActionTest extends SolrCloudTestCase {
       }
     }
 
-    CloudSolrClient solrClient = cluster.getSolrClient();
+    cluster.deleteAllCollections();
 
-    try {
-      CollectionAdminRequest.deleteCollection("testNodeLost").process(solrClient);
-    } catch (Exception e) {
-      // expected if testNodeLost hasn't run already
-    }
-    try {
-      CollectionAdminRequest.deleteCollection("testNodeAdded").process(solrClient);
-    } catch (Exception e) {
-      // expected if testNodeAdded hasn't run already
-    }
-    try {
-      CollectionAdminRequest.deleteCollection("testNodeWithMultipleReplicasLost").process(solrClient);
-    } catch (Exception e) {
-      // expected if testNodeWithMultipleReplicasLost hasn't run already
-    }
+    CloudSolrClient solrClient = cluster.getSolrClient();
 
     String setClusterPolicyCommand = "{" +
         " 'set-cluster-policy': [" +
@@ -406,4 +395,86 @@ public class ComputePlanActionTest extends SolrCloudTestCase {
 
     }
   }
+
+  @Test
+  public void testSelectedCollections() throws Exception {
+    AssertingTriggerAction.expectedNode = null;
+
+    // start 3 more nodes
+    cluster.startJettySolrRunner();
+    cluster.startJettySolrRunner();
+    cluster.startJettySolrRunner();
+
+    cluster.waitForAllNodes(30);
+
+    CloudSolrClient solrClient = cluster.getSolrClient();
+    String setTriggerCommand = "{" +
+        "'set-trigger' : {" +
+        "'name' : 'node_lost_trigger'," +
+        "'event' : 'nodeLost'," +
+        "'waitFor' : '1s'," +
+        "'enabled' : true," +
+        "'actions' : [{'name':'compute_plan', 'class' : 'solr.ComputePlanAction', 'collections' : 'testSelected1,testSelected2'}," +
+        "{'name':'test','class':'" + ComputePlanActionTest.AssertingTriggerAction.class.getName() + "'}]" +
+        "}}";
+    SolrRequest req = createAutoScalingRequest(SolrRequest.METHOD.POST, setTriggerCommand);
+    NamedList<Object> response = solrClient.request(req);
+    assertEquals(response.get("result").toString(), "success");
+
+    CollectionAdminRequest.Create create = CollectionAdminRequest.createCollection("testSelected1",
+        "conf",2, 2);
+    create.process(solrClient);
+
+    create = CollectionAdminRequest.createCollection("testSelected2",
+        "conf",2, 2);
+    create.process(solrClient);
+
+    create = CollectionAdminRequest.createCollection("testSelected3",
+        "conf",2, 2);
+    create.process(solrClient);
+
+    waitForState("Timed out waiting for replicas of new collection to be active",
+        "testSelected1", clusterShape(2, 2));
+
+    waitForState("Timed out waiting for replicas of new collection to be active",
+        "testSelected2", clusterShape(2, 2));
+
+    waitForState("Timed out waiting for replicas of new collection to be active",
+        "testSelected3", clusterShape(2, 2));
+
+    // find a node that has replicas from all collections
+    SolrCloudManager cloudManager = cluster.getJettySolrRunner(0).getCoreContainer().getZkController().getSolrCloudManager();
+    NodeStateProvider stateProvider = cloudManager.getNodeStateProvider();
+    List<String> nodes = new ArrayList<>();
+    cloudManager.getClusterStateProvider().getLiveNodes().forEach(n -> {
+      Map<String, Map<String, List<ReplicaInfo>>> map = stateProvider.getReplicaInfo(n, ImplicitSnitch.tags);
+      if (map.containsKey("testSelected3") && map.containsKey("testSelected2") && map.containsKey("testSelected1")) {
+        nodes.add(n);
+      }
+    });
+    assertTrue(nodes.size() > 0);
+    // kill first such node
+    String node = nodes.get(0);
+    for (int i = 0; i < cluster.getJettySolrRunners().size(); i++) {
+      if (cluster.getJettySolrRunner(i).getNodeName().equals(node)) {
+        cluster.stopJettySolrRunner(i);
+        break;
+      }
+    }
+    assertTrue("Trigger was not fired even after 5 seconds", triggerFiredLatch.await(5, TimeUnit.SECONDS));
+    assertTrue(fired.get());
+    Map context = actionContextPropsRef.get();
+    assertNotNull(context);
+    List<SolrRequest> operations = (List<SolrRequest>) context.get("operations");
+    assertNotNull("The operations computed by ComputePlanAction should not be null" + getNodeStateProviderState() + context, operations);
+    assertEquals("ComputePlanAction should have computed exactly 2 operations", 2, operations.size());
+    SolrRequest request = operations.get(0);
+    SolrParams params = request.getParams();
+    assertEquals("Expected MOVEREPLICA action after adding node", MOVEREPLICA, CollectionParams.CollectionAction.get(params.get("action")));
+    assertFalse("not expected testSelected3", "testSelected3".equals(params.get("collection")));
+    request = operations.get(1);
+    params = request.getParams();
+    assertEquals("Expected MOVEREPLICA action after adding node", MOVEREPLICA, CollectionParams.CollectionAction.get(params.get("action")));
+    assertFalse("not expected testSelected3", "testSelected3".equals(params.get("collection")));
+  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3d7b003/solr/solr-ref-guide/src/solrcloud-autoscaling-trigger-actions.adoc
----------------------------------------------------------------------
diff --git a/solr/solr-ref-guide/src/solrcloud-autoscaling-trigger-actions.adoc b/solr/solr-ref-guide/src/solrcloud-autoscaling-trigger-actions.adoc
index d29568f..77ab9c9 100644
--- a/solr/solr-ref-guide/src/solrcloud-autoscaling-trigger-actions.adoc
+++ b/solr/solr-ref-guide/src/solrcloud-autoscaling-trigger-actions.adoc
@@ -26,7 +26,40 @@ Currently two implementations are provided: `ComputePlanAction` and `ExecutePlan
 The `ComputePlanAction` uses the policy and preferences to calculate the optimal set of Collection API
 commands which can re-balance the cluster in response to trigger events.
 
-Currently, it has no configurable parameters.
+The following parameters are configurable:
+
+`collections`::
+A comma-separated list of collection names. If this list is not empty then
+the computed operations will only calculate collection operations that affect
+listed collections and ignore any other collection operations for collections
+not listed here (please note that non-collection operations are not affected by this).
+
+Example configuration:
+
+[source,json]
+{
+ 'set-trigger' : {
+  'name' : 'node_added_trigger',
+  'event' : 'nodeAdded',
+  'waitFor' : '1s',
+  'enabled' : true,
+  'actions' : [
+   {
+    'name' : 'compute_plan',
+    'class' : 'solr.ComputePlanAction',
+    'collections' : 'test1,test2',
+   },
+   {
+    'name' : 'execute_plan',
+    'class' : 'solr.ExecutePlanAction',
+   }
+  ]
+ }
+}
+
+In this example only collections `test1` and `test2` will be potentially
+replicated / moved to an added node, other collections will be ignored even
+if they cause policy violations.
 
 == Execute Plan Action
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3d7b003/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
index 3f2d800..8953f2e 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
@@ -72,7 +72,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
 
   public CollectionAdminRequest(String path, CollectionAction action) {
     super(METHOD.GET, path);
-    this.action = checkNotNull("action", action);
+    this.action = checkNotNull(CoreAdminParams.ACTION, action);
   }
 
   @Override
@@ -214,7 +214,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
 
     public AsyncCollectionSpecificAdminRequest(CollectionAction action, String collection) {
       super(action);
-      this.collection = checkNotNull("collection", collection);
+      this.collection = checkNotNull(CoreAdminParams.COLLECTION, collection);
     }
 
     public String getCollectionName() {
@@ -236,8 +236,8 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
 
     public AsyncShardSpecificAdminRequest(CollectionAction action, String collection, String shard) {
       super(action);
-      this.collection = checkNotNull("collection",collection);
-      this.shard = checkNotNull("shard",shard);
+      this.collection = checkNotNull(CoreAdminParams.COLLECTION, collection);
+      this.shard = checkNotNull(CoreAdminParams.SHARD, shard);
     }
 
     @Override
@@ -256,8 +256,8 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
 
     public ShardSpecificAdminRequest(CollectionAction action, String collection, String shard) {
       super(action);
-      this.collection = checkNotNull("collection",collection);
-      this.shard = checkNotNull("shard",shard);
+      this.collection = checkNotNull(CoreAdminParams.COLLECTION, collection);
+      this.shard = checkNotNull(CoreAdminParams.SHARD, shard);
     }
 
 
@@ -287,8 +287,8 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
 
     public CollectionAdminRoleRequest(CollectionAction action, String node, String role) {
       super(action);
-      this.role = checkNotNull("role",role);
-      this.node = checkNotNull("node",node);
+      this.role = checkNotNull(CollectionAdminParams.ROLE, role);
+      this.node = checkNotNull(CoreAdminParams.NODE, node);
     }
 
     public String getNode() {
@@ -302,8 +302,8 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
     @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
-      params.set("role", this.role);
-      params.set("node", this.node);
+      params.set(CollectionAdminParams.ROLE, this.role);
+      params.set(CoreAdminParams.NODE, this.node);
       return params;
     }
 
@@ -498,7 +498,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
         params.set( ZkStateReader.NUM_SHARDS_PROP, numShards);
       }
       if (maxShardsPerNode != null) {
-        params.set( "maxShardsPerNode", maxShardsPerNode);
+        params.set( ZkStateReader.MAX_SHARDS_PER_NODE, maxShardsPerNode);
       }
       if (routerName != null)
         params.set( "router.name", routerName);
@@ -508,13 +508,13 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
         params.set("router.field", routerField);
       }
       if (nrtReplicas != null) {
-        params.set( "replicationFactor", nrtReplicas);// Keep both for compatibility?
+        params.set( ZkStateReader.REPLICATION_FACTOR, nrtReplicas);// Keep both for compatibility?
         params.set( ZkStateReader.NRT_REPLICAS, nrtReplicas);
       }
       if (autoAddReplicas != null) {
         params.set(ZkStateReader.AUTO_ADD_REPLICAS, autoAddReplicas);
       }
-      if(properties != null) {
+      if (properties != null) {
         addProperties(params, properties);
       }
       if (stateFormat != null) {
@@ -526,8 +526,8 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
       if (tlogReplicas != null) {
         params.set(ZkStateReader.TLOG_REPLICAS, tlogReplicas);
       }
-      if(rule != null) params.set("rule", rule);
-      if(snitch != null) params.set("snitch", snitch);
+      if (rule != null) params.set(DocCollection.RULE, rule);
+      if (snitch != null) params.set(DocCollection.SNITCH, snitch);
       params.setNonNull(POLICY, policy);
       return params;
     }
@@ -566,7 +566,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
     @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = (ModifiableSolrParams) super.getParams();
-      params.set("node", node);
+      params.set(CoreAdminParams.NODE, node);
       return params;
     }
 
@@ -611,7 +611,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
     }
     @Override
     public SolrParams getParams() {
-      return ((ModifiableSolrParams) super.getParams()).set("node", node);
+      return ((ModifiableSolrParams) super.getParams()).set(CoreAdminParams.NODE, node);
     }
 
   }
@@ -625,16 +625,16 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
 
     public MoveReplica(String collection, String replica, String targetNode) {
       super(CollectionAction.MOVEREPLICA);
-      this.collection = checkNotNull("collection",collection);
-      this.replica = checkNotNull("replica",replica);
-      this.targetNode = checkNotNull("targetNode",targetNode);
+      this.collection = checkNotNull(CoreAdminParams.COLLECTION, collection);
+      this.replica = checkNotNull(CoreAdminParams.REPLICA, replica);
+      this.targetNode = checkNotNull(CollectionParams.TARGET_NODE, targetNode);
       this.randomlyMoveReplica = false;
     }
 
     public MoveReplica(String collection, String shard, String sourceNode, String targetNode) {
       super(CollectionAction.MOVEREPLICA);
-      this.collection = checkNotNull("collection",collection);
-      this.shard = checkNotNull("shard",shard);
+      this.collection = checkNotNull(CoreAdminParams.COLLECTION, collection);
+      this.shard = checkNotNull(CoreAdminParams.SHARD, shard);
       this.sourceNode = checkNotNull(CollectionParams.SOURCE_NODE, sourceNode);
       this.targetNode = checkNotNull(CollectionParams.TARGET_NODE, targetNode);
       this.randomlyMoveReplica = true;
@@ -651,17 +651,17 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
     @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = (ModifiableSolrParams) super.getParams();
-      params.set("collection", collection);
+      params.set(CoreAdminParams.COLLECTION, collection);
       params.set(CollectionParams.TARGET_NODE, targetNode);
       params.set(CommonAdminParams.IN_PLACE_MOVE, inPlaceMove);
       if (timeout != -1) {
         params.set(CommonAdminParams.TIMEOUT, timeout);
       }
       if (randomlyMoveReplica) {
-        params.set("shard", shard);
+        params.set(CoreAdminParams.SHARD, shard);
         params.set(CollectionParams.SOURCE_NODE, sourceNode);
       } else {
-        params.set("replica", replica);
+        params.set(CoreAdminParams.REPLICA, replica);
       }
       return params;
     }
@@ -701,7 +701,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
 
     public RebalanceLeaders(String collection) {
       super(CollectionAction.REBALANCELEADERS);
-      this.collection = checkNotNull("collection",collection);
+      this.collection = checkNotNull(CoreAdminParams.COLLECTION, collection);
     }
 
     @Override
@@ -899,10 +899,10 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
       params.set(CoreAdminParams.BACKUP_LOCATION, location); //note: optional
       params.set("collection.configName", configName); //note: optional
       if (maxShardsPerNode != null) {
-        params.set( "maxShardsPerNode", maxShardsPerNode);
+        params.set( ZkStateReader.MAX_SHARDS_PER_NODE, maxShardsPerNode);
       }
       if (replicationFactor != null) {
-        params.set("replicationFactor", replicationFactor);
+        params.set(ZkStateReader.REPLICATION_FACTOR, replicationFactor);
       }
       if (autoAddReplicas != null) {
         params.set(ZkStateReader.AUTO_ADD_REPLICAS, autoAddReplicas);
@@ -1074,7 +1074,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
 
     private SplitShard(String collection) {
       super(CollectionAction.SPLITSHARD);
-      this.collection = checkNotNull("collection",collection);
+      this.collection = checkNotNull(CoreAdminParams.COLLECTION, collection);
     }
 
     public SplitShard setRanges(String ranges) { this.ranges = ranges; return this; }
@@ -1113,9 +1113,9 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
         throw new IllegalArgumentException("You must set shardname OR splitkey for this request.");
       }
 
-      params.set("shard", shard);
+      params.set(CoreAdminParams.SHARD, shard);
       params.set("split.key", this.splitKey);
-      params.set( "ranges", ranges);
+      params.set(CoreAdminParams.RANGES, ranges);
 
       if(properties != null) {
         addProperties(params, properties);
@@ -1223,7 +1223,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
 
     private RequestStatus(String requestId) {
       super(CollectionAction.REQUESTSTATUS);
-      this.requestId = checkNotNull("requestId",requestId);
+      this.requestId = checkNotNull("requestId", requestId);
     }
 
     public String getRequestId() {
@@ -1268,7 +1268,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
    * Returns a SolrRequest to delete an asynchronous request status
    */
   public static DeleteStatus deleteAsyncId(String requestId) {
-    return new DeleteStatus(checkNotNull("requestId",requestId), null);
+    return new DeleteStatus(checkNotNull("requestId", requestId), null);
   }
 
   /**
@@ -1523,7 +1523,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
    *
    */
   public static AddReplica addReplicaToShard(String collection, String shard, Replica.Type replicaType) {
-    return new AddReplica(collection, checkNotNull("shard",shard), null, replicaType);
+    return new AddReplica(collection, checkNotNull(CoreAdminParams.SHARD, shard), null, replicaType);
   }
 
   /**
@@ -1549,7 +1549,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
 
     private AddReplica(String collection, String shard, String routeKey, Replica.Type type) {
       super(CollectionAction.ADDREPLICA);
-      this.collection = checkNotNull("collection",collection);
+      this.collection = checkNotNull(CoreAdminParams.COLLECTION, collection);
       this.shard = shard;
       this.routeKey = routeKey;
       this.type = type;
@@ -1633,19 +1633,19 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
         params.add(ShardParams._ROUTE_, routeKey);
       }
       if (node != null) {
-        params.add("node", node);
+        params.add(CoreAdminParams.NODE, node);
       }
       if (instanceDir != null)  {
-        params.add("instanceDir", instanceDir);
+        params.add(CoreAdminParams.INSTANCE_DIR, instanceDir);
       }
       if (dataDir != null)  {
-        params.add("dataDir", dataDir);
+        params.add(CoreAdminParams.DATA_DIR, dataDir);
       }
       if (ulogDir != null) {
-        params.add("ulogDir", ulogDir);
+        params.add(CoreAdminParams.ULOG_DIR, ulogDir);
       }
       if (coreName != null) {
-        params.add("name", coreName);
+        params.add(CoreAdminParams.NAME, coreName);
       }
       if (type != null) {
         params.add(ZkStateReader.REPLICA_TYPE, type.name());
@@ -1662,14 +1662,15 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
    * Returns a SolrRequest to delete a replica from a shard in a collection
    */
   public static DeleteReplica deleteReplica(String collection, String shard, String replica) {
-    return new DeleteReplica(collection, checkNotNull("shard",shard), checkNotNull("replica",replica));
+    return new DeleteReplica(collection, checkNotNull(CoreAdminParams.SHARD, shard),
+        checkNotNull(CoreAdminParams.REPLICA, replica));
   }
 
   /**
    * Returns a SolrRequest to remove a number of replicas from a specific shard
    */
   public static DeleteReplica deleteReplicasFromShard(String collection, String shard, int count) {
-    return new DeleteReplica(collection, checkNotNull("shard",shard), count);
+    return new DeleteReplica(collection, checkNotNull(CoreAdminParams.SHARD, shard), count);
   }
 
   public static DeleteReplica deleteReplicasFromAllShards(String collection, int count) {
@@ -1839,9 +1840,10 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
 
     private Migrate(String collection, String targetCollection, String splitKey) {
       super(CollectionAction.MIGRATE);
-      this.collection = checkNotNull("collection",collection);
-      this.targetCollection = checkNotNull("targetCollection",targetCollection);
-      this.splitKey = checkNotNull("splitKey",splitKey);
+      this.collection = checkNotNull(CoreAdminParams.COLLECTION, collection);
+      this.targetCollection = checkNotNull("targetCollection", targetCollection);
+      // TODO: inconsistent with "split.key"
+      this.splitKey = checkNotNull("splitKey", splitKey);
     }
 
     public String getCollectionName() {
@@ -2056,7 +2058,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
 
     private AddReplicaProp(String collection, String shard, String replica, String propertyName, String propertyValue) {
       super(CollectionAction.ADDREPLICAPROP, collection, shard);
-      this.replica = checkNotNull("replica",replica);
+      this.replica = checkNotNull(CoreAdminParams.REPLICA, replica);
       this.propertyName = checkNotNull("propertyName",propertyName);
       this.propertyValue = checkNotNull("propertyValue",propertyValue);
     }
@@ -2114,7 +2116,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
 
     private DeleteReplicaProp(String collection, String shard, String replica, String propertyName) {
       super(CollectionAction.DELETEREPLICAPROP, collection, shard);
-      this.replica = checkNotNull("replica",replica);
+      this.replica = checkNotNull(CoreAdminParams.REPLICA, replica);
       this.propertyName = checkNotNull("propertyName",propertyName);
     }
 
@@ -2129,7 +2131,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
     @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
-      params.set("replica", replica);
+      params.set(CoreAdminParams.REPLICA, replica);
       params.set("property", propertyName);
       return params;
     }
@@ -2153,7 +2155,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
 
     private MigrateClusterState(String collection) {
       super(CollectionAction.MIGRATESTATEFORMAT);
-      this.collection = checkNotNull("collection",collection);
+      this.collection = checkNotNull(CoreAdminParams.COLLECTION, collection);
     }
 
     @Override
@@ -2181,7 +2183,7 @@ public abstract class CollectionAdminRequest<T extends CollectionAdminResponse>
 
     private BalanceShardUnique(String collection, String propertyName) {
       super(CollectionAction.BALANCESHARDUNIQUE);
-      this.collection = checkNotNull("collection",collection);
+      this.collection = checkNotNull(CoreAdminParams.COLLECTION, collection);
       this.propertyName = checkNotNull("propertyName",propertyName);
     }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3d7b003/solr/solrj/src/java/org/apache/solr/common/params/CollectionAdminParams.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/common/params/CollectionAdminParams.java b/solr/solrj/src/java/org/apache/solr/common/params/CollectionAdminParams.java
index b5f23e2..04acd9f 100644
--- a/solr/solrj/src/java/org/apache/solr/common/params/CollectionAdminParams.java
+++ b/solr/solrj/src/java/org/apache/solr/common/params/CollectionAdminParams.java
@@ -28,6 +28,8 @@ public interface CollectionAdminParams {
 
   String COUNT_PROP = "count";
 
+  String ROLE = "role";
+
   /** Predefined system collection name. */
   String SYSTEM_COLL = ".system";