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.apache.hadoop.hbase.util.Threads.sleep; 021import static org.junit.Assert.assertEquals; 022import static org.junit.Assert.assertNotNull; 023import static org.junit.Assert.assertTrue; 024 025import java.io.IOException; 026import java.util.HashSet; 027import java.util.Set; 028import org.apache.hadoop.conf.Configuration; 029import org.apache.hadoop.hbase.HBaseClassTestRule; 030import org.apache.hadoop.hbase.HBaseTestingUtility; 031import org.apache.hadoop.hbase.HConstants; 032import org.apache.hadoop.hbase.ServerName; 033import org.apache.hadoop.hbase.TableName; 034import org.apache.hadoop.hbase.client.RegionInfo; 035import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; 036import org.apache.hadoop.hbase.net.Address; 037import org.apache.hadoop.hbase.testclassification.LargeTests; 038import org.apache.hadoop.hbase.testclassification.MasterTests; 039import org.apache.hadoop.hbase.util.Bytes; 040import org.junit.After; 041import org.junit.Before; 042import org.junit.ClassRule; 043import org.junit.Test; 044import org.junit.experimental.categories.Category; 045import org.slf4j.Logger; 046import org.slf4j.LoggerFactory; 047 048@Category({ MasterTests.class, LargeTests.class }) 049public class TestAssignmentOnRSGroupCrash { 050 @ClassRule 051 public static final HBaseClassTestRule CLASS_RULE = 052 HBaseClassTestRule.forClass(TestAssignmentOnRSGroupCrash.class); 053 054 private static final Logger LOG = LoggerFactory.getLogger(TestAssignmentOnRSGroupCrash.class); 055 056 private static final TableName TEST_TABLE = TableName.valueOf("testb"); 057 private static final String FAMILY_STR = "f"; 058 private static final byte[] FAMILY = Bytes.toBytes(FAMILY_STR); 059 private static final int NUM_RS = 3; 060 061 private HBaseTestingUtility UTIL; 062 063 private static RSGroupAdmin rsGroupAdmin; 064 065 private static void setupConf(Configuration conf) { 066 conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, RSGroupAdminEndpoint.class.getName()); 067 conf.set(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, RSGroupBasedLoadBalancer.class.getName()); 068 } 069 070 @Before 071 public void setup() throws Exception { 072 UTIL = new HBaseTestingUtility(); 073 074 setupConf(UTIL.getConfiguration()); 075 UTIL.startMiniCluster(NUM_RS); 076 077 UTIL.createTable(TEST_TABLE, new byte[][] { FAMILY }, 078 new byte[][] { Bytes.toBytes("B"), Bytes.toBytes("D"), Bytes.toBytes("F"), 079 Bytes.toBytes("L") }); 080 rsGroupAdmin = new VerifyingRSGroupAdminClient(new RSGroupAdminClient(UTIL.getConnection()), 081 UTIL.getConfiguration()); 082 } 083 084 @After 085 public void tearDown() throws Exception { 086 UTIL.shutdownMiniCluster(); 087 } 088 089 @Test 090 public void testKillAllRSInGroupAndThenStart() throws Exception { 091 // create a rsgroup and move one regionserver to it 092 String groupName = "my_group"; 093 int groupRSCount = 1; 094 RSGroupTestingUtil.addRSGroup(rsGroupAdmin, groupName, groupRSCount); 095 Set<TableName> toAddTables = new HashSet<>(); 096 toAddTables.add(TEST_TABLE); 097 rsGroupAdmin.moveTables(toAddTables, groupName); 098 RSGroupInfo rsGroupInfo = rsGroupAdmin.getRSGroupInfo(groupName); 099 LOG.debug("my_group: " + rsGroupInfo.toString()); 100 Set<Address> servers = rsGroupInfo.getServers(); 101 ServerName myGroupRS = null; 102 for (int i = 0; i < NUM_RS; ++i) { 103 ServerName sn = UTIL.getMiniHBaseCluster().getRegionServer(i).getServerName(); 104 if (servers.contains(sn.getAddress())) { 105 myGroupRS = sn; 106 break; 107 } 108 } 109 assertNotNull(myGroupRS); 110 checkRegionsOnline(TEST_TABLE, true); 111 112 // stop regionserver in the rsgroup, and table regions will be offline 113 UTIL.getMiniHBaseCluster().stopRegionServer(myGroupRS); 114 // better wait for a while for region reassign 115 sleep(10000); 116 assertEquals(UTIL.getMiniHBaseCluster().getLiveRegionServerThreads().size(), 117 NUM_RS - servers.size()); 118 checkRegionsOnline(TEST_TABLE, false); 119 120 // move another regionserver to the rsgroup 121 // in this case, moving another region server can be replaced by restarting the regionserver 122 // mentioned before 123 RSGroupInfo defaultInfo = rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP); 124 Set<Address> set = new HashSet<>(); 125 for (Address server : defaultInfo.getServers()) { 126 if (set.size() == groupRSCount) { 127 break; 128 } 129 set.add(server); 130 } 131 rsGroupAdmin.moveServers(set, groupName); 132 133 // wait and check if table regions are online 134 sleep(10000); 135 checkRegionsOnline(TEST_TABLE, true); 136 } 137 138 private void checkRegionsOnline(TableName tableName, boolean isOnline) throws IOException { 139 for (RegionInfo hri : UTIL.getHBaseAdmin().getTableRegions(tableName)) { 140 assertTrue(UTIL.getMiniHBaseCluster().getMaster().getAssignmentManager().getRegionStates() 141 .isRegionOnline(hri) == isOnline); 142 } 143 } 144}