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