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.master.assignment; 019 020import static org.hamcrest.core.Is.isA; 021import static org.junit.jupiter.api.Assertions.assertEquals; 022import static org.junit.jupiter.api.Assertions.assertNotNull; 023import static org.junit.jupiter.api.Assertions.assertThrows; 024 025import java.io.IOException; 026import java.util.List; 027import org.apache.hadoop.conf.Configuration; 028import org.apache.hadoop.hbase.HBaseTestingUtil; 029import org.apache.hadoop.hbase.ServerName; 030import org.apache.hadoop.hbase.SingleProcessHBaseCluster; 031import org.apache.hadoop.hbase.TableName; 032import org.apache.hadoop.hbase.YouAreDeadException; 033import org.apache.hadoop.hbase.client.Admin; 034import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 035import org.apache.hadoop.hbase.client.RegionInfo; 036import org.apache.hadoop.hbase.client.TableDescriptor; 037import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 038import org.apache.hadoop.hbase.master.HMaster; 039import org.apache.hadoop.hbase.master.procedure.MasterProcedureConstants; 040import org.apache.hadoop.hbase.testclassification.MasterTests; 041import org.apache.hadoop.hbase.testclassification.MediumTests; 042import org.apache.hadoop.hbase.util.Bytes; 043import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 044import org.junit.jupiter.api.AfterAll; 045import org.junit.jupiter.api.AfterEach; 046import org.junit.jupiter.api.BeforeAll; 047import org.junit.jupiter.api.BeforeEach; 048import org.junit.jupiter.api.Disabled; 049import org.junit.jupiter.api.Tag; 050import org.junit.jupiter.api.Test; 051import org.junit.jupiter.api.TestInfo; 052import org.slf4j.Logger; 053import org.slf4j.LoggerFactory; 054 055import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException; 056import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations; 057 058import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 059import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos; 060import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos; 061import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos; 062 063/** 064 * Tests to verify master/ assignment manager functionality against rogue RS 065 */ 066@Tag(MasterTests.TAG) 067@Tag(MediumTests.TAG) 068public class TestRogueRSAssignment { 069 070 private static final Logger LOG = LoggerFactory.getLogger(TestRogueRSAssignment.class); 071 private String testMethodName; 072 073 @BeforeEach 074 public void setTestMethod(TestInfo testInfo) { 075 testMethodName = testInfo.getTestMethod().get().getName(); 076 } 077 078 private static final int initialRegionCount = 3; 079 private final static byte[] FAMILY = Bytes.toBytes("FAMILY"); 080 081 private static final HBaseTestingUtil UTIL = new HBaseTestingUtil(); 082 private static final Configuration conf = UTIL.getConfiguration(); 083 private static Admin admin; 084 private static SingleProcessHBaseCluster cluster; 085 private static HMaster master; 086 087 private static void setupConf(Configuration conf) { 088 // Reduce the maximum attempts to speed up the test 089 conf.setInt("hbase.assignment.maximum.attempts", 3); 090 conf.setInt("hbase.master.maximum.ping.server.attempts", 3); 091 conf.setInt("hbase.master.ping.server.retry.sleep.interval", 1); 092 conf.setInt(MasterProcedureConstants.MASTER_PROCEDURE_THREADS, 1); 093 } 094 095 @BeforeAll 096 public static void setupCluster() throws Exception { 097 setupConf(conf); 098 UTIL.startMiniCluster(2); 099 100 cluster = UTIL.getHBaseCluster(); 101 assertNotNull(cluster); 102 103 admin = UTIL.getAdmin(); 104 assertNotNull(admin); 105 106 master = cluster.getMaster(); 107 assertNotNull(master); 108 } 109 110 @AfterAll 111 public static void cleanupTest() throws Exception { 112 try { 113 UTIL.shutdownMiniCluster(); 114 cluster = null; 115 admin = null; 116 } catch (Exception e) { 117 LOG.warn("failure shutting down cluster", e); 118 } 119 } 120 121 @BeforeEach 122 public void setup() throws IOException { 123 // Turn off balancer 124 admin.balancerSwitch(false, true); 125 } 126 127 @AfterEach 128 public void tearDown() throws Exception { 129 for (TableDescriptor td : UTIL.getAdmin().listTableDescriptors()) { 130 LOG.info("Tear down, remove table=" + td.getTableName()); 131 UTIL.deleteTable(td.getTableName()); 132 } 133 // Turn on balancer 134 admin.balancerSwitch(true, false); 135 } 136 137 /** 138 * Ignore this test, see HBASE-21421 139 */ 140 @Test 141 @Disabled 142 public void testReportRSWithWrongRegion() throws Exception { 143 final TableName tableName = TableName.valueOf(testMethodName); 144 145 List<RegionInfo> tableRegions = createTable(tableName); 146 147 final ServerName sn = ServerName.parseVersionedServerName(ServerName 148 .valueOf("1.example.org", 1, EnvironmentEdgeManager.currentTime()).getVersionedBytes()); 149 150 // make fake request with a region assigned to different RS 151 RegionServerStatusProtos.RegionServerReportRequest.Builder request = 152 makeRSReportRequestWithRegions(sn, tableRegions.get(1)); 153 154 // sending fake request to master 155 // TODO: replace YouAreDeadException with appropriate exception as and when necessary 156 ServiceException exception = assertThrows(ServiceException.class, 157 () -> master.getMasterRpcServices().regionServerReport(null, request.build())); 158 org.hamcrest.MatcherAssert.assertThat((YouAreDeadException) exception.getCause(), 159 isA(YouAreDeadException.class)); 160 } 161 162 private RegionServerStatusProtos.RegionServerReportRequest.Builder 163 makeRSReportRequestWithRegions(final ServerName sn, RegionInfo... regions) { 164 ClusterStatusProtos.ServerLoad.Builder sl = ClusterStatusProtos.ServerLoad.newBuilder(); 165 for (int i = 0; i < regions.length; i++) { 166 HBaseProtos.RegionSpecifier.Builder rs = HBaseProtos.RegionSpecifier.newBuilder(); 167 rs.setType(HBaseProtos.RegionSpecifier.RegionSpecifierType.REGION_NAME); 168 rs.setValue(UnsafeByteOperations.unsafeWrap(regions[i].getRegionName())); 169 170 ClusterStatusProtos.RegionLoad.Builder rl = 171 ClusterStatusProtos.RegionLoad.newBuilder().setRegionSpecifier(rs.build()); 172 173 sl.addRegionLoads(i, rl.build()); 174 } 175 176 return RegionServerStatusProtos.RegionServerReportRequest.newBuilder() 177 .setServer(ProtobufUtil.toServerName(sn)).setLoad(sl); 178 } 179 180 private List<RegionInfo> createTable(final TableName tableName) throws Exception { 181 TableDescriptorBuilder tdBuilder = TableDescriptorBuilder.newBuilder(tableName); 182 tdBuilder.setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(FAMILY).build()); 183 184 byte[][] rows = new byte[initialRegionCount - 1][]; 185 for (int i = 0; i < rows.length; ++i) { 186 rows[i] = Bytes.toBytes(String.format("%d", i)); 187 } 188 admin.createTable(tdBuilder.build(), rows); 189 return assertRegionCount(tableName, initialRegionCount); 190 } 191 192 private List<RegionInfo> assertRegionCount(final TableName tableName, final int nregions) 193 throws Exception { 194 UTIL.waitUntilNoRegionsInTransition(); 195 List<RegionInfo> tableRegions = admin.getRegions(tableName); 196 assertEquals(nregions, tableRegions.size()); 197 return tableRegions; 198 } 199}