diff --git a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTDumpServlet.java b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTDumpServlet.java
new file mode 100644
index 000000000000..8bb306f7829a
--- /dev/null
+++ b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTDumpServlet.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.rest;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.Date;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.http.HttpServer;
+import org.apache.hadoop.hbase.monitoring.StateDumpServlet;
+import org.apache.hadoop.hbase.util.LogMonitoring;
+import org.apache.hadoop.hbase.util.Threads;
+import org.apache.yetus.audience.InterfaceAudience;
+
+@InterfaceAudience.Private
+public class RESTDumpServlet extends StateDumpServlet {
+ private static final long serialVersionUID = 1L;
+ private static final String LINE = "===========================================================";
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
+ if (!HttpServer.isInstrumentationAccessAllowed(getServletContext(), request, response)) {
+ return;
+ }
+
+ RESTServer restServer = (RESTServer) getServletContext().getAttribute(RESTServer.REST_SERVER);
+ assert restServer != null : "No REST Server in context!";
+
+ response.setContentType("text/plain");
+ OutputStream os = response.getOutputStream();
+ try (PrintWriter out = new PrintWriter(os)) {
+
+ out.println("REST Server status for " + restServer.getServerName() + " as of " + new Date());
+
+ out.println("\n\nVersion Info:");
+ out.println(LINE);
+ dumpVersionInfo(out);
+
+ out.println("\n\nStacks:");
+ out.println(LINE);
+ out.flush();
+ PrintStream ps = new PrintStream(response.getOutputStream(), false, "UTF-8");
+ Threads.printThreadInfo(ps, "");
+ ps.flush();
+
+ out.println("\n\nREST Server configuration:");
+ out.println(LINE);
+ Configuration conf = restServer.conf;
+ out.flush();
+ conf.writeXml(os);
+ os.flush();
+
+ out.println("\n\nLogs");
+ out.println(LINE);
+ long tailKb = getTailKbParam(request);
+ LogMonitoring.dumpTailOfLogs(out, tailKb);
+
+ out.flush();
+ }
+ }
+}
diff --git a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServer.java b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServer.java
index 5796cd066f9d..dea6f2909875 100644
--- a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServer.java
+++ b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServer.java
@@ -20,6 +20,7 @@
import static org.apache.hadoop.hbase.http.HttpServerUtil.PATH_SPEC_ANY;
import java.lang.management.ManagementFactory;
+import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
@@ -31,6 +32,7 @@
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HBaseInterfaceAudience;
+import org.apache.hadoop.hbase.ServerName;
import org.apache.hadoop.hbase.http.HttpServerUtil;
import org.apache.hadoop.hbase.http.InfoServer;
import org.apache.hadoop.hbase.log.HBaseMarkers;
@@ -83,6 +85,7 @@
@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS)
public class RESTServer implements Constants {
static Logger LOG = LoggerFactory.getLogger("RESTServer");
+ public static final String REST_SERVER = "rest";
static final String REST_CSRF_ENABLED_KEY = "hbase.rest.csrf.enabled";
static final boolean REST_CSRF_ENABLED_DEFAULT = false;
@@ -110,6 +113,7 @@ public class RESTServer implements Constants {
private final UserProvider userProvider;
private Server server;
private InfoServer infoServer;
+ private ServerName serverName;
public RESTServer(Configuration conf) {
RESTServer.conf = conf;
@@ -143,8 +147,7 @@ void addCSRFFilter(ServletContextHandler ctxHandler, Configuration conf) {
loginServerPrincipal(UserProvider userProvider, Configuration conf) throws Exception {
Class extends ServletContainer> containerClass = ServletContainer.class;
if (userProvider.isHadoopSecurityEnabled() && userProvider.isHBaseSecurityEnabled()) {
- String machineName = Strings.domainNamePointerToHostName(DNS.getDefaultHost(
- conf.get(REST_DNS_INTERFACE, "default"), conf.get(REST_DNS_NAMESERVER, "default")));
+ String machineName = getHostName(conf);
String keytabFilename = conf.get(REST_KEYTAB_FILE);
Preconditions.checkArgument(keytabFilename != null && !keytabFilename.isEmpty(),
REST_KEYTAB_FILE + " should be set if security is enabled");
@@ -385,9 +388,14 @@ public synchronized void run() throws Exception {
// Put up info server.
int port = conf.getInt("hbase.rest.info.port", 8085);
if (port >= 0) {
- conf.setLong("startcode", EnvironmentEdgeManager.currentTime());
- String a = conf.get("hbase.rest.info.bindAddress", "0.0.0.0");
- this.infoServer = new InfoServer("rest", a, port, false, conf);
+ final long startCode = EnvironmentEdgeManager.currentTime();
+ conf.setLong("startcode", startCode);
+ this.serverName = ServerName.valueOf(getHostName(conf), servicePort, startCode);
+
+ String addr = conf.get("hbase.rest.info.bindAddress", "0.0.0.0");
+ this.infoServer = new InfoServer(REST_SERVER, addr, port, false, conf);
+ this.infoServer.addPrivilegedServlet("dump", "/dump", RESTDumpServlet.class);
+ this.infoServer.setAttribute(REST_SERVER, this);
this.infoServer.setAttribute("hbase.conf", conf);
this.infoServer.start();
}
@@ -395,6 +403,11 @@ public synchronized void run() throws Exception {
server.start();
}
+ private static String getHostName(Configuration conf) throws UnknownHostException {
+ return Strings.domainNamePointerToHostName(DNS.getDefaultHost(
+ conf.get(REST_DNS_INTERFACE, "default"), conf.get(REST_DNS_NAMESERVER, "default")));
+ }
+
public synchronized void join() throws Exception {
if (server == null) {
throw new IllegalStateException("Server is not running");
@@ -402,7 +415,19 @@ public synchronized void join() throws Exception {
server.join();
}
+ private void stopInfoServer() {
+ if (this.infoServer != null) {
+ LOG.info("Stop info server");
+ try {
+ this.infoServer.stop();
+ } catch (Exception e) {
+ LOG.error("Failed to stop infoServer", e);
+ }
+ }
+ }
+
public synchronized void stop() throws Exception {
+ stopInfoServer();
if (server == null) {
throw new IllegalStateException("Server is not running");
}
@@ -426,6 +451,10 @@ public synchronized int getInfoPort() {
return infoServer.getPort();
}
+ public ServerName getServerName() {
+ return serverName;
+ }
+
public Configuration getConf() {
return conf;
}
diff --git a/hbase-rest/src/main/resources/hbase-webapps/rest/footer.jsp b/hbase-rest/src/main/resources/hbase-webapps/rest/footer.jsp
new file mode 100644
index 000000000000..a642ac36eff7
--- /dev/null
+++ b/hbase-rest/src/main/resources/hbase-webapps/rest/footer.jsp
@@ -0,0 +1,32 @@
+<%--
+/**
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+--%>
+
+
+
+
+
+