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.assertTrue; 021 022import java.io.IOException; 023import java.util.Collections; 024import org.apache.hadoop.conf.Configuration; 025import org.apache.hadoop.hbase.HBaseClassTestRule; 026import org.apache.hadoop.hbase.HConstants; 027import org.apache.hadoop.hbase.TableName; 028import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 029import org.apache.hadoop.hbase.client.TableDescriptor; 030import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 031import org.apache.hadoop.hbase.master.assignment.AssignmentTestingUtil; 032import org.apache.hadoop.hbase.net.Address; 033import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility; 034import org.apache.hadoop.hbase.testclassification.MediumTests; 035import org.apache.hadoop.hbase.util.Bytes; 036import org.apache.hadoop.hbase.util.JVMClusterUtil; 037import org.junit.After; 038import org.junit.AfterClass; 039import org.junit.Before; 040import org.junit.BeforeClass; 041import org.junit.ClassRule; 042import org.junit.Test; 043import org.junit.experimental.categories.Category; 044import org.slf4j.Logger; 045import org.slf4j.LoggerFactory; 046 047@Category(MediumTests.class) 048public class TestRSGroupsFallback extends TestRSGroupsBase { 049 050 @ClassRule 051 public static final HBaseClassTestRule CLASS_RULE = 052 HBaseClassTestRule.forClass(TestRSGroupsFallback.class); 053 054 protected static final Logger LOG = LoggerFactory.getLogger(TestRSGroupsFallback.class); 055 056 private static final String FALLBACK_GROUP = "fallback"; 057 058 @BeforeClass 059 public static void setUp() throws Exception { 060 Configuration conf = TEST_UTIL.getConfiguration(); 061 conf.setBoolean(RSGroupBasedLoadBalancer.FALLBACK_GROUP_ENABLE_KEY, true); 062 conf.setInt(HConstants.HBASE_BALANCER_MAX_BALANCING, 0); 063 setUpTestBeforeClass(); 064 master.balanceSwitch(true); 065 } 066 067 @AfterClass 068 public static void tearDown() throws Exception { 069 tearDownAfterClass(); 070 } 071 072 @Before 073 public void beforeMethod() throws Exception { 074 setUpBeforeMethod(); 075 } 076 077 @After 078 public void afterMethod() throws Exception { 079 tearDownAfterMethod(); 080 } 081 082 @Test 083 public void testFallback() throws Exception { 084 // add fallback group 085 addGroup(FALLBACK_GROUP, 1); 086 // add test group 087 String groupName = getGroupName(name.getMethodName()); 088 addGroup(groupName, 1); 089 TableDescriptor desc = TableDescriptorBuilder.newBuilder(tableName) 090 .setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("f")).build()) 091 .build(); 092 admin.createTable(desc); 093 rsGroupAdmin.moveTables(Collections.singleton(tableName), groupName); 094 TEST_UTIL.waitUntilAllRegionsAssigned(tableName); 095 // server of test group crash, regions move to default group 096 crashRsInGroup(groupName); 097 assertRegionsInGroup(tableName, RSGroupInfo.DEFAULT_GROUP); 098 099 // server of default group crash, regions move to any other group 100 crashRsInGroup(RSGroupInfo.DEFAULT_GROUP); 101 assertRegionsInGroup(tableName, FALLBACK_GROUP); 102 103 // add a new server to default group, regions move to default group 104 JVMClusterUtil.RegionServerThread t = 105 TEST_UTIL.getMiniHBaseCluster().startRegionServerAndWait(60000); 106 Address startRSAddress = t.getRegionServer().getServerName().getAddress(); 107 TEST_UTIL.waitFor(3000, 108 () -> rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).containsServer(startRSAddress)); 109 assertTrue(master.balance().isBalancerRan()); 110 assertRegionsInGroup(tableName, RSGroupInfo.DEFAULT_GROUP); 111 112 // add a new server to test group, regions move back 113 t = TEST_UTIL.getMiniHBaseCluster().startRegionServerAndWait(60000); 114 rsGroupAdmin.moveServers( 115 Collections.singleton(t.getRegionServer().getServerName().getAddress()), groupName); 116 assertTrue(master.balance().isBalancerRan()); 117 assertRegionsInGroup(tableName, groupName); 118 119 TEST_UTIL.deleteTable(tableName); 120 } 121 122 private void assertRegionsInGroup(TableName tableName, String group) throws IOException { 123 ProcedureTestingUtility 124 .waitAllProcedures(TEST_UTIL.getMiniHBaseCluster().getMaster().getMasterProcedureExecutor()); 125 RSGroupInfo groupInfo = rsGroupAdmin.getRSGroupInfo(group); 126 master.getAssignmentManager().getRegionStates().getRegionsOfTable(tableName).forEach(region -> { 127 Address regionOnServer = master.getAssignmentManager().getRegionStates() 128 .getRegionAssignments().get(region).getAddress(); 129 assertTrue(groupInfo.getServers().contains(regionOnServer)); 130 }); 131 } 132 133 private void crashRsInGroup(String groupName) throws Exception { 134 for (Address server : rsGroupAdmin.getRSGroupInfo(groupName).getServers()) { 135 AssignmentTestingUtil.crashRs(TEST_UTIL, getServerName(server), true); 136 } 137 TEST_UTIL.waitFor(30000, () -> !master.getServerManager().areDeadServersInProgress()); 138 TEST_UTIL.waitUntilNoRegionsInTransition(60000); 139 } 140}