HBASE-22676 Move all the code in hbase-rsgroup to hbase-server and remove hbase-rsgro...
[hbase.git] / hbase-server / src / test / java / org / apache / hadoop / hbase / rsgroup / TestRSGroupsAdmin1.java
blob27511e30794a3015de33e37223b40f9dd4338351
1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package org.apache.hadoop.hbase.rsgroup;
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertFalse;
22 import static org.junit.Assert.assertNull;
23 import static org.junit.Assert.assertTrue;
24 import static org.junit.Assert.fail;
26 import java.io.IOException;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Set;
31 import java.util.SortedSet;
33 import org.apache.hadoop.hbase.HBaseClassTestRule;
34 import org.apache.hadoop.hbase.MiniHBaseCluster;
35 import org.apache.hadoop.hbase.NamespaceDescriptor;
36 import org.apache.hadoop.hbase.ServerName;
37 import org.apache.hadoop.hbase.TableExistsException;
38 import org.apache.hadoop.hbase.TableName;
39 import org.apache.hadoop.hbase.TableNotFoundException;
40 import org.apache.hadoop.hbase.Waiter;
41 import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
42 import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
43 import org.apache.hadoop.hbase.client.TableDescriptor;
44 import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
45 import org.apache.hadoop.hbase.constraint.ConstraintException;
46 import org.apache.hadoop.hbase.master.ServerManager;
47 import org.apache.hadoop.hbase.master.TableNamespaceManager;
48 import org.apache.hadoop.hbase.master.snapshot.SnapshotManager;
49 import org.apache.hadoop.hbase.net.Address;
50 import org.apache.hadoop.hbase.quotas.QuotaUtil;
51 import org.apache.hadoop.hbase.testclassification.MediumTests;
52 import org.apache.hadoop.hbase.util.Bytes;
53 import org.junit.After;
54 import org.junit.AfterClass;
55 import org.junit.Assert;
56 import org.junit.Before;
57 import org.junit.BeforeClass;
58 import org.junit.ClassRule;
59 import org.junit.Test;
60 import org.junit.experimental.categories.Category;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
64 import org.apache.hbase.thirdparty.com.google.common.collect.Sets;
66 @Category({ MediumTests.class })
67 public class TestRSGroupsAdmin1 extends TestRSGroupsBase {
69 @ClassRule
70 public static final HBaseClassTestRule CLASS_RULE =
71 HBaseClassTestRule.forClass(TestRSGroupsAdmin1.class);
73 protected static final Logger LOG = LoggerFactory.getLogger(TestRSGroupsAdmin1.class);
75 @BeforeClass
76 public static void setUp() throws Exception {
77 setUpTestBeforeClass();
80 @AfterClass
81 public static void tearDown() throws Exception {
82 tearDownAfterClass();
85 @Before
86 public void beforeMethod() throws Exception {
87 setUpBeforeMethod();
90 @After
91 public void afterMethod() throws Exception {
92 tearDownAfterMethod();
95 @Test
96 public void testValidGroupNames() throws IOException {
97 String[] badNames = { "foo*", "foo@", "-" };
98 String[] goodNames = { "foo_123" };
100 for (String entry : badNames) {
101 try {
102 rsGroupAdmin.addRSGroup(entry);
103 fail("Expected a constraint exception for: " + entry);
104 } catch (ConstraintException ex) {
105 // expected
109 for (String entry : goodNames) {
110 rsGroupAdmin.addRSGroup(entry);
114 @Test
115 public void testBogusArgs() throws Exception {
116 assertNull(rsGroupAdmin.getRSGroupInfoOfTable(TableName.valueOf("nonexistent")));
117 assertNull(rsGroupAdmin.getRSGroupOfServer(Address.fromParts("bogus", 123)));
118 assertNull(rsGroupAdmin.getRSGroupInfo("bogus"));
120 try {
121 rsGroupAdmin.removeRSGroup("bogus");
122 fail("Expected removing bogus group to fail");
123 } catch (ConstraintException ex) {
124 // expected
127 try {
128 rsGroupAdmin.moveTables(Sets.newHashSet(TableName.valueOf("bogustable")), "bogus");
129 fail("Expected move with bogus group to fail");
130 } catch (ConstraintException | TableNotFoundException ex) {
131 // expected
134 try {
135 rsGroupAdmin.moveServers(Sets.newHashSet(Address.fromParts("bogus", 123)), "bogus");
136 fail("Expected move with bogus group to fail");
137 } catch (ConstraintException ex) {
138 // expected
141 try {
142 admin.balancerSwitch(true, true);
143 rsGroupAdmin.balanceRSGroup("bogus");
144 admin.balancerSwitch(false, true);
145 fail("Expected move with bogus group to fail");
146 } catch (ConstraintException ex) {
147 // expected
151 @Test
152 public void testNamespaceConstraint() throws Exception {
153 String nsName = tablePrefix + "_foo";
154 String groupName = tablePrefix + "_foo";
155 LOG.info("testNamespaceConstraint");
156 rsGroupAdmin.addRSGroup(groupName);
157 assertTrue(observer.preAddRSGroupCalled);
158 assertTrue(observer.postAddRSGroupCalled);
160 admin.createNamespace(NamespaceDescriptor.create(nsName)
161 .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, groupName).build());
162 // test removing a referenced group
163 try {
164 rsGroupAdmin.removeRSGroup(groupName);
165 fail("Expected a constraint exception");
166 } catch (IOException ex) {
168 // test modify group
169 // changing with the same name is fine
170 admin.modifyNamespace(NamespaceDescriptor.create(nsName)
171 .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, groupName).build());
172 String anotherGroup = tablePrefix + "_anotherGroup";
173 rsGroupAdmin.addRSGroup(anotherGroup);
174 // test add non-existent group
175 admin.deleteNamespace(nsName);
176 rsGroupAdmin.removeRSGroup(groupName);
177 assertTrue(observer.preRemoveRSGroupCalled);
178 assertTrue(observer.postRemoveRSGroupCalled);
179 try {
180 admin.createNamespace(NamespaceDescriptor.create(nsName)
181 .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, "foo").build());
182 fail("Expected a constraint exception");
183 } catch (IOException ex) {
187 @Test
188 public void testGroupInfoMultiAccessing() throws Exception {
189 RSGroupInfoManager manager = rsGroupAdminEndpoint.getGroupInfoManager();
190 RSGroupInfo defaultGroup = manager.getRSGroup("default");
191 // getRSGroup updates default group's server list
192 // this process must not affect other threads iterating the list
193 Iterator<Address> it = defaultGroup.getServers().iterator();
194 manager.getRSGroup("default");
195 it.next();
198 @Test
199 public void testGetRSGroupInfoCPHookCalled() throws Exception {
200 rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP);
201 assertTrue(observer.preGetRSGroupInfoCalled);
202 assertTrue(observer.postGetRSGroupInfoCalled);
205 @Test
206 public void testGetRSGroupInfoOfTableCPHookCalled() throws Exception {
207 rsGroupAdmin.getRSGroupInfoOfTable(TableName.META_TABLE_NAME);
208 assertTrue(observer.preGetRSGroupInfoOfTableCalled);
209 assertTrue(observer.postGetRSGroupInfoOfTableCalled);
212 @Test
213 public void testListRSGroupsCPHookCalled() throws Exception {
214 rsGroupAdmin.listRSGroups();
215 assertTrue(observer.preListRSGroupsCalled);
216 assertTrue(observer.postListRSGroupsCalled);
219 @Test
220 public void testGetRSGroupInfoOfServerCPHookCalled() throws Exception {
221 ServerName masterServerName = ((MiniHBaseCluster) cluster).getMaster().getServerName();
222 rsGroupAdmin.getRSGroupOfServer(masterServerName.getAddress());
223 assertTrue(observer.preGetRSGroupInfoOfServerCalled);
224 assertTrue(observer.postGetRSGroupInfoOfServerCalled);
227 @Test
228 public void testFailRemoveGroup() throws IOException, InterruptedException {
229 int initNumGroups = rsGroupAdmin.listRSGroups().size();
230 addGroup("bar", 3);
231 TEST_UTIL.createTable(tableName, Bytes.toBytes("f"));
232 rsGroupAdmin.moveTables(Sets.newHashSet(tableName), "bar");
233 RSGroupInfo barGroup = rsGroupAdmin.getRSGroupInfo("bar");
234 // group is not empty therefore it should fail
235 try {
236 rsGroupAdmin.removeRSGroup(barGroup.getName());
237 fail("Expected remove group to fail");
238 } catch (IOException e) {
240 // group cannot lose all it's servers therefore it should fail
241 try {
242 rsGroupAdmin.moveServers(barGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);
243 fail("Expected move servers to fail");
244 } catch (IOException e) {
247 rsGroupAdmin.moveTables(barGroup.getTables(), RSGroupInfo.DEFAULT_GROUP);
248 try {
249 rsGroupAdmin.removeRSGroup(barGroup.getName());
250 fail("Expected move servers to fail");
251 } catch (IOException e) {
254 rsGroupAdmin.moveServers(barGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);
255 rsGroupAdmin.removeRSGroup(barGroup.getName());
257 Assert.assertEquals(initNumGroups, rsGroupAdmin.listRSGroups().size());
260 @Test
261 public void testMultiTableMove() throws Exception {
262 final TableName tableNameA = TableName.valueOf(tablePrefix + name.getMethodName() + "A");
263 final TableName tableNameB = TableName.valueOf(tablePrefix + name.getMethodName() + "B");
264 final byte[] familyNameBytes = Bytes.toBytes("f");
265 String newGroupName = getGroupName(name.getMethodName());
266 final RSGroupInfo newGroup = addGroup(newGroupName, 1);
268 TEST_UTIL.createTable(tableNameA, familyNameBytes);
269 TEST_UTIL.createTable(tableNameB, familyNameBytes);
270 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
271 @Override
272 public boolean evaluate() throws Exception {
273 List<String> regionsA = getTableRegionMap().get(tableNameA);
274 if (regionsA == null) {
275 return false;
277 List<String> regionsB = getTableRegionMap().get(tableNameB);
278 if (regionsB == null) {
279 return false;
281 return getTableRegionMap().get(tableNameA).size() >= 1 &&
282 getTableRegionMap().get(tableNameB).size() >= 1;
286 RSGroupInfo tableGrpA = rsGroupAdmin.getRSGroupInfoOfTable(tableNameA);
287 assertTrue(tableGrpA.getName().equals(RSGroupInfo.DEFAULT_GROUP));
289 RSGroupInfo tableGrpB = rsGroupAdmin.getRSGroupInfoOfTable(tableNameB);
290 assertTrue(tableGrpB.getName().equals(RSGroupInfo.DEFAULT_GROUP));
291 // change table's group
292 LOG.info("Moving table [" + tableNameA + "," + tableNameB + "] to " + newGroup.getName());
293 rsGroupAdmin.moveTables(Sets.newHashSet(tableNameA, tableNameB), newGroup.getName());
295 // verify group change
296 Assert.assertEquals(newGroup.getName(),
297 rsGroupAdmin.getRSGroupInfoOfTable(tableNameA).getName());
299 Assert.assertEquals(newGroup.getName(),
300 rsGroupAdmin.getRSGroupInfoOfTable(tableNameB).getName());
302 // verify tables' not exist in old group
303 Set<TableName> DefaultTables =
304 rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getTables();
305 assertFalse(DefaultTables.contains(tableNameA));
306 assertFalse(DefaultTables.contains(tableNameB));
308 // verify tables' exist in new group
309 Set<TableName> newGroupTables = rsGroupAdmin.getRSGroupInfo(newGroupName).getTables();
310 assertTrue(newGroupTables.contains(tableNameA));
311 assertTrue(newGroupTables.contains(tableNameB));
314 @Test
315 public void testTableMoveTruncateAndDrop() throws Exception {
316 final byte[] familyNameBytes = Bytes.toBytes("f");
317 String newGroupName = getGroupName(name.getMethodName());
318 final RSGroupInfo newGroup = addGroup(newGroupName, 2);
320 TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 5);
321 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
322 @Override
323 public boolean evaluate() throws Exception {
324 List<String> regions = getTableRegionMap().get(tableName);
325 if (regions == null) {
326 return false;
329 return getTableRegionMap().get(tableName).size() >= 5;
333 RSGroupInfo tableGrp = rsGroupAdmin.getRSGroupInfoOfTable(tableName);
334 assertTrue(tableGrp.getName().equals(RSGroupInfo.DEFAULT_GROUP));
336 // change table's group
337 LOG.info("Moving table " + tableName + " to " + newGroup.getName());
338 rsGroupAdmin.moveTables(Sets.newHashSet(tableName), newGroup.getName());
340 // verify group change
341 Assert.assertEquals(newGroup.getName(),
342 rsGroupAdmin.getRSGroupInfoOfTable(tableName).getName());
344 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
345 @Override
346 public boolean evaluate() throws Exception {
347 Map<ServerName, List<String>> serverMap = getTableServerRegionMap().get(tableName);
348 int count = 0;
349 if (serverMap != null) {
350 for (ServerName rs : serverMap.keySet()) {
351 if (newGroup.containsServer(rs.getAddress())) {
352 count += serverMap.get(rs).size();
356 return count == 5;
360 // test truncate
361 admin.disableTable(tableName);
362 admin.truncateTable(tableName, true);
363 Assert.assertEquals(1, rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getTables().size());
364 Assert.assertEquals(tableName,
365 rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getTables().first());
367 // verify removed table is removed from group
368 TEST_UTIL.deleteTable(tableName);
369 Assert.assertEquals(0, rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getTables().size());
371 assertTrue(observer.preMoveTablesCalled);
372 assertTrue(observer.postMoveTablesCalled);
375 @Test
376 public void testDisabledTableMove() throws Exception {
377 final byte[] familyNameBytes = Bytes.toBytes("f");
378 String newGroupName = getGroupName(name.getMethodName());
379 final RSGroupInfo newGroup = addGroup(newGroupName, 2);
381 TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 5);
382 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
383 @Override
384 public boolean evaluate() throws Exception {
385 List<String> regions = getTableRegionMap().get(tableName);
386 if (regions == null) {
387 return false;
389 return getTableRegionMap().get(tableName).size() >= 5;
393 RSGroupInfo tableGrp = rsGroupAdmin.getRSGroupInfoOfTable(tableName);
394 assertTrue(tableGrp.getName().equals(RSGroupInfo.DEFAULT_GROUP));
396 // test disable table
397 admin.disableTable(tableName);
399 // change table's group
400 LOG.info("Moving table " + tableName + " to " + newGroup.getName());
401 rsGroupAdmin.moveTables(Sets.newHashSet(tableName), newGroup.getName());
403 // verify group change
404 Assert.assertEquals(newGroup.getName(),
405 rsGroupAdmin.getRSGroupInfoOfTable(tableName).getName());
408 @Test
409 public void testNonExistentTableMove() throws Exception {
410 TableName tableName = TableName.valueOf(tablePrefix + name.getMethodName());
412 RSGroupInfo tableGrp = rsGroupAdmin.getRSGroupInfoOfTable(tableName);
413 assertNull(tableGrp);
415 // test if table exists already.
416 boolean exist = admin.tableExists(tableName);
417 assertFalse(exist);
419 LOG.info("Moving table " + tableName + " to " + RSGroupInfo.DEFAULT_GROUP);
420 try {
421 rsGroupAdmin.moveTables(Sets.newHashSet(tableName), RSGroupInfo.DEFAULT_GROUP);
422 fail("Table " + tableName + " shouldn't have been successfully moved.");
423 } catch (IOException ex) {
424 assertTrue(ex instanceof TableNotFoundException);
427 try {
428 rsGroupAdmin.moveServersAndTables(Sets.newHashSet(Address.fromParts("bogus", 123)),
429 Sets.newHashSet(tableName), RSGroupInfo.DEFAULT_GROUP);
430 fail("Table " + tableName + " shouldn't have been successfully moved.");
431 } catch (IOException ex) {
432 assertTrue(ex instanceof TableNotFoundException);
434 // verify group change
435 assertNull(rsGroupAdmin.getRSGroupInfoOfTable(tableName));
438 @Test
439 public void testRSGroupListDoesNotContainFailedTableCreation() throws Exception {
440 toggleQuotaCheckAndRestartMiniCluster(true);
441 String nsp = "np1";
442 NamespaceDescriptor nspDesc =
443 NamespaceDescriptor.create(nsp).addConfiguration(TableNamespaceManager.KEY_MAX_REGIONS, "5")
444 .addConfiguration(TableNamespaceManager.KEY_MAX_TABLES, "2").build();
445 admin.createNamespace(nspDesc);
446 assertEquals(3, admin.listNamespaceDescriptors().length);
447 ColumnFamilyDescriptor fam1 = ColumnFamilyDescriptorBuilder.of("fam1");
448 TableDescriptor tableDescOne = TableDescriptorBuilder
449 .newBuilder(TableName.valueOf(nsp + TableName.NAMESPACE_DELIM + "table1"))
450 .setColumnFamily(fam1).build();
451 admin.createTable(tableDescOne);
453 TableDescriptor tableDescTwo = TableDescriptorBuilder
454 .newBuilder(TableName.valueOf(nsp + TableName.NAMESPACE_DELIM + "table2"))
455 .setColumnFamily(fam1).build();
456 boolean constraintViolated = false;
458 try {
459 admin.createTable(tableDescTwo, Bytes.toBytes("AAA"), Bytes.toBytes("ZZZ"), 6);
460 Assert.fail("Creation table should fail because of quota violation.");
461 } catch (Exception exp) {
462 assertTrue(exp instanceof IOException);
463 constraintViolated = true;
464 } finally {
465 assertTrue("Constraint not violated for table " + tableDescTwo.getTableName(),
466 constraintViolated);
468 List<RSGroupInfo> rsGroupInfoList = rsGroupAdmin.listRSGroups();
469 boolean foundTable2 = false;
470 boolean foundTable1 = false;
471 for (int i = 0; i < rsGroupInfoList.size(); i++) {
472 if (rsGroupInfoList.get(i).getTables().contains(tableDescTwo.getTableName())) {
473 foundTable2 = true;
475 if (rsGroupInfoList.get(i).getTables().contains(tableDescOne.getTableName())) {
476 foundTable1 = true;
479 assertFalse("Found table2 in rsgroup list.", foundTable2);
480 assertTrue("Did not find table1 in rsgroup list", foundTable1);
482 TEST_UTIL.deleteTable(tableDescOne.getTableName());
483 admin.deleteNamespace(nspDesc.getName());
484 toggleQuotaCheckAndRestartMiniCluster(false);
488 @Test
489 public void testNotMoveTableToNullRSGroupWhenCreatingExistingTable()
490 throws Exception {
491 // Trigger
492 TableName tn1 = TableName.valueOf("t1");
493 TEST_UTIL.createTable(tn1, "cf1");
494 try {
495 // Create an existing table to trigger HBASE-21866
496 TEST_UTIL.createTable(tn1, "cf1");
497 } catch (TableExistsException teex) {
498 // Ignore
501 // Wait then verify
502 // Could not verify until the rollback of CreateTableProcedure is done
503 // (that is, the coprocessor finishes its work),
504 // or the table is still in the "default" rsgroup even though HBASE-21866
505 // is not fixed.
506 TEST_UTIL.waitFor(5000, new Waiter.Predicate<Exception>() {
507 @Override
508 public boolean evaluate() throws Exception {
509 return
510 (master.getMasterProcedureExecutor().getActiveExecutorCount() == 0);
513 SortedSet<TableName> tables
514 = rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getTables();
515 assertTrue("Table 't1' must be in 'default' rsgroup", tables.contains(tn1));
517 // Cleanup
518 TEST_UTIL.deleteTable(tn1);
521 private void toggleQuotaCheckAndRestartMiniCluster(boolean enable) throws Exception {
522 TEST_UTIL.shutdownMiniCluster();
523 TEST_UTIL.getConfiguration().setBoolean(QuotaUtil.QUOTA_CONF_KEY, enable);
524 TEST_UTIL.startMiniCluster(NUM_SLAVES_BASE - 1);
525 TEST_UTIL.getConfiguration().setInt(ServerManager.WAIT_ON_REGIONSERVERS_MINTOSTART,
526 NUM_SLAVES_BASE - 1);
527 TEST_UTIL.getConfiguration().setBoolean(SnapshotManager.HBASE_SNAPSHOT_ENABLED, true);
528 initialize();