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