001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.rsgroup;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertFalse;
022import static org.junit.Assert.assertNotNull;
023import static org.junit.Assert.assertNull;
024import static org.junit.Assert.assertTrue;
025import static org.junit.Assert.fail;
026
027import java.io.IOException;
028import java.util.List;
029import java.util.Map;
030import java.util.Set;
031import org.apache.hadoop.hbase.HBaseClassTestRule;
032import org.apache.hadoop.hbase.NamespaceDescriptor;
033import org.apache.hadoop.hbase.ServerName;
034import org.apache.hadoop.hbase.TableExistsException;
035import org.apache.hadoop.hbase.TableName;
036import org.apache.hadoop.hbase.TableNotFoundException;
037import org.apache.hadoop.hbase.Waiter;
038import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
039import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
040import org.apache.hadoop.hbase.client.TableDescriptor;
041import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
042import org.apache.hadoop.hbase.constraint.ConstraintException;
043import org.apache.hadoop.hbase.master.TableNamespaceManager;
044import org.apache.hadoop.hbase.net.Address;
045import org.apache.hadoop.hbase.testclassification.MediumTests;
046import org.apache.hadoop.hbase.testclassification.RSGroupTests;
047import org.apache.hadoop.hbase.util.Bytes;
048import org.junit.After;
049import org.junit.AfterClass;
050import org.junit.Before;
051import org.junit.BeforeClass;
052import org.junit.ClassRule;
053import org.junit.Test;
054import org.junit.experimental.categories.Category;
055import org.slf4j.Logger;
056import org.slf4j.LoggerFactory;
057
058import org.apache.hbase.thirdparty.com.google.common.collect.Sets;
059
060@Category({ RSGroupTests.class, MediumTests.class })
061public class TestRSGroupsAdmin1 extends TestRSGroupsBase {
062
063  @ClassRule
064  public static final HBaseClassTestRule CLASS_RULE =
065    HBaseClassTestRule.forClass(TestRSGroupsAdmin1.class);
066
067  private static final Logger LOG = LoggerFactory.getLogger(TestRSGroupsAdmin1.class);
068
069  @BeforeClass
070  public static void setUp() throws Exception {
071    setUpTestBeforeClass();
072  }
073
074  @AfterClass
075  public static void tearDown() throws Exception {
076    tearDownAfterClass();
077  }
078
079  @Before
080  public void beforeMethod() throws Exception {
081    setUpBeforeMethod();
082  }
083
084  @After
085  public void afterMethod() throws Exception {
086    tearDownAfterMethod();
087  }
088
089  @Test
090  public void testValidGroupNames() throws IOException {
091    String[] badNames = { "foo*", "foo@", "-" };
092    String[] goodNames = { "foo_123" };
093
094    for (String entry : badNames) {
095      try {
096        ADMIN.addRSGroup(entry);
097        fail("Expected a constraint exception for: " + entry);
098      } catch (ConstraintException ex) {
099        // expected
100      }
101    }
102
103    for (String entry : goodNames) {
104      ADMIN.addRSGroup(entry);
105    }
106  }
107
108  @Test
109  public void testBogusArgs() throws Exception {
110    assertNull(ADMIN.getRSGroup(TableName.valueOf("nonexistent")));
111    assertNull(ADMIN.getRSGroup(Address.fromParts("bogus", 123)));
112    assertNull(ADMIN.getRSGroup("bogus"));
113
114    try {
115      ADMIN.removeRSGroup("bogus");
116      fail("Expected removing bogus group to fail");
117    } catch (ConstraintException ex) {
118      // expected
119    }
120
121    try {
122      ADMIN.setRSGroup(Sets.newHashSet(TableName.valueOf("bogustable")), "bogus");
123      fail("Expected set table to bogus group fail");
124    } catch (ConstraintException | TableNotFoundException ex) {
125      // expected
126    }
127
128    try {
129      ADMIN.moveServersToRSGroup(Sets.newHashSet(Address.fromParts("bogus", 123)), "bogus");
130      fail("Expected move with bogus group to fail");
131    } catch (ConstraintException ex) {
132      // expected
133    }
134
135    try {
136      ADMIN.balancerSwitch(true, true);
137      ADMIN.balanceRSGroup("bogus");
138      ADMIN.balancerSwitch(false, true);
139      fail("Expected move with bogus group to fail");
140    } catch (ConstraintException ex) {
141      // expected
142    }
143  }
144
145  @Test
146  public void testNamespaceConstraint() throws Exception {
147    String nsName = TABLE_PREFIX + "_foo";
148    String groupName = TABLE_PREFIX + "_foo";
149    LOG.info("testNamespaceConstraint");
150    addGroup(groupName, 1);
151    assertTrue(OBSERVER.preAddRSGroupCalled);
152    assertTrue(OBSERVER.postAddRSGroupCalled);
153
154    ADMIN.createNamespace(NamespaceDescriptor.create(nsName)
155      .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, groupName).build());
156    RSGroupInfo rsGroupInfo = ADMIN.getRSGroup(groupName);
157    ADMIN.moveServersToRSGroup(rsGroupInfo.getServers(), RSGroupInfo.DEFAULT_GROUP);
158    // test removing a referenced group
159    try {
160      ADMIN.removeRSGroup(groupName);
161      fail("Expected a constraint exception");
162    } catch (IOException ex) {
163    }
164    // test modify group
165    // changing with the same name is fine
166    ADMIN.modifyNamespace(NamespaceDescriptor.create(nsName)
167      .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, groupName).build());
168    String anotherGroup = TABLE_PREFIX + "_anotherGroup";
169    ADMIN.addRSGroup(anotherGroup);
170    // test add non-existent group
171    ADMIN.deleteNamespace(nsName);
172    ADMIN.removeRSGroup(groupName);
173    assertTrue(OBSERVER.preRemoveRSGroupCalled);
174    assertTrue(OBSERVER.postRemoveRSGroupCalled);
175    try {
176      ADMIN.createNamespace(NamespaceDescriptor.create(nsName)
177        .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, "foo").build());
178      fail("Expected a constraint exception");
179    } catch (IOException ex) {
180    }
181  }
182
183  @Test
184  public void testNamespaceConstraint2() throws Exception {
185    String nsName = TABLE_PREFIX + name.getMethodName();
186    String groupName = TABLE_PREFIX + name.getMethodName();
187    TableName tableName = TableName.valueOf(nsName, name.getMethodName());
188    addGroup(groupName, 1);
189
190    ADMIN.createNamespace(NamespaceDescriptor.create(nsName)
191      .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, groupName).build());
192
193    TEST_UTIL.createTable(tableName, "C");
194    TEST_UTIL.waitTableAvailable(tableName);
195    RSGroupInfo rsGroup = ADMIN.getRSGroup(tableName);
196    assertEquals(groupName, rsGroup.getName());
197
198    TEST_UTIL.deleteTable(tableName);
199    ADMIN.deleteNamespace(nsName);
200
201    ADMIN.moveServersToRSGroup(rsGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);
202    ADMIN.removeRSGroup(groupName);
203  }
204
205  @Test
206  public void testFailRemoveGroup() throws IOException, InterruptedException {
207    int initNumGroups = ADMIN.listRSGroups().size();
208    addGroup("bar", 3);
209    TEST_UTIL.createTable(tableName, Bytes.toBytes("f"));
210    ADMIN.setRSGroup(Sets.newHashSet(tableName), "bar");
211    RSGroupInfo barGroup = ADMIN.getRSGroup("bar");
212    // group is not empty therefore it should fail
213    try {
214      ADMIN.removeRSGroup(barGroup.getName());
215      fail("Expected remove group to fail");
216    } catch (IOException e) {
217    }
218    // group cannot lose all it's servers therefore it should fail
219    try {
220      ADMIN.moveServersToRSGroup(barGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);
221      fail("Expected move servers to fail");
222    } catch (IOException e) {
223    }
224
225    ADMIN.setRSGroup(Sets.newHashSet(ADMIN.listTablesInRSGroup("bar")), RSGroupInfo.DEFAULT_GROUP);
226    try {
227      ADMIN.removeRSGroup(barGroup.getName());
228      fail("Expected move servers to fail");
229    } catch (IOException e) {
230    }
231
232    ADMIN.moveServersToRSGroup(barGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);
233    ADMIN.removeRSGroup(barGroup.getName());
234
235    assertEquals(initNumGroups, ADMIN.listRSGroups().size());
236  }
237
238  @Test
239  public void testMultiTableMove() throws Exception {
240    final TableName tableNameA =
241      TableName.valueOf(TABLE_PREFIX + getNameWithoutIndex(name.getMethodName()) + "A");
242    final TableName tableNameB =
243      TableName.valueOf(TABLE_PREFIX + getNameWithoutIndex(name.getMethodName()) + "B");
244    final byte[] familyNameBytes = Bytes.toBytes("f");
245    String newGroupName = getGroupName(getNameWithoutIndex(name.getMethodName()));
246    final RSGroupInfo newGroup = addGroup(newGroupName, 1);
247
248    TEST_UTIL.createTable(tableNameA, familyNameBytes);
249    TEST_UTIL.createTable(tableNameB, familyNameBytes);
250    TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
251      @Override
252      public boolean evaluate() throws Exception {
253        List<String> regionsA = getTableRegionMap().get(tableNameA);
254        if (regionsA == null) {
255          return false;
256        }
257        List<String> regionsB = getTableRegionMap().get(tableNameB);
258        if (regionsB == null) {
259          return false;
260        }
261        return getTableRegionMap().get(tableNameA).size() >= 1
262          && getTableRegionMap().get(tableNameB).size() >= 1;
263      }
264    });
265
266    RSGroupInfo tableGrpA = ADMIN.getRSGroup(tableNameA);
267    assertTrue(tableGrpA.getName().equals(RSGroupInfo.DEFAULT_GROUP));
268
269    RSGroupInfo tableGrpB = ADMIN.getRSGroup(tableNameB);
270    assertTrue(tableGrpB.getName().equals(RSGroupInfo.DEFAULT_GROUP));
271    // change table's group
272    LOG.info("Moving table [" + tableNameA + "," + tableNameB + "] to " + newGroup.getName());
273    ADMIN.setRSGroup(Sets.newHashSet(tableNameA, tableNameB), newGroup.getName());
274
275    // verify group change
276    assertEquals(newGroup.getName(), ADMIN.getRSGroup(tableNameA).getName());
277
278    assertEquals(newGroup.getName(), ADMIN.getRSGroup(tableNameB).getName());
279
280    // verify tables' not exist in old group
281    Set<TableName> defaultTables =
282      Sets.newHashSet(ADMIN.listTablesInRSGroup(RSGroupInfo.DEFAULT_GROUP));
283    assertFalse(defaultTables.contains(tableNameA));
284    assertFalse(defaultTables.contains(tableNameB));
285
286    // verify tables' exist in new group
287    Set<TableName> newGroupTables = Sets.newHashSet(ADMIN.listTablesInRSGroup(newGroupName));
288    assertTrue(newGroupTables.contains(tableNameA));
289    assertTrue(newGroupTables.contains(tableNameB));
290  }
291
292  @Test
293  public void testTableMoveTruncateAndDrop() throws Exception {
294    final byte[] familyNameBytes = Bytes.toBytes("f");
295    String newGroupName = getGroupName(getNameWithoutIndex(name.getMethodName()));
296    final RSGroupInfo newGroup = addGroup(newGroupName, 2);
297
298    TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 5);
299    TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
300      @Override
301      public boolean evaluate() throws Exception {
302        List<String> regions = getTableRegionMap().get(tableName);
303        if (regions == null) {
304          return false;
305        }
306
307        return getTableRegionMap().get(tableName).size() >= 5;
308      }
309    });
310
311    RSGroupInfo tableGrp = ADMIN.getRSGroup(tableName);
312    LOG.info("got table group info is {}", tableGrp);
313    assertTrue(tableGrp.getName().equals(RSGroupInfo.DEFAULT_GROUP));
314
315    // change table's group
316    LOG.info("Moving table " + tableName + " to " + newGroup.getName());
317    ADMIN.setRSGroup(Sets.newHashSet(tableName), newGroup.getName());
318
319    // verify group change
320    assertEquals(newGroup.getName(), ADMIN.getRSGroup(tableName).getName());
321
322    TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
323      @Override
324      public boolean evaluate() throws Exception {
325        Map<ServerName, List<String>> serverMap = getTableServerRegionMap().get(tableName);
326        int count = 0;
327        if (serverMap != null) {
328          for (ServerName rs : serverMap.keySet()) {
329            if (newGroup.containsServer(rs.getAddress())) {
330              count += serverMap.get(rs).size();
331            }
332          }
333        }
334        return count == 5;
335      }
336    });
337
338    // test truncate
339    ADMIN.disableTable(tableName);
340    ADMIN.truncateTable(tableName, true);
341    List<TableName> tablesInGroup = ADMIN.listTablesInRSGroup(newGroup.getName());
342    assertEquals(1, tablesInGroup.size());
343    assertEquals(tableName, tablesInGroup.get(0));
344
345    // verify removed table is removed from group
346    TEST_UTIL.deleteTable(tableName);
347    assertEquals(0, ADMIN.listTablesInRSGroup(newGroup.getName()).size());
348  }
349
350  @Test
351  public void testDisabledTableMove() throws Exception {
352    final byte[] familyNameBytes = Bytes.toBytes("f");
353    String newGroupName = getGroupName(getNameWithoutIndex(name.getMethodName()));
354    final RSGroupInfo newGroup = addGroup(newGroupName, 2);
355
356    TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 5);
357    TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
358      @Override
359      public boolean evaluate() throws Exception {
360        List<String> regions = getTableRegionMap().get(tableName);
361        if (regions == null) {
362          return false;
363        }
364        return getTableRegionMap().get(tableName).size() >= 5;
365      }
366    });
367
368    RSGroupInfo tableGrp = ADMIN.getRSGroup(tableName);
369    assertTrue(tableGrp.getName().equals(RSGroupInfo.DEFAULT_GROUP));
370
371    // test disable table
372    ADMIN.disableTable(tableName);
373
374    // change table's group
375    LOG.info("Moving table " + tableName + " to " + newGroup.getName());
376    ADMIN.setRSGroup(Sets.newHashSet(tableName), newGroup.getName());
377
378    // verify group change
379    assertEquals(newGroup.getName(), ADMIN.getRSGroup(tableName).getName());
380  }
381
382  @Test
383  public void testNonExistentTableMove() throws Exception {
384    TableName tableName =
385      TableName.valueOf(TABLE_PREFIX + getNameWithoutIndex(name.getMethodName()));
386    RSGroupInfo tableGrp = ADMIN.getRSGroup(tableName);
387    assertNull(tableGrp);
388
389    // test if table exists already.
390    boolean exist = ADMIN.tableExists(tableName);
391    assertFalse(exist);
392
393    LOG.info("Moving table " + tableName + " to " + RSGroupInfo.DEFAULT_GROUP);
394    try {
395      ADMIN.setRSGroup(Sets.newHashSet(tableName), RSGroupInfo.DEFAULT_GROUP);
396      fail("Table " + tableName + " shouldn't have been successfully moved.");
397    } catch (IOException ex) {
398      assertTrue(ex instanceof TableNotFoundException);
399    }
400
401    try {
402      ADMIN.setRSGroup(Sets.newHashSet(tableName), RSGroupInfo.DEFAULT_GROUP);
403      ADMIN.moveServersToRSGroup(Sets.newHashSet(Address.fromParts("bogus", 123)),
404        RSGroupInfo.DEFAULT_GROUP);
405      fail("Table " + tableName + " shouldn't have been successfully moved.");
406    } catch (IOException ex) {
407      assertTrue(ex instanceof TableNotFoundException);
408    }
409    // verify group change
410    assertNull(ADMIN.getRSGroup(tableName));
411  }
412
413  @Test
414  public void testRSGroupListDoesNotContainFailedTableCreation() throws Exception {
415    toggleQuotaCheckAndRestartMiniCluster(true);
416    String nsp = "np1";
417    NamespaceDescriptor nspDesc =
418      NamespaceDescriptor.create(nsp).addConfiguration(TableNamespaceManager.KEY_MAX_REGIONS, "5")
419        .addConfiguration(TableNamespaceManager.KEY_MAX_TABLES, "2").build();
420    ADMIN.createNamespace(nspDesc);
421    assertEquals(3, ADMIN.listNamespaceDescriptors().length);
422    ColumnFamilyDescriptor fam1 = ColumnFamilyDescriptorBuilder.of("fam1");
423    TableDescriptor tableDescOne = TableDescriptorBuilder
424      .newBuilder(TableName.valueOf(nsp + TableName.NAMESPACE_DELIM + "table1"))
425      .setColumnFamily(fam1).build();
426    ADMIN.createTable(tableDescOne);
427
428    TableDescriptor tableDescTwo = TableDescriptorBuilder
429      .newBuilder(TableName.valueOf(nsp + TableName.NAMESPACE_DELIM + "table2"))
430      .setColumnFamily(fam1).build();
431    boolean constraintViolated = false;
432
433    try {
434      ADMIN.createTable(tableDescTwo, Bytes.toBytes("AAA"), Bytes.toBytes("ZZZ"), 6);
435      fail("Creation table should fail because of quota violation.");
436    } catch (Exception exp) {
437      assertTrue(exp instanceof IOException);
438      constraintViolated = true;
439    } finally {
440      assertTrue("Constraint not violated for table " + tableDescTwo.getTableName(),
441        constraintViolated);
442    }
443    List<RSGroupInfo> rsGroupInfoList = ADMIN.listRSGroups();
444    boolean foundTable2 = false;
445    boolean foundTable1 = false;
446    for (int i = 0; i < rsGroupInfoList.size(); i++) {
447      Set<TableName> tables =
448        Sets.newHashSet(ADMIN.listTablesInRSGroup(rsGroupInfoList.get(i).getName()));
449      if (tables.contains(tableDescTwo.getTableName())) {
450        foundTable2 = true;
451      }
452      if (tables.contains(tableDescOne.getTableName())) {
453        foundTable1 = true;
454      }
455    }
456    assertFalse("Found table2 in rsgroup list.", foundTable2);
457    assertTrue("Did not find table1 in rsgroup list", foundTable1);
458
459    TEST_UTIL.deleteTable(tableDescOne.getTableName());
460    ADMIN.deleteNamespace(nspDesc.getName());
461    toggleQuotaCheckAndRestartMiniCluster(false);
462
463  }
464
465  @Test
466  public void testNotMoveTableToNullRSGroupWhenCreatingExistingTable() throws Exception {
467    // Trigger
468    TableName tn1 = TableName.valueOf("t1");
469    TEST_UTIL.createTable(tn1, "cf1");
470    try {
471      // Create an existing table to trigger HBASE-21866
472      TEST_UTIL.createTable(tn1, "cf1");
473    } catch (TableExistsException teex) {
474      // Ignore
475    }
476
477    // Wait then verify
478    // Could not verify until the rollback of CreateTableProcedure is done
479    // (that is, the coprocessor finishes its work),
480    // or the table is still in the "default" rsgroup even though HBASE-21866
481    // is not fixed.
482    TEST_UTIL.waitFor(5000, new Waiter.Predicate<Exception>() {
483      @Override
484      public boolean evaluate() throws Exception {
485        return MASTER.getMasterProcedureExecutor().getActiveExecutorCount() == 0;
486      }
487    });
488    Set<TableName> tables = Sets.newHashSet(ADMIN.listTablesInRSGroup(RSGroupInfo.DEFAULT_GROUP));
489    assertTrue("Table 't1' must be in 'default' rsgroup", tables.contains(tn1));
490
491    // Cleanup
492    TEST_UTIL.deleteTable(tn1);
493  }
494
495  @Test
496  public void testRenameRSGroup() throws Exception {
497    // Add rsgroup, and assign 2 servers and a table to it.
498    RSGroupInfo oldgroup = addGroup("oldgroup", 2);
499    TableName tb1 = TableName.valueOf("testRename");
500    TEST_UTIL.createTable(tb1, "tr");
501    ADMIN.setRSGroup(Sets.newHashSet(tb1), oldgroup.getName());
502    TEST_UTIL.waitFor(1000,
503      (Waiter.Predicate<Exception>) () -> ADMIN.getRSGroup(tb1).getServers().size() == 2);
504    oldgroup = ADMIN.getRSGroup(oldgroup.getName());
505    assertEquals(2, oldgroup.getServers().size());
506    assertEquals(oldgroup.getName(), ADMIN.getRSGroup(tb1).getName());
507
508    // Another rsgroup and table for verification
509    // that they are unchanged during we're renaming oldgroup.
510    RSGroupInfo normal = addGroup("normal", 1);
511    TableName tb2 = TableName.valueOf("unmovedTable");
512    TEST_UTIL.createTable(tb2, "ut");
513    ADMIN.setRSGroup(Sets.newHashSet(tb2), normal.getName());
514    TEST_UTIL.waitFor(1000,
515      (Waiter.Predicate<Exception>) () -> ADMIN.getRSGroup(tb2).getServers().size() == 1);
516    normal = ADMIN.getRSGroup(normal.getName());
517    assertEquals(1, normal.getServers().size());
518    assertEquals(normal.getName(), ADMIN.getRSGroup(tb2).getName());
519
520    // Rename rsgroup
521    ADMIN.renameRSGroup(oldgroup.getName(), "newgroup");
522    Set<Address> servers = oldgroup.getServers();
523    RSGroupInfo newgroup = ADMIN.getRSGroup("newgroup");
524    assertEquals(servers.size(), newgroup.getServers().size());
525    int match = 0;
526    for (Address addr : newgroup.getServers()) {
527      if (servers.contains(addr)) {
528        match++;
529      }
530    }
531    assertEquals(servers.size(), match);
532    assertEquals(newgroup.getName(), ADMIN.getRSGroup(tb1).getName());
533    assertEquals(normal.getName(), ADMIN.getRSGroup(tb2).getName());
534  }
535
536  @Test
537  public void testRenameRSGroupConstraints() throws Exception {
538    // Add RSGroup, and assign 2 servers and a table to it.
539    String oldGroupName = "oldGroup";
540    RSGroupInfo oldGroup = addGroup(oldGroupName, 2);
541    oldGroup = ADMIN.getRSGroup(oldGroup.getName());
542    assertNotNull(oldGroup);
543    assertEquals(2, oldGroup.getServers().size());
544
545    // Add another RSGroup
546    String anotherRSGroupName = "anotherRSGroup";
547    RSGroupInfo anotherGroup = addGroup(anotherRSGroupName, 1);
548    anotherGroup = ADMIN.getRSGroup(anotherGroup.getName());
549    assertNotNull(anotherGroup);
550    assertEquals(1, anotherGroup.getServers().size());
551
552    // Rename a non existing RSGroup
553    try {
554      ADMIN.renameRSGroup("nonExistingRSGroup", "newRSGroup1");
555      fail("ConstraintException was expected.");
556    } catch (ConstraintException e) {
557      assertTrue(e.getMessage().contains("does not exist"));
558    }
559
560    // Rename to existing group
561    try {
562      ADMIN.renameRSGroup(oldGroup.getName(), anotherRSGroupName);
563      fail("ConstraintException was expected.");
564    } catch (ConstraintException e) {
565      assertTrue(e.getMessage().contains("Group already exists"));
566    }
567
568    // Rename default RSGroup
569    try {
570      ADMIN.renameRSGroup(RSGroupInfo.DEFAULT_GROUP, "newRSGroup2");
571      fail("ConstraintException was expected.");
572    } catch (ConstraintException e) {
573      // Do nothing
574    }
575
576    // Rename to default RSGroup
577    try {
578      ADMIN.renameRSGroup(oldGroup.getName(), RSGroupInfo.DEFAULT_GROUP);
579      fail("ConstraintException was expected.");
580    } catch (ConstraintException e) {
581      assertTrue(e.getMessage().contains("Group already exists"));
582    }
583
584  }
585
586  @Test
587  public void testTableConstraint() throws Exception {
588    String prefix = name.getMethodName();
589    String ns = prefix + "_ns";
590    TableName tableName = TableName.valueOf(ns + ":" + "t");
591    String nsGroup = prefix + "_nsg";
592    String tableGroup = prefix + "_tg";
593    addGroup(nsGroup, 1);
594    addGroup(tableGroup, 1);
595    ADMIN.createNamespace(NamespaceDescriptor.create(ns).build());
596    TEST_UTIL.createTable(tableName, "C");
597    TEST_UTIL.waitTableAvailable(tableName);
598    assertEquals(ADMIN.getRSGroup(tableName).getName(), RSGroupInfo.DEFAULT_GROUP);
599    // set table's rsgroup
600    TableDescriptor td = TableDescriptorBuilder.newBuilder(ADMIN.getDescriptor(tableName))
601      .setRegionServerGroup(tableGroup).build();
602    ADMIN.modifyTable(td);
603    TEST_UTIL.waitUntilNoRegionsInTransition();
604    assertEquals(ADMIN.getRSGroup(tableName).getName(), tableGroup);
605    // set namespace's rsgroup
606    NamespaceDescriptor nd = NamespaceDescriptor.create(ADMIN.getNamespaceDescriptor(ns))
607      .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, nsGroup).build();
608    ADMIN.modifyNamespace(nd);
609    assertEquals(ADMIN.getRSGroup(tableName).getName(), tableGroup);
610    // clear table's rsgroup
611    td = TableDescriptorBuilder.newBuilder(ADMIN.getDescriptor(tableName))
612      .setRegionServerGroup(null).build();
613    ADMIN.modifyTable(td);
614    TEST_UTIL.waitUntilNoRegionsInTransition();
615    assertEquals(ADMIN.getRSGroup(tableName).getName(), nsGroup);
616
617    TEST_UTIL.deleteTable(tableName);
618    ADMIN.deleteNamespace(ns);
619  }
620}