You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sh...@apache.org on 2017/06/28 23:20:33 UTC

lucene-solr:feature/autoscaling: SOLR-10496: Added an integration test for multiple operations

Repository: lucene-solr
Updated Branches:
  refs/heads/feature/autoscaling 39c6fb2e3 -> 44e723159


SOLR-10496: Added an integration test for multiple operations


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

Branch: refs/heads/feature/autoscaling
Commit: 44e723159ce2312c19bd2e1f766f66a2bf568885
Parents: 39c6fb2
Author: Shalin Shekhar Mangar <sh...@apache.org>
Authored: Thu Jun 29 04:50:25 2017 +0530
Committer: Shalin Shekhar Mangar <sh...@apache.org>
Committed: Thu Jun 29 04:50:25 2017 +0530

----------------------------------------------------------------------
 .../autoscaling/ComputePlanActionTest.java      | 122 +++++++++++++++++--
 1 file changed, 114 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/44e72315/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 2d19023..73ae087 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
@@ -56,14 +56,16 @@ public class ComputePlanActionTest extends SolrCloudTestCase {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
   private static final AtomicBoolean fired = new AtomicBoolean(false);
+  private static final int NODE_COUNT = 1;
   private static CountDownLatch triggerFiredLatch = new CountDownLatch(1);
-  private static final AtomicReference<Object> eventContextRef = new AtomicReference<>();
+  private static final AtomicReference<Map> actionContextPropsRef = new AtomicReference<>();
+  private static final AtomicReference<TriggerEvent> eventRef = new AtomicReference<>();
 
   private String path = null;
 
   @BeforeClass
   public static void setupCluster() throws Exception {
-    configureCluster(1)
+    configureCluster(NODE_COUNT)
         .addConfig("conf", configset("cloud-minimal"))
         .configure();
   }
@@ -74,12 +76,28 @@ public class ComputePlanActionTest extends SolrCloudTestCase {
 
     fired.set(false);
     triggerFiredLatch = new CountDownLatch(1);
-    eventContextRef.set(null);
+    actionContextPropsRef.set(null);
     this.path = "/admin/autoscaling";
 
     // remove everything from autoscaling.json in ZK
     zkClient().setData(ZkStateReader.SOLR_AUTOSCALING_CONF_PATH, "{}".getBytes(Charsets.UTF_8), true);
 
+    if (cluster.getJettySolrRunners().size() > NODE_COUNT) {
+      // stop some to get to original state
+      int numJetties = cluster.getJettySolrRunners().size();
+      for (int i = 0; i < numJetties - NODE_COUNT; i++) {
+        JettySolrRunner randomJetty = cluster.getRandomJetty(random());
+        List<JettySolrRunner> jettySolrRunners = cluster.getJettySolrRunners();
+        for (int i1 = 0; i1 < jettySolrRunners.size(); i1++) {
+          JettySolrRunner jettySolrRunner = jettySolrRunners.get(i1);
+          if (jettySolrRunner == randomJetty) {
+            cluster.stopJettySolrRunner(i1);
+            break;
+          }
+        }
+      }
+    }
+
     CloudSolrClient solrClient = cluster.getSolrClient();
 
     try {
@@ -92,6 +110,11 @@ public class ComputePlanActionTest extends SolrCloudTestCase {
     } 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
+    }
 
     String setClusterPolicyCommand = "{" +
         " 'set-cluster-policy': [" +
@@ -140,7 +163,7 @@ public class ComputePlanActionTest extends SolrCloudTestCase {
     create.process(solrClient);
 
     waitForState("Timed out waiting for replicas of new collection to be active",
-        "testNodeLost", (liveNodes, collectionState) -> collectionState.getReplicas().stream().allMatch(replica -> replica.isActive(liveNodes)));
+        "testNodeLost", clusterShape(1, 2));
 
     ClusterState clusterState = cluster.getSolrClient().getZkStateReader().getClusterState();
     DocCollection collection = clusterState.getCollection("testNodeLost");
@@ -150,9 +173,10 @@ public class ComputePlanActionTest extends SolrCloudTestCase {
 
     // start another node because because when the other node goes away, the cluster policy requires only
     // 1 replica per node and none on the overseer
-    cluster.startJettySolrRunner();
+    JettySolrRunner node2 = cluster.startJettySolrRunner();
     cluster.waitForAllNodes(30);
 
+    // stop the original node
     for (int i = 0; i < cluster.getJettySolrRunners().size(); i++) {
       JettySolrRunner jettySolrRunner = cluster.getJettySolrRunners().get(i);
       if (jettySolrRunner == runner)  {
@@ -164,7 +188,7 @@ public class ComputePlanActionTest extends SolrCloudTestCase {
 
     assertTrue("Trigger was not fired even after 5 seconds", triggerFiredLatch.await(5, TimeUnit.SECONDS));
     assertTrue(fired.get());
-    Map context = (Map) eventContextRef.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", operations);
@@ -174,6 +198,87 @@ public class ComputePlanActionTest extends SolrCloudTestCase {
     assertEquals("Expected MOVEREPLICA action after adding node", MOVEREPLICA, CollectionParams.CollectionAction.get(params.get("action")));
     String replicaToBeMoved = params.get("replica");
     assertEquals("Unexpected node in computed operation", replicas.get(0).getName(), replicaToBeMoved);
+
+    // shutdown the extra node that we had started
+    for (int i = 0; i < cluster.getJettySolrRunners().size(); i++) {
+      JettySolrRunner jettySolrRunner = cluster.getJettySolrRunners().get(i);
+      if (jettySolrRunner == node2)  {
+        cluster.stopJettySolrRunner(i);
+        break;
+      }
+    }
+  }
+
+  public void testNodeWithMultipleReplicasLost() throws Exception {
+    // 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'}," +
+        "{'name':'test','class':'" + ComputePlanActionTest.AssertingTriggerAction.class.getName() + "'}]" +
+        "}}";
+    SolrRequest req = new AutoScalingHandlerTest.AutoScalingRequest(SolrRequest.METHOD.POST, path, setTriggerCommand);
+    NamedList<Object> response = solrClient.request(req);
+    assertEquals(response.get("result").toString(), "success");
+
+    CollectionAdminRequest.Create create = CollectionAdminRequest.createCollection("testNodeWithMultipleReplicasLost",
+        "conf",2, 3);
+    create.setMaxShardsPerNode(2);
+    create.process(solrClient);
+
+    waitForState("Timed out waiting for replicas of new collection to be active",
+        "testNodeWithMultipleReplicasLost", clusterShape(2, 3));
+
+    ClusterState clusterState = cluster.getSolrClient().getZkStateReader().getClusterState();
+    DocCollection docCollection = clusterState.getCollection("testNodeWithMultipleReplicasLost");
+
+    // lets find a node with at least 2 replicas
+    String stoppedNodeName = null;
+    List<Replica> replicasToBeMoved = null;
+    for (int i = 0; i < cluster.getJettySolrRunners().size(); i++) {
+      JettySolrRunner jettySolrRunner = cluster.getJettySolrRunners().get(i);
+      List<Replica> replicas = docCollection.getReplicas(jettySolrRunner.getNodeName());
+      if (replicas != null && replicas.size() == 2) {
+        stoppedNodeName = jettySolrRunner.getNodeName();
+        replicasToBeMoved = replicas;
+        cluster.stopJettySolrRunner(i);
+        break;
+      }
+    }
+    assertNotNull(stoppedNodeName);
+    cluster.waitForAllNodes(30);
+
+    assertTrue("Trigger was not fired even after 5 seconds", triggerFiredLatch.await(5, TimeUnit.SECONDS));
+    assertTrue(fired.get());
+
+    TriggerEvent triggerEvent = eventRef.get();
+    assertNotNull(triggerEvent);
+    assertEquals(AutoScaling.EventType.NODELOST, triggerEvent.getEventType());
+    assertEquals(stoppedNodeName, triggerEvent.getProperty(TriggerEvent.NODE_NAME));
+
+    Map context = actionContextPropsRef.get();
+    assertNotNull(context);
+    List<SolrRequest> operations = (List<SolrRequest>) context.get("operations");
+    assertNotNull("The operations computed by ComputePlanAction should not be null", operations);
+    operations.forEach(solrRequest -> log.info(solrRequest.getParams().toString()));
+    assertEquals("ComputePlanAction should have computed exactly 2 operation", 2, operations.size());
+
+    for (SolrRequest solrRequest : operations) {
+      SolrParams params = solrRequest.getParams();
+      assertEquals("Expected MOVEREPLICA action after adding node", MOVEREPLICA, CollectionParams.CollectionAction.get(params.get("action")));
+      String moved = params.get("replica");
+      assertTrue(replicasToBeMoved.stream().anyMatch(replica -> replica.getName().equals(moved)));
+    }
   }
 
   @Test
@@ -203,7 +308,7 @@ public class ComputePlanActionTest extends SolrCloudTestCase {
     JettySolrRunner runner = cluster.startJettySolrRunner();
     assertTrue("Trigger was not fired even after 5 seconds", triggerFiredLatch.await(5, TimeUnit.SECONDS));
     assertTrue(fired.get());
-    Map context = (Map) eventContextRef.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", operations);
@@ -225,7 +330,8 @@ public class ComputePlanActionTest extends SolrCloudTestCase {
     @Override
     public void process(TriggerEvent event, ActionContext context) {
       if (fired.compareAndSet(false, true)) {
-        eventContextRef.set(context.getProperties());
+        eventRef.set(event);
+        actionContextPropsRef.set(context.getProperties());
         triggerFiredLatch.countDown();
       }
     }