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.jupiter.api.Assertions.assertEquals; 021import static org.junit.jupiter.api.Assertions.assertFalse; 022import static org.junit.jupiter.api.Assertions.assertTrue; 023 024import java.io.IOException; 025import java.util.List; 026import java.util.Set; 027import org.apache.hadoop.hbase.NamespaceDescriptor; 028import org.apache.hadoop.hbase.ServerName; 029import org.apache.hadoop.hbase.TableName; 030import org.apache.hadoop.hbase.Waiter; 031import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 032import org.apache.hadoop.hbase.client.TableDescriptor; 033import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 034import org.apache.hadoop.hbase.net.Address; 035import org.apache.hadoop.hbase.quotas.QuotaTableUtil; 036import org.apache.hadoop.hbase.testclassification.MediumTests; 037import org.apache.hadoop.hbase.testclassification.RSGroupTests; 038import org.apache.hadoop.hbase.util.Bytes; 039import org.junit.jupiter.api.AfterAll; 040import org.junit.jupiter.api.AfterEach; 041import org.junit.jupiter.api.BeforeAll; 042import org.junit.jupiter.api.BeforeEach; 043import org.junit.jupiter.api.Tag; 044import org.junit.jupiter.api.Test; 045import org.junit.jupiter.api.TestInfo; 046import org.slf4j.Logger; 047import org.slf4j.LoggerFactory; 048 049import org.apache.hbase.thirdparty.com.google.common.collect.Lists; 050 051@Tag(RSGroupTests.TAG) 052@Tag(MediumTests.TAG) 053public class TestRSGroupsBasics extends TestRSGroupsBase { 054 055 protected static final Logger LOG = LoggerFactory.getLogger(TestRSGroupsBasics.class); 056 057 @BeforeAll 058 public static void setUp() throws Exception { 059 setUpTestBeforeClass(); 060 } 061 062 @AfterAll 063 public static void tearDown() throws Exception { 064 tearDownAfterClass(); 065 } 066 067 @BeforeEach 068 public void beforeMethod(TestInfo testInfo) throws Exception { 069 setUpBeforeMethod(testInfo); 070 } 071 072 @AfterEach 073 public void afterMethod() throws Exception { 074 tearDownAfterMethod(); 075 } 076 077 @Test 078 public void testBasicStartUp() throws IOException { 079 RSGroupInfo defaultInfo = ADMIN.getRSGroup(RSGroupInfo.DEFAULT_GROUP); 080 assertEquals(NUM_SLAVES_BASE, defaultInfo.getServers().size()); 081 // Assignment of meta and rsgroup regions. 082 int count = MASTER.getAssignmentManager().getRegionStates().getRegionAssignments().size(); 083 LOG.info("regions assignments are" 084 + MASTER.getAssignmentManager().getRegionStates().getRegionAssignments().toString()); 085 // 2 (meta and rsgroup) 086 assertEquals(2, count); 087 } 088 089 @Test 090 public void testCreateAndDrop() throws Exception { 091 TEST_UTIL.createTable(tableName, Bytes.toBytes("cf")); 092 // wait for created table to be assigned 093 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() { 094 @Override 095 public boolean evaluate() throws Exception { 096 return getTableRegionMap().get(tableName) != null; 097 } 098 }); 099 TEST_UTIL.deleteTable(tableName); 100 } 101 102 @Test 103 public void testCreateMultiRegion() throws IOException { 104 byte[] end = { 1, 3, 5, 7, 9 }; 105 byte[] start = { 0, 2, 4, 6, 8 }; 106 byte[][] f = { Bytes.toBytes("f") }; 107 TEST_UTIL.createTable(tableName, f, 1, start, end, 10); 108 } 109 110 @Test 111 public void testNamespaceCreateAndAssign() throws Exception { 112 LOG.info("testNamespaceCreateAndAssign"); 113 String nsName = TABLE_PREFIX + "_foo"; 114 final TableName tableName = TableName.valueOf(nsName, TABLE_PREFIX + "_testCreateAndAssign"); 115 RSGroupInfo appInfo = addGroup("appInfo", 1); 116 ADMIN.createNamespace(NamespaceDescriptor.create(nsName) 117 .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, "appInfo").build()); 118 final TableDescriptor desc = TableDescriptorBuilder.newBuilder(tableName) 119 .setColumnFamily(ColumnFamilyDescriptorBuilder.of("f")).build(); 120 ADMIN.createTable(desc); 121 // wait for created table to be assigned 122 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() { 123 @Override 124 public boolean evaluate() throws Exception { 125 return getTableRegionMap().get(desc.getTableName()) != null; 126 } 127 }); 128 ServerName targetServer = getServerName(appInfo.getServers().iterator().next()); 129 // verify it was assigned to the right group 130 assertEquals(1, ADMIN.getRegions(targetServer).size()); 131 } 132 133 @Test 134 public void testDefaultNamespaceCreateAndAssign() throws Exception { 135 LOG.info("testDefaultNamespaceCreateAndAssign"); 136 String tableName = TABLE_PREFIX + "_testCreateAndAssign"; 137 ADMIN.modifyNamespace(NamespaceDescriptor.create("default") 138 .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, "default").build()); 139 final TableDescriptor desc = TableDescriptorBuilder.newBuilder(TableName.valueOf(tableName)) 140 .setColumnFamily(ColumnFamilyDescriptorBuilder.of("f")).build(); 141 ADMIN.createTable(desc); 142 // wait for created table to be assigned 143 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() { 144 @Override 145 public boolean evaluate() throws Exception { 146 return getTableRegionMap().get(desc.getTableName()) != null; 147 } 148 }); 149 } 150 151 @Test 152 public void testCloneSnapshot() throws Exception { 153 byte[] FAMILY = Bytes.toBytes("test"); 154 String snapshotName = tableName.getNameAsString() + "_snap"; 155 TableName clonedTableName = TableName.valueOf(tableName.getNameAsString() + "_clone"); 156 157 // create base table 158 TEST_UTIL.createTable(tableName, FAMILY); 159 160 // create snapshot 161 ADMIN.snapshot(snapshotName, tableName); 162 163 // clone 164 ADMIN.cloneSnapshot(snapshotName, clonedTableName); 165 ADMIN.deleteSnapshot(snapshotName); 166 } 167 168 @Test 169 public void testClearDeadServers() throws Exception { 170 LOG.info("testClearDeadServers"); 171 172 // move region servers from default group to new group 173 final int serverCountToMoveToNewGroup = 3; 174 final RSGroupInfo newGroup = 175 addGroup(getGroupName(name.getMethodName()), serverCountToMoveToNewGroup); 176 177 // get the existing dead servers 178 NUM_DEAD_SERVERS = CLUSTER.getClusterMetrics().getDeadServerNames().size(); 179 180 // stop 1 region server in new group 181 ServerName serverToStop = getServerName(newGroup.getServers().iterator().next()); 182 try { 183 // stopping may cause an exception 184 // due to the connection loss 185 ADMIN.stopRegionServer(serverToStop.getAddress().toString()); 186 NUM_DEAD_SERVERS++; 187 } catch (Exception e) { 188 } 189 190 // wait for stopped regionserver to dead server list 191 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() { 192 @Override 193 public boolean evaluate() throws Exception { 194 return CLUSTER.getClusterMetrics().getDeadServerNames().size() == NUM_DEAD_SERVERS 195 && !MASTER.getServerManager().areDeadServersInProgress(); 196 } 197 }); 198 assertFalse(CLUSTER.getClusterMetrics().getLiveServerMetrics().containsKey(serverToStop)); 199 assertTrue(CLUSTER.getClusterMetrics().getDeadServerNames().contains(serverToStop)); 200 assertTrue(newGroup.getServers().contains(serverToStop.getAddress())); 201 202 // clear dead servers list 203 List<ServerName> notClearedServers = ADMIN.clearDeadServers(Lists.newArrayList(serverToStop)); 204 assertEquals(0, notClearedServers.size()); 205 206 // the stopped region server gets cleared and removed from the group 207 Set<Address> newGroupServers = ADMIN.getRSGroup(newGroup.getName()).getServers(); 208 assertFalse(newGroupServers.contains(serverToStop.getAddress())); 209 assertEquals(serverCountToMoveToNewGroup - 1 /* 1 stopped */, newGroupServers.size()); 210 } 211 212 @Test 213 public void testClearNotProcessedDeadServer() throws Exception { 214 LOG.info("testClearNotProcessedDeadServer"); 215 216 // get the existing dead servers 217 NUM_DEAD_SERVERS = CLUSTER.getClusterMetrics().getDeadServerNames().size(); 218 219 // move region servers from default group to "dead server" group 220 final int serverCountToMoveToDeadServerGroup = 1; 221 RSGroupInfo deadServerGroup = addGroup("deadServerGroup", serverCountToMoveToDeadServerGroup); 222 223 // stop 1 region servers in "dead server" group 224 ServerName serverToStop = getServerName(deadServerGroup.getServers().iterator().next()); 225 try { 226 // stopping may cause an exception 227 // due to the connection loss 228 ADMIN.stopRegionServer(serverToStop.getAddress().toString()); 229 NUM_DEAD_SERVERS++; 230 } catch (Exception e) { 231 } 232 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() { 233 @Override 234 public boolean evaluate() throws Exception { 235 return CLUSTER.getClusterMetrics().getDeadServerNames().size() == NUM_DEAD_SERVERS; 236 } 237 }); 238 239 Set<Address> ServersInDeadServerGroup = 240 ADMIN.getRSGroup(deadServerGroup.getName()).getServers(); 241 assertEquals(serverCountToMoveToDeadServerGroup, ServersInDeadServerGroup.size()); 242 assertTrue(ServersInDeadServerGroup.contains(serverToStop.getAddress())); 243 } 244 245 @Test 246 public void testRSGroupsWithHBaseQuota() throws Exception { 247 toggleQuotaCheckAndRestartMiniCluster(true); 248 TEST_UTIL.waitFor(90000, new Waiter.Predicate<Exception>() { 249 @Override 250 public boolean evaluate() throws Exception { 251 return ADMIN.isTableAvailable(QuotaTableUtil.QUOTA_TABLE_NAME); 252 } 253 }); 254 toggleQuotaCheckAndRestartMiniCluster(false); 255 } 256}