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