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.http; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertNull; 022import static org.junit.Assert.assertTrue; 023 024import java.io.BufferedReader; 025import java.io.IOException; 026import java.io.InputStreamReader; 027import java.net.HttpURLConnection; 028import java.net.URL; 029import java.util.ArrayList; 030import java.util.List; 031import org.apache.hadoop.conf.Configuration; 032import org.apache.hadoop.fs.Path; 033import org.apache.hadoop.hbase.HBaseClassTestRule; 034import org.apache.hadoop.hbase.HBaseTestingUtil; 035import org.apache.hadoop.hbase.HConstants; 036import org.apache.hadoop.hbase.LocalHBaseCluster; 037import org.apache.hadoop.hbase.ServerName; 038import org.apache.hadoop.hbase.TableName; 039import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; 040import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 041import org.apache.hadoop.hbase.client.TableDescriptor; 042import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 043import org.apache.hadoop.hbase.master.HMaster; 044import org.apache.hadoop.hbase.master.ServerManager; 045import org.apache.hadoop.hbase.testclassification.MasterTests; 046import org.apache.hadoop.hbase.testclassification.MediumTests; 047import org.apache.hadoop.hbase.util.CommonFSUtils; 048import org.apache.hadoop.hbase.util.VersionInfo; 049import org.junit.AfterClass; 050import org.junit.BeforeClass; 051import org.junit.ClassRule; 052import org.junit.Rule; 053import org.junit.Test; 054import org.junit.experimental.categories.Category; 055import org.junit.rules.TestName; 056 057@Category({ MasterTests.class, MediumTests.class }) 058public class TestMasterStatusPage { 059 060 @ClassRule 061 public static final HBaseClassTestRule CLASS_RULE = 062 HBaseClassTestRule.forClass(TestMasterStatusPage.class); 063 064 private final static HBaseTestingUtil UTIL = new HBaseTestingUtil(); 065 public static final String TEST_TABLE_NAME_1 = "TEST_TABLE_1"; 066 public static final String TEST_TABLE_NAME_2 = "TEST_TABLE_2"; 067 068 private static LocalHBaseCluster CLUSTER; 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("TestMasterStatusPage"); 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 testMasterStatusPage() throws Exception { 107 HMaster master = CLUSTER.getActiveMaster(); 108 109 createTestTables(master); 110 111 String page = getMasterStatusPageContent(); 112 113 String hostname = master.getServerName().getHostname(); 114 assertTrue(page.contains("<h1>Master <small>" + hostname + "</small></h1>")); 115 assertTrue(page.contains("<h2><a name=\"regionservers\">Region Servers</a></h2>")); 116 assertRegionServerLinks(master, page); 117 118 assertTrue(page.contains("<h2>Backup Masters</h2>")); 119 assertTrue(page.contains("<h2><a name=\"tables\">Tables</a></h2>")); 120 assertTableLinks(master, page); 121 122 assertTrue(page.contains("<h2><a name=\"region_visualizer\"></a>Region Visualizer</h2>")); 123 assertTrue(page.contains("<h2><a name=\"peers\">Peers</a></h2>")); 124 assertTrue(page.contains("<h2><a name=\"tasks\">Tasks</a></h2>")); 125 assertTrue(page.contains("<h2><a name=\"attributes\">Software Attributes</a></h2>")); 126 127 assertTrue(page.contains(VersionInfo.getVersion())); 128 } 129 130 private String getMasterStatusPageContent() throws IOException { 131 URL url = new URL(getInfoServerHostAndPort() + "/master-status"); 132 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 133 conn.connect(); 134 135 assertEquals(200, conn.getResponseCode()); 136 assertEquals("text/html;charset=utf-8", conn.getContentType()); 137 138 return getResponseBody(conn); 139 } 140 141 private static void createTestTables(HMaster master) throws IOException { 142 ColumnFamilyDescriptor cf = ColumnFamilyDescriptorBuilder.of("CF"); 143 TableDescriptor tableDescriptor1 = TableDescriptorBuilder 144 .newBuilder(TableName.valueOf(TEST_TABLE_NAME_1)).setColumnFamily(cf).build(); 145 master.createTable(tableDescriptor1, null, 0, 0); 146 TableDescriptor tableDescriptor2 = TableDescriptorBuilder 147 .newBuilder(TableName.valueOf(TEST_TABLE_NAME_2)).setColumnFamily(cf).build(); 148 master.createTable(tableDescriptor2, null, 0, 0); 149 master.flushMasterStore(); 150 } 151 152 private String getInfoServerHostAndPort() { 153 return "http://localhost:" + CLUSTER.getActiveMaster().getInfoServer().getPort(); 154 } 155 156 private static String getResponseBody(HttpURLConnection conn) throws IOException { 157 StringBuilder sb = new StringBuilder(); 158 BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); 159 String output; 160 while ((output = br.readLine()) != null) { 161 sb.append(output); 162 } 163 return sb.toString(); 164 } 165 166 private static void assertRegionServerLinks(HMaster master, String responseBody) { 167 ServerManager serverManager = master.getServerManager(); 168 List<ServerName> servers = serverManager.getOnlineServersList(); 169 assertEquals(1, servers.size()); 170 for (ServerName serverName : servers) { 171 String expectedRsLink = MasterStatusUtil.serverNameLink(master, serverName); 172 assertTrue(responseBody.contains(expectedRsLink)); 173 } 174 } 175 176 private static void assertTableLinks(HMaster master, String responseBody) { 177 List<TableDescriptor> tables = new ArrayList<>(); 178 String errorMessage = MasterStatusUtil.getUserTables(master, tables); 179 assertNull(errorMessage); 180 assertEquals(2, tables.size()); 181 for (TableDescriptor table : tables) { 182 String tableName = table.getTableName().getNameAsString(); 183 String expectedTableLink = "<a href=table.jsp?name=" + tableName + ">" + tableName + "</a>"; 184 assertTrue(responseBody.contains(expectedTableLink)); 185 } 186 } 187}