1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.rsgroup;
21
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assert.assertNotNull;
25 import static org.junit.Assert.assertNull;
26 import static org.junit.Assert.assertTrue;
27 import static org.junit.Assert.fail;
28
29 import java.io.IOException;
30 import java.security.SecureRandom;
31 import java.util.HashSet;
32 import java.util.LinkedList;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36 import java.util.TreeMap;
37
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40 import org.apache.hadoop.hbase.ClusterStatus;
41 import org.apache.hadoop.hbase.HBaseCluster;
42 import org.apache.hadoop.hbase.HBaseTestingUtility;
43 import org.apache.hadoop.hbase.HColumnDescriptor;
44 import org.apache.hadoop.hbase.HRegionInfo;
45 import org.apache.hadoop.hbase.HTableDescriptor;
46 import org.apache.hadoop.hbase.NamespaceDescriptor;
47 import org.apache.hadoop.hbase.RegionLoad;
48 import org.apache.hadoop.hbase.ServerName;
49 import org.apache.hadoop.hbase.TableName;
50 import org.apache.hadoop.hbase.Waiter;
51 import org.apache.hadoop.hbase.client.ClusterConnection;
52 import org.apache.hadoop.hbase.client.HBaseAdmin;
53 import org.apache.hadoop.hbase.constraint.ConstraintException;
54 import org.apache.hadoop.hbase.master.HMaster;
55 import org.apache.hadoop.hbase.master.RegionState;
56 import org.apache.hadoop.hbase.net.Address;
57 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
58 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos;
59 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetServerInfoRequest;
60 import org.apache.hadoop.hbase.util.Bytes;
61
62 import org.junit.Assert;
63 import org.junit.Test;
64
65 import com.google.common.collect.Lists;
66 import com.google.common.collect.Maps;
67 import com.google.common.collect.Sets;
68
69 public abstract class TestRSGroupsBase {
70 protected static final Log LOG = LogFactory.getLog(TestRSGroupsBase.class);
71
72
73 protected final static String groupPrefix = "Group";
74 protected final static String tablePrefix = "Group";
75 protected final static SecureRandom rand = new SecureRandom();
76
77
78 protected static HBaseTestingUtility TEST_UTIL;
79 protected static HBaseAdmin admin;
80 protected static HBaseCluster cluster;
81 protected static RSGroupAdmin rsGroupAdmin;
82
83 public final static long WAIT_TIMEOUT = 60000*5;
84 public final static int NUM_SLAVES_BASE = 4;
85
86
87
88 protected RSGroupInfo addGroup(RSGroupAdmin gAdmin, String groupName,
89 int serverCount) throws IOException, InterruptedException {
90 RSGroupInfo defaultInfo = gAdmin
91 .getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP);
92 assertTrue(defaultInfo != null);
93 assertTrue(defaultInfo.getServers().size() >= serverCount);
94 gAdmin.addRSGroup(groupName);
95
96 Set<Address> set = new HashSet<Address>();
97 for(Address server: defaultInfo.getServers()) {
98 if(set.size() == serverCount) {
99 break;
100 }
101 set.add(server);
102 }
103 gAdmin.moveServers(set, groupName);
104 RSGroupInfo result = gAdmin.getRSGroupInfo(groupName);
105 assertTrue(result.getServers().size() >= serverCount);
106 return result;
107 }
108
109 static void removeGroup(RSGroupAdminClient groupAdmin, String groupName) throws IOException {
110 RSGroupInfo info = groupAdmin.getRSGroupInfo(groupName);
111 groupAdmin.moveTables(info.getTables(), RSGroupInfo.DEFAULT_GROUP);
112 groupAdmin.moveServers(info.getServers(), RSGroupInfo.DEFAULT_GROUP);
113 groupAdmin.removeRSGroup(groupName);
114 }
115
116 protected void deleteTableIfNecessary() throws IOException {
117 for (HTableDescriptor desc : TEST_UTIL.getHBaseAdmin().listTables(tablePrefix+".*")) {
118 TEST_UTIL.deleteTable(desc.getTableName());
119 }
120 }
121
122 protected void deleteNamespaceIfNecessary() throws IOException {
123 for (NamespaceDescriptor desc : TEST_UTIL.getHBaseAdmin().listNamespaceDescriptors()) {
124 if(desc.getName().startsWith(tablePrefix)) {
125 admin.deleteNamespace(desc.getName());
126 }
127 }
128 }
129
130 protected void deleteGroups() throws IOException {
131 try (RSGroupAdmin groupAdmin = new RSGroupAdminClient(TEST_UTIL.getConnection())) {
132 for(RSGroupInfo group: groupAdmin.listRSGroups()) {
133 if(!group.getName().equals(RSGroupInfo.DEFAULT_GROUP)) {
134 groupAdmin.moveTables(group.getTables(), RSGroupInfo.DEFAULT_GROUP);
135 groupAdmin.moveServers(group.getServers(), RSGroupInfo.DEFAULT_GROUP);
136 groupAdmin.removeRSGroup(group.getName());
137 }
138 }
139 }
140 }
141
142 public Map<TableName, List<String>> getTableRegionMap() throws IOException {
143 Map<TableName, List<String>> map = Maps.newTreeMap();
144 Map<TableName, Map<ServerName, List<String>>> tableServerRegionMap
145 = getTableServerRegionMap();
146 for(TableName tableName : tableServerRegionMap.keySet()) {
147 if(!map.containsKey(tableName)) {
148 map.put(tableName, new LinkedList<String>());
149 }
150 for(List<String> subset: tableServerRegionMap.get(tableName).values()) {
151 map.get(tableName).addAll(subset);
152 }
153 }
154 return map;
155 }
156
157 public Map<TableName, Map<ServerName, List<String>>> getTableServerRegionMap()
158 throws IOException {
159 Map<TableName, Map<ServerName, List<String>>> map = Maps.newTreeMap();
160 ClusterStatus status = TEST_UTIL.getHBaseClusterInterface().getClusterStatus();
161 for(ServerName serverName : status.getServers()) {
162 for(RegionLoad rl : status.getLoad(serverName).getRegionsLoad().values()) {
163 TableName tableName = null;
164 try {
165 tableName = HRegionInfo.getTable(rl.getName());
166 } catch (IllegalArgumentException e) {
167 LOG.warn("Failed parse a table name from regionname=" +
168 Bytes.toStringBinary(rl.getName()));
169 continue;
170 }
171 if(!map.containsKey(tableName)) {
172 map.put(tableName, new TreeMap<ServerName, List<String>>());
173 }
174 if(!map.get(tableName).containsKey(serverName)) {
175 map.get(tableName).put(serverName, new LinkedList<String>());
176 }
177 map.get(tableName).get(serverName).add(rl.getNameAsString());
178 }
179 }
180 return map;
181 }
182
183 @Test
184 public void testBogusArgs() throws Exception {
185 assertNull(rsGroupAdmin.getRSGroupInfoOfTable(TableName.valueOf("nonexistent")));
186 assertNull(rsGroupAdmin.getRSGroupOfServer(Address.fromParts("bogus",123)));
187 assertNull(rsGroupAdmin.getRSGroupInfo("bogus"));
188
189 try {
190 rsGroupAdmin.removeRSGroup("bogus");
191 fail("Expected removing bogus group to fail");
192 } catch(ConstraintException ex) {
193
194 }
195
196 try {
197 rsGroupAdmin.moveTables(Sets.newHashSet(TableName.valueOf("bogustable")), "bogus");
198 fail("Expected move with bogus group to fail");
199 } catch(ConstraintException ex) {
200
201 }
202
203 try {
204 rsGroupAdmin.moveServers(Sets.newHashSet(Address.fromParts("bogus",123)), "bogus");
205 fail("Expected move with bogus group to fail");
206 } catch(ConstraintException ex) {
207
208 }
209
210 try {
211 rsGroupAdmin.balanceRSGroup("bogus");
212 fail("Expected move with bogus group to fail");
213 } catch(ConstraintException ex) {
214
215 }
216 }
217
218 @Test
219 public void testCreateMultiRegion() throws IOException {
220 LOG.info("testCreateMultiRegion");
221 TableName tableName = TableName.valueOf(tablePrefix + "_testCreateMultiRegion");
222 byte[] end = {1,3,5,7,9};
223 byte[] start = {0,2,4,6,8};
224 byte[][] f = {Bytes.toBytes("f")};
225 TEST_UTIL.createTable(tableName, f,1,start,end,10);
226 }
227
228 @Test
229 public void testCreateAndDrop() throws Exception {
230 LOG.info("testCreateAndDrop");
231
232 final TableName tableName = TableName.valueOf(tablePrefix + "_testCreateAndDrop");
233 TEST_UTIL.createTable(tableName, Bytes.toBytes("cf"));
234
235 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
236 @Override
237 public boolean evaluate() throws Exception {
238 return getTableRegionMap().get(tableName) != null;
239 }
240 });
241 TEST_UTIL.deleteTable(tableName);
242 }
243
244 @Test
245 public void testSimpleRegionServerMove() throws IOException,
246 InterruptedException {
247 LOG.info("testSimpleRegionServerMove");
248
249 int initNumGroups = rsGroupAdmin.listRSGroups().size();
250 RSGroupInfo appInfo = addGroup(rsGroupAdmin, getGroupName("testSimpleRegionServerMove"), 1);
251 RSGroupInfo adminInfo = addGroup(rsGroupAdmin, getGroupName("testSimpleRegionServerMove"), 1);
252 RSGroupInfo dInfo = rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP);
253 Assert.assertEquals(initNumGroups + 2, rsGroupAdmin.listRSGroups().size());
254 assertEquals(1, adminInfo.getServers().size());
255 assertEquals(1, appInfo.getServers().size());
256 assertEquals(getNumServers() - 2, dInfo.getServers().size());
257 rsGroupAdmin.moveServers(appInfo.getServers(),
258 RSGroupInfo.DEFAULT_GROUP);
259 rsGroupAdmin.removeRSGroup(appInfo.getName());
260 rsGroupAdmin.moveServers(adminInfo.getServers(),
261 RSGroupInfo.DEFAULT_GROUP);
262 rsGroupAdmin.removeRSGroup(adminInfo.getName());
263 Assert.assertEquals(rsGroupAdmin.listRSGroups().size(), initNumGroups);
264 }
265
266
267 public int getNumServers() throws IOException {
268 ClusterStatus status = admin.getClusterStatus();
269 ServerName master = status.getMaster();
270 int count = 0;
271 for (ServerName sn : status.getServers()) {
272 if (!sn.equals(master)) {
273 count++;
274 }
275 }
276 return count;
277 }
278
279 @Test
280 public void testMoveServers() throws Exception {
281 LOG.info("testMoveServers");
282
283
284 addGroup(rsGroupAdmin, "bar", 3);
285 rsGroupAdmin.addRSGroup("foo");
286
287 RSGroupInfo barGroup = rsGroupAdmin.getRSGroupInfo("bar");
288 RSGroupInfo fooGroup = rsGroupAdmin.getRSGroupInfo("foo");
289 assertEquals(3, barGroup.getServers().size());
290 assertEquals(0, fooGroup.getServers().size());
291
292
293 try {
294 rsGroupAdmin.moveServers(Sets.newHashSet(Address.fromString("foo:9999")),"foo");
295 fail("Bogus servers shouldn't have been successfully moved.");
296 } catch(IOException ex) {
297 String exp = "Server foo:9999 does not have a group.";
298 String msg = "Expected '"+exp+"' in exception message: ";
299 assertTrue(msg+" "+ex.getMessage(), ex.getMessage().contains(exp));
300 }
301
302
303 LOG.info("moving servers "+barGroup.getServers()+" to group foo");
304 rsGroupAdmin.moveServers(barGroup.getServers(), fooGroup.getName());
305
306 barGroup = rsGroupAdmin.getRSGroupInfo("bar");
307 fooGroup = rsGroupAdmin.getRSGroupInfo("foo");
308 assertEquals(0,barGroup.getServers().size());
309 assertEquals(3,fooGroup.getServers().size());
310
311 LOG.info("moving servers "+fooGroup.getServers()+" to group default");
312 rsGroupAdmin.moveServers(fooGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);
313
314 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
315 @Override
316 public boolean evaluate() throws Exception {
317 return getNumServers() ==
318 rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getServers().size();
319 }
320 });
321
322 fooGroup = rsGroupAdmin.getRSGroupInfo("foo");
323 assertEquals(0,fooGroup.getServers().size());
324
325
326 LOG.info("Remove group "+barGroup.getName());
327 rsGroupAdmin.removeRSGroup(barGroup.getName());
328 Assert.assertEquals(null, rsGroupAdmin.getRSGroupInfo(barGroup.getName()));
329 LOG.info("Remove group "+fooGroup.getName());
330 rsGroupAdmin.removeRSGroup(fooGroup.getName());
331 Assert.assertEquals(null, rsGroupAdmin.getRSGroupInfo(fooGroup.getName()));
332 }
333
334 @Test
335 public void testTableMoveTruncateAndDrop() throws Exception {
336 LOG.info("testTableMove");
337
338 final TableName tableName = TableName.valueOf(tablePrefix + "_testTableMoveAndDrop");
339 final byte[] familyNameBytes = Bytes.toBytes("f");
340 String newGroupName = getGroupName("testTableMove");
341 final RSGroupInfo newGroup = addGroup(rsGroupAdmin, newGroupName, 2);
342
343 TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 5);
344 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
345 @Override
346 public boolean evaluate() throws Exception {
347 List<String> regions = getTableRegionMap().get(tableName);
348 if (regions == null)
349 return false;
350 return getTableRegionMap().get(tableName).size() >= 5;
351 }
352 });
353
354 RSGroupInfo tableGrp = rsGroupAdmin.getRSGroupInfoOfTable(tableName);
355 assertTrue(tableGrp.getName().equals(RSGroupInfo.DEFAULT_GROUP));
356
357
358 LOG.info("Moving table "+tableName+" to "+newGroup.getName());
359 rsGroupAdmin.moveTables(Sets.newHashSet(tableName), newGroup.getName());
360
361
362 Assert.assertEquals(newGroup.getName(),
363 rsGroupAdmin.getRSGroupInfoOfTable(tableName).getName());
364
365 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
366 @Override
367 public boolean evaluate() throws Exception {
368 Map<ServerName, List<String>> serverMap = getTableServerRegionMap().get(tableName);
369 int count = 0;
370 if (serverMap != null) {
371 for (ServerName rs : serverMap.keySet()) {
372 if (newGroup.containsServer(rs.getAddress())) {
373 count += serverMap.get(rs).size();
374 }
375 }
376 }
377 return count == 5;
378 }
379 });
380
381
382 admin.disableTable(tableName);
383 admin.truncateTable(tableName, true);
384 Assert.assertEquals(1, rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getTables().size());
385 Assert.assertEquals(tableName, rsGroupAdmin.getRSGroupInfo(
386 newGroup.getName()).getTables().first());
387
388
389 TEST_UTIL.deleteTable(tableName);
390 Assert.assertEquals(0, rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getTables().size());
391 }
392
393 @Test
394 public void testGroupBalance() throws Exception {
395 LOG.info("testGroupBalance");
396 String newGroupName = getGroupName("testGroupBalance");
397 final RSGroupInfo newGroup = addGroup(rsGroupAdmin, newGroupName, 3);
398
399 final TableName tableName = TableName.valueOf(tablePrefix+"_ns", "testGroupBalance");
400 admin.createNamespace(
401 NamespaceDescriptor.create(tableName.getNamespaceAsString())
402 .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, newGroupName).build());
403 final byte[] familyNameBytes = Bytes.toBytes("f");
404 final HTableDescriptor desc = new HTableDescriptor(tableName);
405 desc.addFamily(new HColumnDescriptor("f"));
406 byte [] startKey = Bytes.toBytes("aaaaa");
407 byte [] endKey = Bytes.toBytes("zzzzz");
408 admin.createTable(desc, startKey, endKey, 6);
409 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
410 @Override
411 public boolean evaluate() throws Exception {
412 List<String> regions = getTableRegionMap().get(tableName);
413 if (regions == null) {
414 return false;
415 }
416 return regions.size() >= 6;
417 }
418 });
419
420
421 Map<ServerName,List<String>> assignMap =
422 getTableServerRegionMap().get(tableName);
423 final ServerName first = assignMap.entrySet().iterator().next().getKey();
424 for(HRegionInfo region: admin.getTableRegions(tableName)) {
425 if(!assignMap.get(first).contains(region.getRegionNameAsString())) {
426 admin.move(region.getEncodedNameAsBytes(), Bytes.toBytes(first.getServerName()));
427 }
428 }
429 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
430 @Override
431 public boolean evaluate() throws Exception {
432 Map<ServerName, List<String>> map = getTableServerRegionMap().get(tableName);
433 if (map == null) {
434 return true;
435 }
436 List<String> regions = map.get(first);
437 if (regions == null) {
438 return true;
439 }
440 return regions.size() >= 6;
441 }
442 });
443
444
445 rsGroupAdmin.balanceRSGroup(RSGroupInfo.DEFAULT_GROUP);
446 assertEquals(6, getTableServerRegionMap().get(tableName).get(first).size());
447
448 rsGroupAdmin.balanceRSGroup(newGroupName);
449 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
450 @Override
451 public boolean evaluate() throws Exception {
452 for (List<String> regions : getTableServerRegionMap().get(tableName).values()) {
453 if (2 != regions.size()) {
454 return false;
455 }
456 }
457 return true;
458 }
459 });
460 }
461
462 @Test
463 public void testRegionMove() throws Exception {
464 LOG.info("testRegionMove");
465
466 final RSGroupInfo newGroup = addGroup(rsGroupAdmin, getGroupName("testRegionMove"), 1);
467 final TableName tableName = TableName.valueOf(tablePrefix + rand.nextInt());
468 final byte[] familyNameBytes = Bytes.toBytes("f");
469
470 TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 6);
471 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
472 @Override
473 public boolean evaluate() throws Exception {
474 List<String> regions = getTableRegionMap().get(tableName);
475 if (regions == null)
476 return false;
477 return getTableRegionMap().get(tableName).size() >= 6;
478 }
479 });
480
481
482 Map<ServerName,List<String>> assignMap =
483 getTableServerRegionMap().get(tableName);
484 String targetRegion = null;
485 for(ServerName server : assignMap.keySet()) {
486 targetRegion = assignMap.get(server).size() > 0 ? assignMap.get(server).get(0) : null;
487 if(targetRegion != null) {
488 break;
489 }
490 }
491
492 ServerName targetServer = null;
493 for(ServerName server : admin.getClusterStatus().getServers()) {
494 if(!newGroup.containsServer(server.getAddress())) {
495 targetServer = server;
496 break;
497 }
498 }
499 assertNotNull(targetServer);
500
501 final AdminProtos.AdminService.BlockingInterface targetRS =
502 admin.getConnection().getAdmin(targetServer);
503
504
505 rsGroupAdmin.moveServers(Sets.newHashSet(targetServer.getAddress()),
506 newGroup.getName());
507 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
508 @Override
509 public boolean evaluate() throws Exception {
510 return ProtobufUtil.getOnlineRegions(targetRS).size() <= 0;
511 }
512 });
513
514
515 TEST_UTIL.getHBaseAdmin().move(Bytes.toBytes(HRegionInfo.encodeRegionName(Bytes.toBytes(targetRegion))),
516 Bytes.toBytes(targetServer.getServerName()));
517 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
518 @Override
519 public boolean evaluate() throws Exception {
520 List<String> regions = getTableRegionMap().get(tableName);
521 Set<RegionState> regionsInTransition = admin.getClusterStatus().getRegionsInTransition();
522 return (regions != null && getTableRegionMap().get(tableName).size() == 6) &&
523 ( regionsInTransition == null || regionsInTransition.size() < 1);
524 }
525 });
526
527
528 for (HRegionInfo region: ProtobufUtil.getOnlineRegions(targetRS)) {
529 if (targetRegion.equals(region.getRegionNameAsString())) {
530 fail("Target server opened region");
531 }
532 }
533 }
534
535 @Test
536 public void testFailRemoveGroup() throws IOException, InterruptedException {
537 LOG.info("testFailRemoveGroup");
538
539 int initNumGroups = rsGroupAdmin.listRSGroups().size();
540 addGroup(rsGroupAdmin, "bar", 3);
541 TableName tableName = TableName.valueOf(tablePrefix+"_my_table");
542 TEST_UTIL.createTable(tableName, Bytes.toBytes("f"));
543 rsGroupAdmin.moveTables(Sets.newHashSet(tableName), "bar");
544 RSGroupInfo barGroup = rsGroupAdmin.getRSGroupInfo("bar");
545
546 try {
547 rsGroupAdmin.removeRSGroup(barGroup.getName());
548 fail("Expected remove group to fail");
549 } catch(IOException e) {
550 }
551
552 try {
553 rsGroupAdmin.moveServers(barGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);
554 fail("Expected move servers to fail");
555 } catch(IOException e) {
556 }
557
558 rsGroupAdmin.moveTables(barGroup.getTables(), RSGroupInfo.DEFAULT_GROUP);
559 try {
560 rsGroupAdmin.removeRSGroup(barGroup.getName());
561 fail("Expected move servers to fail");
562 } catch(IOException e) {
563 }
564
565 rsGroupAdmin.moveServers(barGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);
566 rsGroupAdmin.removeRSGroup(barGroup.getName());
567
568 Assert.assertEquals(initNumGroups, rsGroupAdmin.listRSGroups().size());
569 }
570
571 @Test
572 public void testKillRS() throws Exception {
573 LOG.info("testKillRS");
574 RSGroupInfo appInfo = addGroup(rsGroupAdmin, "appInfo", 1);
575
576 final TableName tableName = TableName.valueOf(tablePrefix+"_ns", "_testKillRS");
577 admin.createNamespace(
578 NamespaceDescriptor.create(tableName.getNamespaceAsString())
579 .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, appInfo.getName()).build());
580 final HTableDescriptor desc = new HTableDescriptor(tableName);
581 desc.addFamily(new HColumnDescriptor("f"));
582 admin.createTable(desc);
583
584 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
585 @Override
586 public boolean evaluate() throws Exception {
587 return getTableRegionMap().get(desc.getTableName()) != null;
588 }
589 });
590
591 ServerName targetServer = ServerName.parseServerName(
592 appInfo.getServers().iterator().next().toString());
593 AdminProtos.AdminService.BlockingInterface targetRS =
594 admin.getConnection().getAdmin(targetServer);
595 Assert.assertEquals(1, ProtobufUtil.getOnlineRegions(targetRS).size());
596
597 try {
598
599
600 targetRS.stopServer(null,
601 AdminProtos.StopServerRequest.newBuilder().setReason("Die").build());
602 } catch(Exception e) {
603 }
604 assertFalse(cluster.getClusterStatus().getServers().contains(targetServer));
605
606
607 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
608 @Override
609 public boolean evaluate() throws Exception {
610 return cluster.getClusterStatus().getRegionsInTransition().size() == 0;
611 }
612 });
613 Set<Address> newServers = Sets.newHashSet();
614 newServers.add(
615 rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getServers().iterator().next());
616 rsGroupAdmin.moveServers(newServers, appInfo.getName());
617
618
619
620 admin.disableTable(tableName);
621 admin.enableTable(tableName);
622
623
624 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
625 @Override
626 public boolean evaluate() throws Exception {
627 return cluster.getClusterStatus().getRegionsInTransition().size() == 0;
628 }
629 });
630
631 targetServer = ServerName.parseServerName(
632 newServers.iterator().next().toString());
633 targetRS =
634 admin.getConnection().getAdmin(targetServer);
635 Assert.assertEquals(1, ProtobufUtil.getOnlineRegions(targetRS).size());
636 Assert.assertEquals(tableName,
637 ProtobufUtil.getOnlineRegions(targetRS).get(0).getTable());
638 }
639
640 @Test
641 public void testValidGroupNames() throws IOException {
642 String[] badNames = {"foo*","foo@","-"};
643 String[] goodNames = {"foo_123"};
644
645 for(String entry: badNames) {
646 try {
647 rsGroupAdmin.addRSGroup(entry);
648 fail("Expected a constraint exception for: "+entry);
649 } catch(ConstraintException ex) {
650
651 }
652 }
653
654 for(String entry: goodNames) {
655 rsGroupAdmin.addRSGroup(entry);
656 }
657 }
658
659 private String getGroupName(String baseName) {
660 return groupPrefix+"_"+baseName+"_"+rand.nextInt(Integer.MAX_VALUE);
661 }
662
663 @Test
664 public void testMultiTableMove() throws Exception {
665 LOG.info("testMultiTableMove");
666
667 final TableName tableNameA = TableName.valueOf(tablePrefix + "_testMultiTableMoveA");
668 final TableName tableNameB = TableName.valueOf(tablePrefix + "_testMultiTableMoveB");
669 final byte[] familyNameBytes = Bytes.toBytes("f");
670 String newGroupName = getGroupName("testMultiTableMove");
671 final RSGroupInfo newGroup = addGroup(rsGroupAdmin, newGroupName, 1);
672
673 TEST_UTIL.createTable(tableNameA, familyNameBytes);
674 TEST_UTIL.createTable(tableNameB, familyNameBytes);
675 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
676 @Override
677 public boolean evaluate() throws Exception {
678 List<String> regionsA = getTableRegionMap().get(tableNameA);
679 if (regionsA == null)
680 return false;
681 List<String> regionsB = getTableRegionMap().get(tableNameB);
682 if (regionsB == null)
683 return false;
684
685 return getTableRegionMap().get(tableNameA).size() >= 1
686 && getTableRegionMap().get(tableNameB).size() >= 1;
687 }
688 });
689
690 RSGroupInfo tableGrpA = rsGroupAdmin.getRSGroupInfoOfTable(tableNameA);
691 assertTrue(tableGrpA.getName().equals(RSGroupInfo.DEFAULT_GROUP));
692
693 RSGroupInfo tableGrpB = rsGroupAdmin.getRSGroupInfoOfTable(tableNameB);
694 assertTrue(tableGrpB.getName().equals(RSGroupInfo.DEFAULT_GROUP));
695
696 LOG.info("Moving table [" + tableNameA + "," + tableNameB + "] to " + newGroup.getName());
697 rsGroupAdmin.moveTables(Sets.newHashSet(tableNameA, tableNameB), newGroup.getName());
698
699
700 Assert.assertEquals(newGroup.getName(),
701 rsGroupAdmin.getRSGroupInfoOfTable(tableNameA).getName());
702
703 Assert.assertEquals(newGroup.getName(),
704 rsGroupAdmin.getRSGroupInfoOfTable(tableNameB).getName());
705
706
707 Set<TableName> DefaultTables = rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getTables();
708 assertFalse(DefaultTables.contains(tableNameA));
709 assertFalse(DefaultTables.contains(tableNameB));
710
711
712 Set<TableName> newGroupTables = rsGroupAdmin.getRSGroupInfo(newGroupName).getTables();
713 assertTrue(newGroupTables.contains(tableNameA));
714 assertTrue(newGroupTables.contains(tableNameB));
715 }
716
717 @Test
718 public void testMoveServersAndTables() throws Exception {
719 final TableName tableName = TableName.valueOf(tablePrefix + "_testMoveServersAndTables");
720 final RSGroupInfo newGroup = addGroup(rsGroupAdmin, getGroupName("testMoveServersAndTables"), 1);
721
722
723 final byte[] familyNameBytes = Bytes.toBytes("f");
724 TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 5);
725 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
726 @Override
727 public boolean evaluate() throws Exception {
728 List<String> regions = getTableRegionMap().get(tableName);
729 if (regions == null)
730 return false;
731 return getTableRegionMap().get(tableName).size() >= 5;
732 }
733 });
734
735
736 ServerName targetServer = null;
737 for(ServerName server : admin.getClusterStatus().getServers()) {
738 if(!newGroup.containsServer(server.getAddress()) &&
739 !rsGroupAdmin.getRSGroupInfo("master").containsServer(server.getAddress())) {
740 targetServer = server;
741 break;
742 }
743 }
744
745 LOG.debug("Print group info : " + rsGroupAdmin.listRSGroups());
746 int oldDefaultGroupServerSize =
747 rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getServers().size();
748 int oldDefaultGroupTableSize =
749 rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getTables().size();
750
751
752 try {
753 rsGroupAdmin.moveServersAndTables(Sets.newHashSet(Address.fromString("foo:9999")),
754 Sets.newHashSet(tableName), newGroup.getName());
755 fail("Bogus servers shouldn't have been successfully moved.");
756 } catch(IOException ex) {
757 }
758
759
760 try {
761 rsGroupAdmin.moveServersAndTables(Sets.newHashSet(targetServer.getAddress()),
762 Sets.newHashSet(tableName), RSGroupInfo.DEFAULT_GROUP);
763 fail("servers shouldn't have been successfully moved.");
764 } catch(IOException ex) {
765 }
766
767
768 Assert.assertEquals(oldDefaultGroupServerSize,
769 rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getServers().size());
770 Assert.assertEquals(oldDefaultGroupTableSize,
771 rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getTables().size());
772
773
774 Assert.assertEquals(1,
775 rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getServers().size());
776 Assert.assertEquals(0,
777 rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getTables().size());
778
779
780 List<String> regionList = getTableRegionMap().get(tableName);
781 for(String region : regionList) {
782
783 admin.move(Bytes.toBytes(HRegionInfo.encodeRegionName(Bytes.toBytes(region))),
784 Bytes.toBytes(targetServer.getServerName()));
785 }
786
787 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
788 @Override
789 public boolean evaluate() throws Exception {
790 List<String> regions = getTableRegionMap().get(tableName);
791 Map<ServerName, List<String>> serverMap = getTableServerRegionMap().get(tableName);
792 Set<RegionState> regionsInTransition = admin.getClusterStatus().getRegionsInTransition();
793 return (regions != null && regions.size() == 5) &&
794 (serverMap != null && serverMap.size() == 1) &&
795 (regionsInTransition == null || regionsInTransition.size() < 1);
796 }
797 });
798
799
800 Assert.assertNotNull(getTableServerRegionMap().get(tableName));
801 Assert.assertNotNull(getTableServerRegionMap().get(tableName).get(targetServer));
802 Assert.assertEquals(5, getTableServerRegionMap().get(tableName).get(targetServer).size());
803
804
805 LOG.info("moving server and table to newGroup");
806 rsGroupAdmin.moveServersAndTables(Sets.newHashSet(targetServer.getAddress()),
807 Sets.newHashSet(tableName), newGroup.getName());
808
809
810 Assert.assertEquals(newGroup.getName(),
811 rsGroupAdmin.getRSGroupInfoOfTable(tableName).getName());
812
813
814 Set<Address> defaultServers = rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getServers();
815 assertFalse(defaultServers.contains(targetServer.getAddress()));
816
817
818 Set<Address> newGroupServers = rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getServers();
819 assertTrue(newGroupServers.contains(targetServer.getAddress()));
820
821
822 Set<TableName> defaultTables = rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getTables();
823 assertFalse(defaultTables.contains(tableName));
824
825
826 Set<TableName> newGroupTables = rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getTables();
827 assertTrue(newGroupTables.contains(tableName));
828 }
829
830 @Test
831 public void testDisabledTableMove() throws Exception {
832 final TableName tableName = TableName.valueOf(tablePrefix + "_testDisabledTableMove");
833 final byte[] familyNameBytes = Bytes.toBytes("f");
834 String newGroupName = getGroupName("testDisabledTableMove");
835 final RSGroupInfo newGroup = addGroup(rsGroupAdmin, newGroupName, 2);
836
837 TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 5);
838 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
839 @Override
840 public boolean evaluate() throws Exception {
841 List<String> regions = getTableRegionMap().get(tableName);
842 if (regions == null) {
843 return false;
844 }
845 return getTableRegionMap().get(tableName).size() >= 5;
846 }
847 });
848
849 RSGroupInfo tableGrp = rsGroupAdmin.getRSGroupInfoOfTable(tableName);
850 assertTrue(tableGrp.getName().equals(RSGroupInfo.DEFAULT_GROUP));
851
852
853 admin.disableTable(tableName);
854
855
856 LOG.info("Moving table "+ tableName + " to " + newGroup.getName());
857 rsGroupAdmin.moveTables(Sets.newHashSet(tableName), newGroup.getName());
858
859
860 Assert.assertEquals(newGroup.getName(),
861 rsGroupAdmin.getRSGroupInfoOfTable(tableName).getName());
862 }
863
864 @Test
865 public void testClearDeadServers() throws Exception {
866 final RSGroupInfo newGroup = addGroup(rsGroupAdmin, "testClearDeadServers", 3);
867
868 ServerName targetServer = ServerName.parseServerName(
869 newGroup.getServers().iterator().next().toString());
870 AdminProtos.AdminService.BlockingInterface targetRS =
871 ((ClusterConnection) admin.getConnection()).getAdmin(targetServer);
872 try {
873 targetServer = ProtobufUtil.toServerName(targetRS.getServerInfo(null,
874 GetServerInfoRequest.newBuilder().build()).getServerInfo().getServerName());
875
876
877 targetRS.stopServer(null,
878 AdminProtos.StopServerRequest.newBuilder().setReason("Die").build());
879 } catch(Exception e) {
880 }
881 final HMaster master = TEST_UTIL.getHBaseCluster().getMaster();
882
883 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
884 @Override
885 public boolean evaluate() throws Exception {
886 return !master.getServerManager().areDeadServersInProgress()
887 && cluster.getClusterStatus().getDeadServerNames().size() > 0;
888 }
889 });
890 assertFalse(cluster.getClusterStatus().getServers().contains(targetServer));
891 assertTrue(cluster.getClusterStatus().getDeadServerNames().contains(targetServer));
892 assertTrue(newGroup.getServers().contains(targetServer.getAddress()));
893
894
895 List<ServerName> notClearedServers = admin.clearDeadServers(Lists.newArrayList(targetServer));
896 assertEquals(0, notClearedServers.size());
897
898 Set<Address> newGroupServers = rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getServers();
899 assertFalse(newGroupServers.contains(targetServer.getAddress()));
900 assertEquals(2, newGroupServers.size());
901 }
902
903 @Test
904 public void testRemoveServers() throws Exception {
905 final RSGroupInfo newGroup = addGroup(rsGroupAdmin, "testRemoveServers", 3);
906 ServerName targetServer = ServerName.parseServerName(
907 newGroup.getServers().iterator().next().toString());
908 try {
909 rsGroupAdmin.removeServers(Sets.newHashSet(targetServer.getAddress()));
910 fail("Online servers shouldn't have been successfully removed.");
911 } catch(IOException ex) {
912 String exp = "Server " + targetServer.getAddress()
913 + " is an online server, not allowed to remove.";
914 String msg = "Expected '" + exp + "' in exception message: ";
915 assertTrue(msg + " " + ex.getMessage(), ex.getMessage().contains(exp));
916 }
917 assertTrue(newGroup.getServers().contains(targetServer.getAddress()));
918
919 AdminProtos.AdminService.BlockingInterface targetRS =
920 ((ClusterConnection) admin.getConnection()).getAdmin(targetServer);
921 try {
922 targetServer = ProtobufUtil.toServerName(targetRS.getServerInfo(null,
923 GetServerInfoRequest.newBuilder().build()).getServerInfo().getServerName());
924
925
926 targetRS.stopServer(null,
927 AdminProtos.StopServerRequest.newBuilder().setReason("Die").build());
928 } catch(Exception e) {
929 }
930
931 final HMaster master = TEST_UTIL.getHBaseCluster().getMaster();
932
933 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
934 @Override
935 public boolean evaluate() throws Exception {
936 return !master.getServerManager().areDeadServersInProgress()
937 && cluster.getClusterStatus().getDeadServerNames().size() > 0;
938 }
939 });
940
941 try {
942 rsGroupAdmin.removeServers(Sets.newHashSet(targetServer.getAddress()));
943 fail("Dead servers shouldn't have been successfully removed.");
944 } catch(IOException ex) {
945 String exp = "Server " + targetServer.getAddress() + " is on the dead servers list,"
946 + " Maybe it will come back again, not allowed to remove.";
947 String msg = "Expected '" + exp + "' in exception message: ";
948 assertTrue(msg + " " + ex.getMessage(), ex.getMessage().contains(exp));
949 }
950 assertTrue(newGroup.getServers().contains(targetServer.getAddress()));
951
952 ServerName sn = TEST_UTIL.getHBaseClusterInterface().getClusterStatus().getMaster();
953 TEST_UTIL.getHBaseClusterInterface().stopMaster(sn);
954 TEST_UTIL.getHBaseClusterInterface().waitForMasterToStop(sn, 60000);
955 TEST_UTIL.getHBaseClusterInterface().startMaster(sn.getHostname(), 0);
956 TEST_UTIL.getHBaseClusterInterface().waitForActiveAndReadyMaster(60000);
957
958 assertEquals(3, cluster.getClusterStatus().getServersSize());
959 assertFalse(cluster.getClusterStatus().getServers().contains(targetServer));
960 assertFalse(cluster.getClusterStatus().getDeadServerNames().contains(targetServer));
961 assertTrue(newGroup.getServers().contains(targetServer.getAddress()));
962
963 rsGroupAdmin.removeServers(Sets.newHashSet(targetServer.getAddress()));
964 Set<Address> newGroupServers = rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getServers();
965 assertFalse(newGroupServers.contains(targetServer.getAddress()));
966 assertEquals(2, newGroupServers.size());
967 }
968 }