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; 019 020import static org.junit.jupiter.api.Assertions.assertEquals; 021import static org.junit.jupiter.api.Assertions.assertFalse; 022import static org.junit.jupiter.api.Assertions.assertTrue; 023 024import java.io.IOException; 025import java.io.InputStream; 026import java.net.URL; 027import org.apache.commons.io.IOUtils; 028import org.apache.hadoop.hbase.client.Admin; 029import org.apache.hadoop.hbase.master.HMaster; 030import org.apache.hadoop.hbase.testclassification.MediumTests; 031import org.apache.hadoop.hbase.testclassification.MiscTests; 032import org.apache.hadoop.hbase.util.Bytes; 033import org.junit.jupiter.api.AfterAll; 034import org.junit.jupiter.api.BeforeAll; 035import org.junit.jupiter.api.Tag; 036import org.junit.jupiter.api.Test; 037import org.junit.jupiter.api.TestInfo; 038import org.slf4j.Logger; 039import org.slf4j.LoggerFactory; 040 041/** 042 * Testing, info servers are disabled. This test enables then and checks that they serve pages. 043 */ 044@Tag(MiscTests.TAG) 045@Tag(MediumTests.TAG) 046public class TestInfoServers { 047 048 private static final Logger LOG = LoggerFactory.getLogger(TestInfoServers.class); 049 private final static HBaseTestingUtil UTIL = new HBaseTestingUtil(); 050 051 @BeforeAll 052 public static void beforeClass() throws Exception { 053 // The info servers do not run in tests by default. 054 // Set them to ephemeral ports so they will start 055 UTIL.getConfiguration().setInt(HConstants.MASTER_INFO_PORT, 0); 056 UTIL.getConfiguration().setInt(HConstants.REGIONSERVER_INFO_PORT, 0); 057 058 // We need to make sure that the server can be started as read only. 059 UTIL.getConfiguration().setBoolean("hbase.master.ui.readonly", true); 060 UTIL.startMiniCluster(); 061 if (!UTIL.getHBaseCluster().waitForActiveAndReadyMaster(30000)) { 062 throw new RuntimeException("Active master not ready"); 063 } 064 } 065 066 @AfterAll 067 public static void afterClass() throws Exception { 068 UTIL.shutdownMiniCluster(); 069 } 070 071 @Test 072 public void testGetMasterInfoPort() throws Exception { 073 try (Admin admin = UTIL.getAdmin()) { 074 assertEquals(UTIL.getHBaseCluster().getMaster().getInfoServer().getPort(), 075 admin.getMasterInfoPort()); 076 } 077 } 078 079 /** 080 * Ensure when we go to top level index pages that we get redirected to an info-server specific 081 * status page. 082 */ 083 @Test 084 public void testInfoServersRedirect() throws Exception { 085 // give the cluster time to start up 086 UTIL.getConnection().getTable(TableName.META_TABLE_NAME).close(); 087 int port = UTIL.getHBaseCluster().getMaster().getInfoServer().getPort(); 088 assertContainsContent(new URL("http://localhost:" + port + "/index.html"), "master.jsp"); 089 assertContainsContent(new URL("http://localhost:" + port + "/master-status"), "master.jsp"); 090 port = UTIL.getHBaseCluster().getRegionServerThreads().get(0).getRegionServer().getInfoServer() 091 .getPort(); 092 assertContainsContent(new URL("http://localhost:" + port + "/index.html"), "regionserver.jsp"); 093 assertContainsContent(new URL("http://localhost:" + port + "/rs-status"), "regionserver.jsp"); 094 } 095 096 /** 097 * Test that the status pages in the minicluster load properly. This is somewhat a duplicate of 098 * TestRSStatusServlet and TestMasterStatusServlet, but those are true unit tests whereas this 099 * uses a cluster. 100 */ 101 @Test 102 public void testInfoServersStatusPages() throws Exception { 103 int port = UTIL.getHBaseCluster().getMaster().getInfoServer().getPort(); 104 assertContainsContent(new URL("http://localhost:" + port + "/master.jsp"), "meta"); 105 port = UTIL.getHBaseCluster().getRegionServerThreads().get(0).getRegionServer().getInfoServer() 106 .getPort(); 107 assertContainsContent(new URL("http://localhost:" + port + "/regionserver.jsp"), "meta"); 108 } 109 110 @Test 111 public void testMasterServerReadOnly(TestInfo testInfo) throws Exception { 112 final TableName tableName = TableName.valueOf(testInfo.getTestMethod().get().getName()); 113 byte[] cf = Bytes.toBytes("d"); 114 UTIL.createTable(tableName, cf); 115 UTIL.waitTableAvailable(tableName); 116 HMaster master = UTIL.getHBaseCluster().getMaster(); 117 int port = master.getRegionServerInfoPort(master.getServerName()); 118 assertDoesNotContainContent( 119 new URL("http://localhost:" + port + "/table.jsp?name=" + tableName + "&action=split&key="), 120 "Table action request accepted"); 121 assertDoesNotContainContent( 122 new URL("http://localhost:" + port + "/table.jsp?name=" + tableName), "Actions:"); 123 } 124 125 private void assertContainsContent(final URL u, final String expected) throws IOException { 126 LOG.info("Testing " + u.toString() + " has " + expected); 127 String content = getUrlContent(u); 128 assertTrue(content.contains(expected), "expected=" + expected + ", content=" + content); 129 } 130 131 private void assertDoesNotContainContent(final URL u, final String expected) throws IOException { 132 LOG.info("Testing " + u.toString() + " does not have " + expected); 133 String content = getUrlContent(u); 134 assertFalse(content.contains(expected), 135 "Does Not Contain =" + expected + ", content=" + content); 136 } 137 138 private String getUrlContent(URL u) throws IOException { 139 java.net.URLConnection c = u.openConnection(); 140 c.setConnectTimeout(20000); 141 c.setReadTimeout(20000); 142 c.connect(); 143 try (InputStream in = c.getInputStream()) { 144 return IOUtils.toString(in, HConstants.UTF8_ENCODING); 145 } 146 } 147}