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