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