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.regionserver.http; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertTrue; 022 023import java.io.BufferedReader; 024import java.io.IOException; 025import java.io.InputStreamReader; 026import java.net.HttpURLConnection; 027import java.net.URL; 028import java.util.List; 029import org.apache.hadoop.conf.Configuration; 030import org.apache.hadoop.fs.Path; 031import org.apache.hadoop.hbase.HBaseClassTestRule; 032import org.apache.hadoop.hbase.HBaseTestingUtil; 033import org.apache.hadoop.hbase.HConstants; 034import org.apache.hadoop.hbase.LocalHBaseCluster; 035import org.apache.hadoop.hbase.ServerName; 036import org.apache.hadoop.hbase.TableName; 037import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; 038import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 039import org.apache.hadoop.hbase.client.TableDescriptor; 040import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 041import org.apache.hadoop.hbase.master.HMaster; 042import org.apache.hadoop.hbase.master.ServerManager; 043import org.apache.hadoop.hbase.testclassification.MediumTests; 044import org.apache.hadoop.hbase.testclassification.RegionServerTests; 045import org.apache.hadoop.hbase.util.CommonFSUtils; 046import org.junit.AfterClass; 047import org.junit.BeforeClass; 048import org.junit.ClassRule; 049import org.junit.Rule; 050import org.junit.Test; 051import org.junit.experimental.categories.Category; 052import org.junit.rules.TestName; 053 054/** 055 * Tests for the region server status page and its template. 056 */ 057@Category({ RegionServerTests.class, MediumTests.class }) 058public class TestRSStatusPage { 059 060 @ClassRule 061 public static final HBaseClassTestRule CLASS_RULE = 062 HBaseClassTestRule.forClass(TestRSStatusPage.class); 063 064 private static LocalHBaseCluster CLUSTER; 065 066 private final static HBaseTestingUtil UTIL = new HBaseTestingUtil(); 067 public static final String TEST_TABLE_NAME_1 = "TEST_TABLE_1"; 068 public static final String TEST_TABLE_NAME_2 = "TEST_TABLE_2"; 069 070 @Rule 071 public TestName name = new TestName(); 072 073 @BeforeClass 074 public static void beforeClass() throws Exception { 075 Configuration conf = UTIL.getConfiguration(); 076 UTIL.startMiniZKCluster(); 077 078 UTIL.startMiniDFSCluster(1); 079 Path rootdir = UTIL.getDataTestDirOnTestFS("TestRSStatusPage"); 080 CommonFSUtils.setRootDir(conf, rootdir); 081 082 // The info servers do not run in tests by default. 083 // Set them to ephemeral ports so they will start 084 // setup configuration 085 conf.setInt(HConstants.MASTER_INFO_PORT, 0); 086 conf.setInt(HConstants.REGIONSERVER_INFO_PORT, 0); 087 088 CLUSTER = new LocalHBaseCluster(conf, 1); 089 CLUSTER.startup(); 090 CLUSTER.getActiveMaster().waitForMetaOnline(); 091 } 092 093 /** 094 * Helper method to shut down the cluster (if running) 095 */ 096 @AfterClass 097 public static void shutDownMiniCluster() throws Exception { 098 if (CLUSTER != null) { 099 CLUSTER.shutdown(); 100 CLUSTER.join(); 101 } 102 UTIL.shutdownMiniCluster(); 103 } 104 105 @Test 106 public void testStatusPage() throws Exception { 107 HMaster master = CLUSTER.getActiveMaster(); 108 109 int masterPort = master.getActiveMasterManager().getActiveMasterInfoPort(); 110 ServerName activeMaster = 111 master.getActiveMaster().orElseThrow(() -> new IllegalStateException("No active master")); 112 String masterHostname = activeMaster.getHostname(); 113 114 createTestTables(master); 115 116 ServerManager serverManager = master.getServerManager(); 117 List<ServerName> onlineServersList = serverManager.getOnlineServersList(); 118 119 assertEquals(1, onlineServersList.size()); 120 121 ServerName firstServerName = onlineServersList.get(0); 122 int infoPort = master.getRegionServerInfoPort(firstServerName); 123 String hostname = firstServerName.getHostname(); 124 int port = firstServerName.getPort(); 125 126 String page = getRegionServerStatusPageContent(hostname, infoPort); 127 128 assertTrue(page.contains("<title>HBase Region Server: " + masterHostname + "</title>")); 129 130 String expectedPageHeader = "<h1>RegionServer <small>" + hostname + "," + port + "," 131 + firstServerName.getStartCode() + "</small></h1>"; 132 assertTrue(page.contains(expectedPageHeader)); 133 assertTrue(page.contains("<h2>Server Metrics</h2>")); 134 assertTrue(page.contains("<th>Requests Per Second</th>")); 135 assertTrue(page.contains("<h2>Block Cache</h2>")); 136 assertTrue(page.contains("<h2>Regions</h2>")); 137 assertTrue(page.contains("<h2>Replication Status</h2>")); 138 assertTrue(page.contains("<h2>Software Attributes</h2>")); 139 140 // Should have a link to master 141 String expectedMasterLink = "<a href=\"//" + masterHostname + ":" + masterPort 142 + "/master.jsp\">" + masterHostname + ":" + masterPort + "</a>"; 143 assertTrue(page.contains(expectedMasterLink)); 144 } 145 146 private static void createTestTables(HMaster master) throws IOException { 147 ColumnFamilyDescriptor cf = ColumnFamilyDescriptorBuilder.of("CF"); 148 TableDescriptor tableDescriptor1 = TableDescriptorBuilder 149 .newBuilder(TableName.valueOf(TEST_TABLE_NAME_1)).setColumnFamily(cf).build(); 150 master.createTable(tableDescriptor1, null, 0, 0); 151 TableDescriptor tableDescriptor2 = TableDescriptorBuilder 152 .newBuilder(TableName.valueOf(TEST_TABLE_NAME_2)).setColumnFamily(cf).build(); 153 master.createTable(tableDescriptor2, null, 0, 0); 154 master.flushMasterStore(); 155 } 156 157 private static String getRegionServerStatusPageContent(String hostname, int infoPort) 158 throws IOException { 159 URL url = new URL("http://" + hostname + ":" + infoPort + "/regionserver.jsp"); 160 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 161 conn.connect(); 162 163 assertEquals(200, conn.getResponseCode()); 164 assertEquals("text/html;charset=utf-8", conn.getContentType()); 165 166 return getResponseBody(conn); 167 } 168 169 private static String getResponseBody(HttpURLConnection conn) throws IOException { 170 StringBuilder sb = new StringBuilder(); 171 BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); 172 String output; 173 while ((output = br.readLine()) != null) { 174 sb.append(output); 175 } 176 return sb.toString(); 177 } 178}