View Javadoc

1   package org.apache.helix.tools;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.FileWriter;
23  import java.io.PrintWriter;
24  import java.util.Date;
25  import java.util.HashSet;
26  import java.util.Set;
27  
28  import org.apache.helix.BaseDataAccessor;
29  import org.apache.helix.HelixDataAccessor;
30  import org.apache.helix.TestHelper;
31  import org.apache.helix.ZNRecord;
32  import org.apache.helix.controller.HelixControllerMain;
33  import org.apache.helix.integration.ZkIntegrationTestBase;
34  import org.apache.helix.manager.zk.ZKHelixDataAccessor;
35  import org.apache.helix.manager.zk.ZKUtil;
36  import org.apache.helix.manager.zk.ZkBaseDataAccessor;
37  import org.apache.helix.mock.controller.ClusterController;
38  import org.apache.helix.mock.participant.MockParticipant;
39  import org.apache.helix.model.IdealState;
40  import org.apache.helix.model.InstanceConfig;
41  import org.apache.helix.model.LiveInstance;
42  import org.apache.helix.store.ZNRecordJsonSerializer;
43  import org.apache.helix.tools.ClusterStateVerifier.BestPossAndExtViewZkVerifier;
44  import org.apache.helix.tools.ClusterStateVerifier.MasterNbInExtViewVerifier;
45  import org.testng.Assert;
46  import org.testng.annotations.Test;
47  
48  public class TestHelixAdminCli extends ZkIntegrationTestBase
49  {
50    @Test
51    public void testAddCluster() throws Exception
52    {
53      String command = "--zkSvr localhost:2183 -addCluster clusterTest";
54      ClusterSetup.processCommandLineArgs(command.split("\\s+"));
55  
56      // malformed cluster name
57      command = "--zkSvr localhost:2183 -addCluster /ClusterTest";
58      try
59      {
60        ClusterSetup.processCommandLineArgs(command.split("\\s+"));
61        Assert
62            .fail("ClusterSetup should fail since /ClusterTest is not a valid name");
63      } catch (Exception e)
64      {
65        // OK
66      }
67  
68      // Add the grand cluster
69      // " is ignored by zk
70      command = "--zkSvr localhost:2183 -addCluster \"Klazt3rz";
71      ClusterSetup.processCommandLineArgs(command.split("\\s+"));
72  
73      command = "--zkSvr localhost:2183 -addCluster \\ClusterTest";
74      ClusterSetup.processCommandLineArgs(command.split("\\s+"));
75  
76      // Add already exist cluster
77      command = "--zkSvr localhost:2183 -addCluster clusterTest";
78      try
79      {
80        ClusterSetup.processCommandLineArgs(command.split("\\s+"));
81        Assert.fail("ClusterSetup should fail since clusterTest already exists");
82      } catch (Exception e)
83      {
84        // OK
85      }
86  
87      // make sure clusters are properly setup
88      Assert.assertTrue(ZKUtil.isClusterSetup("Klazt3rz", _gZkClient));
89      Assert.assertTrue(ZKUtil.isClusterSetup("clusterTest", _gZkClient));
90      Assert.assertTrue(ZKUtil.isClusterSetup("\\ClusterTest", _gZkClient));
91  
92      // delete cluster without resource and instance
93      command = "-zkSvr localhost:2183 -dropCluster \\ClusterTest";
94      ClusterSetup.processCommandLineArgs(command.split("\\s+"));
95  
96      command = "-zkSvr localhost:2183 -dropCluster clusterTest1";
97      ClusterSetup.processCommandLineArgs(command.split("\\s+"));
98  
99      command = "-zkSvr localhost:2183 -dropCluster clusterTest";
100     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
101 
102     Assert.assertFalse(_gZkClient.exists("/clusterTest"));
103     Assert.assertFalse(_gZkClient.exists("/\\ClusterTest"));
104     Assert.assertFalse(_gZkClient.exists("/clusterTest1"));
105 
106     // System.out.println("END test");
107   }
108 
109   @Test
110   public void testAddResource() throws Exception
111   {
112     String className = TestHelper.getTestClassName();
113     String methodName = TestHelper.getTestMethodName();
114     String clusterName = className + "_" + methodName;
115 
116     System.out.println("START " + clusterName + " at "
117         + new Date(System.currentTimeMillis()));
118 
119     String command = "-zkSvr localhost:2183 -addCluster " + clusterName;
120     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
121 
122     command = "-zkSvr localhost:2183 -addResource " + clusterName
123         + " db_22 144 MasterSlave";
124     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
125 
126     command = "-zkSvr localhost:2183 -addResource " + clusterName
127         + " db_11 44 MasterSlave";
128     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
129 
130     // Add duplicate resource
131     command = "-zkSvr localhost:2183 -addResource " + clusterName
132         + " db_22 55 OnlineOffline";
133     try
134     {
135       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
136       Assert
137           .fail("ClusterSetup should fail since resource db_22 already exists");
138     } catch (Exception e)
139     {
140       // OK
141     }
142 
143     // drop resource now
144     command = "-zkSvr localhost:2183 -dropResource " + clusterName + " db_11 ";
145     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
146 
147     System.out.println("END " + clusterName + " at "
148         + new Date(System.currentTimeMillis()));
149   }
150 
151   @Test
152   public void testAddInstance() throws Exception
153   {
154     String className = TestHelper.getTestClassName();
155     String methodName = TestHelper.getTestMethodName();
156     String clusterName = className + "_" + methodName;
157 
158     System.out.println("START " + clusterName + " at "
159         + new Date(System.currentTimeMillis()));
160 
161     String command = "-zkSvr localhost:2183 -addCluster " + clusterName;
162     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
163 
164     for (int i = 0; i < 3; i++)
165     {
166       command = "-zkSvr localhost:2183 -addNode " + clusterName
167           + " localhost:123" + i;
168       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
169     }
170 
171     command = "-zkSvr localhost:2183 -addNode " + clusterName
172         + " localhost:1233;localhost:1234;localhost:1235;localhost:1236";
173     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
174 
175     // delete enabled node
176     command = "-zkSvr localhost:2183 -dropNode " + clusterName
177         + " localhost:1236";
178     try
179     {
180       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
181       Assert
182           .fail("delete node localhost:1236 should fail since it's not disabled");
183     } catch (Exception e)
184     {
185       // OK
186     }
187 
188     // delete non-exist node
189     command = "-zkSvr localhost:2183 -dropNode " + clusterName
190         + " localhost:12367";
191     try
192     {
193       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
194       Assert
195           .fail("delete node localhost:1237 should fail since it doesn't exist");
196     } catch (Exception e)
197     {
198       // OK
199     }
200 
201     // disable node
202     command = "-zkSvr localhost:2183 -enableInstance " + clusterName
203         + " localhost:1236 false";
204     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
205 
206     command = "-zkSvr localhost:2183 -dropNode " + clusterName
207         + " localhost:1236";
208     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
209 
210     // add a duplicated host
211     command = "-zkSvr localhost:2183 -addNode " + clusterName
212         + " localhost:1234";
213     try
214     {
215       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
216       Assert
217           .fail("add node localhost:1234 should fail since it already exists");
218     } catch (Exception e)
219     {
220       // OK
221     }
222 
223     System.out.println("END " + clusterName + " at "
224         + new Date(System.currentTimeMillis()));
225   }
226 
227   @Test
228   public void testRebalanceResource() throws Exception
229   {
230     String className = TestHelper.getTestClassName();
231     String methodName = TestHelper.getTestMethodName();
232     String clusterName = className + "_" + methodName;
233 
234     System.out.println("START " + clusterName + " at "
235         + new Date(System.currentTimeMillis()));
236 
237     String command = "-zkSvr localhost:2183 -addCluster " + clusterName;
238     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
239 
240     command = "-zkSvr localhost:2183 -addResource " + clusterName
241         + " db_11 12 MasterSlave";
242     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
243 
244     for (int i = 0; i < 6; i++)
245     {
246       command = "-zkSvr localhost:2183 -addNode " + clusterName
247           + " localhost:123" + i;
248       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
249     }
250 
251     command = "-zkSvr localhost:2183 -rebalance " + clusterName + " db_11 3";
252     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
253 
254     command = "-zkSvr localhost:2183 -dropResource " + clusterName + " db_11 ";
255     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
256 
257     // re-add and rebalance
258     command = "-zkSvr localhost:2183 -addResource " + clusterName
259         + " db_11 48 MasterSlave";
260     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
261 
262     command = "-zkSvr localhost:2183 -rebalance " + clusterName + " db_11 3";
263     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
264 
265     // rebalance with key prefix
266     command = "-zkSvr localhost:2183 -rebalance " + clusterName
267         + " db_11 2 -key alias";
268     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
269 
270     System.out.println("END " + clusterName + " at "
271         + new Date(System.currentTimeMillis()));
272   }
273 
274   @Test
275   public void testStartCluster() throws Exception
276   {
277     String className = TestHelper.getTestClassName();
278     String methodName = TestHelper.getTestMethodName();
279     String clusterName = className + "_" + methodName;
280     String grandClusterName = clusterName + "_grand";
281     final int n = 6;
282 
283     System.out.println("START " + clusterName + " at "
284         + new Date(System.currentTimeMillis()));
285     MockParticipant[] participants = new MockParticipant[n];
286     ClusterController[] controllers = new ClusterController[2];
287     setupCluster(clusterName, grandClusterName, n, participants, controllers);
288 
289     // activate clusters
290     // wrong grand clusterName
291     String command = "-zkSvr localhost:2183 -activateCluster " + clusterName
292         + " nonExistGrandCluster true";
293     try
294     {
295       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
296       Assert.fail("add " + clusterName
297           + " to grandCluster should fail since grandCluster doesn't exists");
298     } catch (Exception e)
299     {
300       // OK
301     }
302 
303     // wrong cluster name
304     command = "-zkSvr localhost:2183 -activateCluster nonExistCluster "
305         + grandClusterName + " true";
306     try
307     {
308       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
309       Assert.fail("add nonExistCluster to " + grandClusterName
310           + " should fail since nonExistCluster doesn't exists");
311     } catch (Exception e)
312     {
313       // OK
314     }
315 
316     command = "-zkSvr localhost:2183 -activateCluster " + clusterName + " "
317         + grandClusterName + " true";
318     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
319     Thread.sleep(500);
320 
321     // drop a running cluster
322     command = "-zkSvr localhost:2183 -dropCluster " + clusterName;
323     try
324     {
325       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
326       Assert.fail("drop " + clusterName
327           + " should fail since it's still running");
328     } catch (Exception e)
329     {
330       // OK
331     }
332 
333     // verify leader node
334     BaseDataAccessor<ZNRecord> baseAccessor = new ZkBaseDataAccessor<ZNRecord>(
335         _gZkClient);
336     HelixDataAccessor accessor = new ZKHelixDataAccessor(grandClusterName,
337         baseAccessor);
338     LiveInstance controllerLeader = accessor.getProperty(accessor.keyBuilder()
339         .controllerLeader());
340     Assert.assertNotNull(controllerLeader,
341         "controllerLeader should be either controller_9000 or controller_9001");
342     Assert.assertTrue(controllerLeader.getInstanceName().startsWith(
343         "controller_900"));
344 
345     accessor = new ZKHelixDataAccessor(clusterName, baseAccessor);
346     LiveInstance leader = accessor.getProperty(accessor.keyBuilder()
347         .controllerLeader());
348     for (int i = 0; i < 20; i++)
349     {
350       if (leader != null)
351       {
352         break;
353       }
354       Thread.sleep(200);
355       leader = accessor.getProperty(accessor.keyBuilder().controllerLeader());
356     }
357     Assert.assertTrue(leader.getInstanceName().startsWith("controller_900"));
358 
359     boolean verifyResult = ClusterStateVerifier
360         .verifyByZkCallback(new MasterNbInExtViewVerifier(ZK_ADDR, clusterName));
361     Assert.assertTrue(verifyResult);
362 
363     verifyResult = ClusterStateVerifier
364         .verifyByZkCallback(new BestPossAndExtViewZkVerifier(ZK_ADDR,
365             clusterName));
366     Assert.assertTrue(verifyResult);
367 
368     // clean up
369     // for (int i = 0; i < 2; i++) {
370     // controllers[i].syncStop();
371     // Thread.sleep(1000); // wait for all zk callbacks done
372     // }
373     // Thread.sleep(5000);
374     // for (int i = 0; i < n; i++) {
375     // participants[i].syncStop();
376     // }
377 
378     System.out.println("END " + clusterName + " at "
379         + new Date(System.currentTimeMillis()));
380   }
381 
382   @Test
383   public void testDropAddResource() throws Exception
384   {
385     String className = TestHelper.getTestClassName();
386     String methodName = TestHelper.getTestMethodName();
387     String clusterName = className + "_" + methodName;
388     String grandClusterName = clusterName + "_grand";
389     final int n = 6;
390 
391     System.out.println("START " + clusterName + " at "
392         + new Date(System.currentTimeMillis()));
393 
394     MockParticipant[] participants = new MockParticipant[n];
395     ClusterController[] controllers = new ClusterController[2];
396     setupCluster(clusterName, grandClusterName, n, participants, controllers);
397     String command = "-zkSvr localhost:2183 -activateCluster " + clusterName
398         + " " + grandClusterName + " true";
399     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
400     Thread.sleep(500);
401 
402     // save ideal state
403     BaseDataAccessor<ZNRecord> baseAccessor = new ZkBaseDataAccessor<ZNRecord>(
404         _gZkClient);
405     HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName,
406         baseAccessor);
407     IdealState idealState = accessor.getProperty(accessor.keyBuilder()
408         .idealStates("db_11"));
409     ZNRecordJsonSerializer serializer = new ZNRecordJsonSerializer();
410 
411     String tmpDir = System.getProperty("java.io.tmpdir");
412     if (tmpDir == null)
413     {
414       tmpDir = "/tmp";
415     }
416     final String tmpIdealStateFile = tmpDir + "/" + clusterName
417         + "_idealState.log";
418     FileWriter fos = new FileWriter(tmpIdealStateFile);
419     PrintWriter pw = new PrintWriter(fos);
420     pw.write(new String(serializer.serialize(idealState.getRecord())));
421     pw.close();
422 
423     command = "-zkSvr localhost:2183 -dropResource " + clusterName + " db_11 ";
424     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
425 
426     boolean verifyResult = ClusterStateVerifier
427         .verifyByZkCallback(new BestPossAndExtViewZkVerifier(ZK_ADDR,
428             clusterName));
429     Assert.assertTrue(verifyResult);
430 
431     command = "-zkSvr localhost:2183 -addIdealState " + clusterName + " db_11 "
432         + tmpIdealStateFile;
433     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
434 
435     verifyResult = ClusterStateVerifier
436         .verifyByZkCallback(new BestPossAndExtViewZkVerifier(ZK_ADDR,
437             clusterName));
438     Assert.assertTrue(verifyResult);
439 
440     IdealState idealState2 = accessor.getProperty(accessor.keyBuilder()
441         .idealStates("db_11"));
442     Assert.assertTrue(idealState2.getRecord().equals(idealState.getRecord()));
443 
444     // clean up
445     // for (int i = 0; i < 2; i++) {
446     // controllers[i].syncStop();
447     // Thread.sleep(1000); // wait for all zk callbacks done
448     // }
449     // Thread.sleep(5000);
450     // for (int i = 0; i < n; i++) {
451     // participants[i].syncStop();
452     // }
453 
454     System.out.println("END " + clusterName + " at "
455         + new Date(System.currentTimeMillis()));
456 
457   }
458 
459   private void setupCluster(String clusterName, String grandClusterName,
460       final int n, MockParticipant[] participants,
461       ClusterController[] controllers) throws Exception, InterruptedException
462   {
463     // add cluster
464     String command = "-zkSvr localhost:2183 -addCluster " + clusterName;
465     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
466 
467     // add grand cluster
468     command = "-zkSvr localhost:2183 -addCluster " + grandClusterName;
469     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
470 
471     // add nodes
472     for (int i = 0; i < n; i++)
473     {
474       command = "-zkSvr localhost:2183 -addNode " + clusterName
475           + " localhost:123" + i;
476       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
477     }
478 
479     // add resource
480     command = "-zkSvr localhost:2183 -addResource " + clusterName
481         + " db_11 48 MasterSlave";
482     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
483 
484     // rebalance with key prefix
485     command = "-zkSvr localhost:2183 -rebalance " + clusterName
486         + " db_11 2 -key alias";
487     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
488 
489     // add nodes to grand cluster
490     command = "-zkSvr localhost:2183 -addNode " + grandClusterName
491         + " controller:9000;controller:9001";
492     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
493 
494     // start mock nodes
495     for (int i = 0; i < n; i++)
496     {
497       String instanceName = "localhost_123" + i;
498       participants[i] = new MockParticipant(clusterName, instanceName, ZK_ADDR);
499       participants[i].syncStart();
500     }
501 
502     // start controller nodes
503     for (int i = 0; i < 2; i++)
504     {
505       controllers[i] = new ClusterController(grandClusterName, "controller_900"
506           + i, ZK_ADDR, HelixControllerMain.DISTRIBUTED);
507       controllers[i].syncStart();
508     }
509 
510     Thread.sleep(100);
511   }
512 
513   @Test
514   public void testInstanceOperations() throws Exception
515   {
516     String className = TestHelper.getTestClassName();
517     String methodName = TestHelper.getTestMethodName();
518     String clusterName = className + "_" + methodName;
519     String grandClusterName = clusterName + "_grand";
520     final int n = 6;
521 
522     System.out.println("START " + clusterName + " at "
523         + new Date(System.currentTimeMillis()));
524 
525     MockParticipant[] participants = new MockParticipant[n];
526     ClusterController[] controllers = new ClusterController[2];
527     setupCluster(clusterName, grandClusterName, n, participants, controllers);
528     String command = "-zkSvr localhost:2183 -activateCluster " + clusterName
529         + " " + grandClusterName + " true";
530     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
531     Thread.sleep(500);
532 
533     // drop node should fail if the node is not disabled
534     command = "-zkSvr localhost:2183 -dropNode " + clusterName
535         + " localhost:1232";
536     try
537     {
538       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
539       Assert.fail("dropNode should fail since the node is not disabled");
540     } catch (Exception e)
541     {
542       // OK
543     }
544 
545     // disabled node
546     command = "-zkSvr localhost:2183 -enableInstance " + clusterName
547         + " localhost:1232 false";
548     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
549 
550     // Cannot dropNode if the node is not disconnected
551     command = "-zkSvr localhost:2183 -dropNode " + clusterName
552         + " localhost:1232";
553     try
554     {
555       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
556       Assert.fail("dropNode should fail since the node is not disconnected");
557     } catch (Exception e)
558     {
559       // OK
560     }
561 
562     // Cannot swapNode if the node is not disconnected
563     command = "-zkSvr localhost:2183 -swapInstance " + clusterName
564         + " localhost_1232 localhost_12320";
565     try
566     {
567       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
568       Assert
569           .fail("swapInstance should fail since the node is not disconnected");
570     } catch (Exception e)
571     {
572       // OK
573     }
574 
575     // disconnect localhost_1232
576     participants[2].syncStop();
577 
578     // add new node then swap instance
579     command = "-zkSvr localhost:2183 -addNode " + clusterName
580         + " localhost:12320";
581     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
582 
583     // swap instance. The instance get swapped out should not exist anymore
584     command = "-zkSvr localhost:2183 -swapInstance " + clusterName
585         + " localhost_1232 localhost_12320";
586     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
587 
588     BaseDataAccessor<ZNRecord> baseAccessor = new ZkBaseDataAccessor<ZNRecord>(
589         _gZkClient);
590     HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName,
591         baseAccessor);
592     String path = accessor.keyBuilder().instanceConfig("localhost_1232")
593         .getPath();
594     Assert
595         .assertFalse(
596             _gZkClient.exists(path),
597             path
598                 + " should not exist since localhost_1232 has been swapped by localhost_12320");
599 
600     System.out.println("END " + clusterName + " at "
601         + new Date(System.currentTimeMillis()));
602   }
603 
604   @Test
605   public void testExpandCluster() throws Exception
606   {
607     String className = TestHelper.getTestClassName();
608     String methodName = TestHelper.getTestMethodName();
609     String clusterName = className + "_" + methodName;
610     String grandClusterName = clusterName + "_grand";
611     final int n = 6;
612 
613     System.out.println("START " + clusterName + " at "
614         + new Date(System.currentTimeMillis()));
615 
616     MockParticipant[] participants = new MockParticipant[n];
617     ClusterController[] controllers = new ClusterController[2];
618     setupCluster(clusterName, grandClusterName, n, participants, controllers);
619     String command = "-zkSvr localhost:2183 -activateCluster " + clusterName
620         + " " + grandClusterName + " true";
621     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
622     Thread.sleep(500);
623 
624     command = "-zkSvr localhost:2183 -addNode " + clusterName
625         + " localhost:12331;localhost:12341;localhost:12351;localhost:12361";
626     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
627 
628     command = "-zkSvr localhost:2183 -expandCluster " + clusterName;
629     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
630 
631     MockParticipant[] newParticipants = new MockParticipant[4];
632     for (int i = 3; i <= 6; i++)
633     {
634       String instanceName = "localhost_123" + i + "1";
635       newParticipants[i - 3] = new MockParticipant(clusterName, instanceName,
636           ZK_ADDR);
637       newParticipants[i - 3].syncStart();
638     }
639 
640     boolean verifyResult = ClusterStateVerifier
641         .verifyByZkCallback(new MasterNbInExtViewVerifier(ZK_ADDR, clusterName));
642     Assert.assertTrue(verifyResult);
643 
644     verifyResult = ClusterStateVerifier
645         .verifyByZkCallback(new BestPossAndExtViewZkVerifier(ZK_ADDR,
646             clusterName));
647     Assert.assertTrue(verifyResult);
648 
649     System.out.println("END " + clusterName + " at "
650         + new Date(System.currentTimeMillis()));
651   }
652 
653   @Test
654   public void testDeactivateCluster() throws Exception
655   {
656     String className = TestHelper.getTestClassName();
657     String methodName = TestHelper.getTestMethodName();
658     String clusterName = className + "_" + methodName;
659     String grandClusterName = clusterName + "_grand";
660     final int n = 6;
661 
662     System.out.println("START " + clusterName + " at "
663         + new Date(System.currentTimeMillis()));
664 
665     MockParticipant[] participants = new MockParticipant[n];
666     ClusterController[] controllers = new ClusterController[2];
667     setupCluster(clusterName, grandClusterName, n, participants, controllers);
668     String command = "-zkSvr localhost:2183 -activateCluster " + clusterName
669         + " " + grandClusterName + " true";
670     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
671     Thread.sleep(500);
672 
673     // deactivate cluster
674     command = "-zkSvr localhost:2183 -activateCluster " + clusterName + " "
675         + grandClusterName + " false";
676     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
677 
678     BaseDataAccessor<ZNRecord> baseAccessor = new ZkBaseDataAccessor<ZNRecord>(
679         _gZkClient);
680     HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName,
681         baseAccessor);
682     String path = accessor.keyBuilder().controllerLeader().getPath();
683     for (int i = 0; i < 10; i++)
684     {
685       Thread.sleep(1000);
686       if (!_gZkClient.exists(path))
687       {
688         break;
689       }
690     }
691     Assert.assertFalse(_gZkClient.exists(path),
692         "leader should be gone after deactivate the cluster");
693 
694     command = "-zkSvr localhost:2183 -dropCluster " + clusterName;
695     try
696     {
697       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
698       Assert
699           .fail("dropCluster should fail since there are still instances running");
700     } catch (Exception e)
701     {
702       // OK
703     }
704 
705     for (int i = 0; i < n; i++)
706     {
707       participants[i].syncStop();
708     }
709 
710     command = "-zkSvr localhost:2183 -dropCluster " + clusterName;
711     ClusterSetup.processCommandLineArgs(command.split("\\s"));
712 
713     for (int i = 0; i < 2; i++)
714     {
715       controllers[i].syncStop();
716       Thread.sleep(1000);
717     }
718     command = "-zkSvr localhost:2183 -dropCluster " + grandClusterName;
719     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
720 
721     System.out.println("END " + clusterName + " at "
722         + new Date(System.currentTimeMillis()));
723   }
724 
725   @Test
726   public void testInstanceGroupTags() throws Exception
727   {
728     
729     String className = TestHelper.getTestClassName();
730     String methodName = TestHelper.getTestMethodName();
731     String clusterName = className + "_" + methodName;
732 
733     BaseDataAccessor<ZNRecord> baseAccessor = new ZkBaseDataAccessor<ZNRecord>(
734         _gZkClient);
735     HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName,
736         baseAccessor);
737     
738     System.out.println("START " + clusterName + " at "
739         + new Date(System.currentTimeMillis()));
740 
741     String command = "-zkSvr localhost:2183 -addCluster " + clusterName;
742     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
743 
744     command = "-zkSvr localhost:2183 -addResource " + clusterName
745         + " db_11 12 MasterSlave";
746     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
747 
748     for (int i = 0; i < 6; i++)
749     {
750       command = "-zkSvr localhost:2183 -addNode " + clusterName
751           + " localhost:123" + i;
752       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
753     }
754     
755     for (int i = 0; i < 2; i++)
756     {
757       command = "-zkSvr localhost:2183 -addInstanceTag " + clusterName
758           + " localhost_123" + i + "  tag1";
759       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
760     }
761     for (int i = 2; i < 6; i++)
762     {
763       command = "-zkSvr localhost:2183 -addInstanceTag " + clusterName
764           + " localhost_123" + i + "  tag2";
765       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
766     }
767 
768     command = "-zkSvr localhost:2183 -rebalance " + clusterName + " db_11 2 -instanceGroupTag tag1";
769     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
770     
771     IdealState dbIs = accessor.getProperty(accessor.keyBuilder().idealStates("db_11"));
772     Set<String> hosts = new HashSet<String>();
773     for(String p : dbIs.getPartitionSet())
774     {
775       for(String hostName : dbIs.getInstanceStateMap(p).keySet())
776       {
777         InstanceConfig config = accessor.getProperty(accessor.keyBuilder().instanceConfig(hostName));
778         Assert.assertTrue(config.containsTag("tag1"));
779         hosts.add(hostName);
780       }
781     }
782     Assert.assertEquals(hosts.size(), 2);
783     
784     command = "-zkSvr localhost:2183 -dropResource " + clusterName + " db_11 ";
785     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
786 
787     // re-add and rebalance
788     command = "-zkSvr localhost:2183 -addResource " + clusterName
789         + " db_11 48 MasterSlave";
790     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
791 
792     command = "-zkSvr localhost:2183 -rebalance " + clusterName + " db_11 3 -instanceGroupTag tag2";
793     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
794     
795     dbIs = accessor.getProperty(accessor.keyBuilder().idealStates("db_11"));
796      hosts = new HashSet<String>();
797     for(String p : dbIs.getPartitionSet())
798     {
799       for(String hostName : dbIs.getInstanceStateMap(p).keySet())
800       {
801         InstanceConfig config = accessor.getProperty(accessor.keyBuilder().instanceConfig(hostName));
802         Assert.assertTrue(config.containsTag("tag2"));
803         hosts.add(hostName);
804       }
805     }
806     Assert.assertEquals(hosts.size(), 4);
807     
808 
809     command = "-zkSvr localhost:2183 -dropResource " + clusterName + " db_11 ";
810     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
811     
812     for (int i = 3; i <= 3; i++)
813     {
814       command = "-zkSvr localhost:2183 -removeInstanceTag " + clusterName
815           + " localhost_123" + i + " tag2";
816       ClusterSetup.processCommandLineArgs(command.split("\\s+"));
817     }
818     
819     // re-add and rebalance
820     command = "-zkSvr localhost:2183 -addResource " + clusterName
821         + " db_11 48 MasterSlave";
822     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
823 
824     command = "-zkSvr localhost:2183 -rebalance " + clusterName + " db_11 3 -instanceGroupTag tag2";
825     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
826     dbIs = accessor.getProperty(accessor.keyBuilder().idealStates("db_11"));
827     hosts = new HashSet<String>();
828    for(String p : dbIs.getPartitionSet())
829    {
830      for(String hostName : dbIs.getInstanceStateMap(p).keySet())
831      {
832        InstanceConfig config = accessor.getProperty(accessor.keyBuilder().instanceConfig(hostName));
833        Assert.assertTrue(config.containsTag("tag2"));
834        hosts.add(hostName);
835      }
836    }
837    Assert.assertEquals(hosts.size(), 3);
838     
839     // rebalance with key prefix
840     command = "-zkSvr localhost:2183 -rebalance " + clusterName
841         + " db_11 2 -key alias";
842     ClusterSetup.processCommandLineArgs(command.split("\\s+"));
843 
844     System.out.println("END " + clusterName + " at "
845         + new Date(System.currentTimeMillis()));
846   }
847 }