Repository: hbase
Updated Branches:
  refs/heads/branch-1.1 0d1feabed -> daf2dc9a8


HBASE-15328 sanity check the redirect used to send master info requests to the 
embedded regionserver.

Signed-off-by: Esteban Gutierrez <este...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/daf2dc9a
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/daf2dc9a
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/daf2dc9a

Branch: refs/heads/branch-1.1
Commit: daf2dc9a8a07caee646bf5f97c451e062075d4a7
Parents: 0d1feab
Author: Sean Busbey <bus...@apache.org>
Authored: Wed Feb 15 16:48:58 2017 -0500
Committer: Sean Busbey <bus...@apache.org>
Committed: Tue Feb 21 10:01:12 2017 -0600

----------------------------------------------------------------------
 .../org/apache/hadoop/hbase/master/HMaster.java | 57 ++++++++++++++++----
 .../hbase/regionserver/HRegionServer.java       |  7 +--
 .../apache/hadoop/hbase/TestInfoServers.java    |  3 +-
 3 files changed, 53 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/daf2dc9a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
index b786522..6a92f98 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
@@ -81,6 +81,7 @@ import org.apache.hadoop.hbase.client.Result;
 import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
 import org.apache.hadoop.hbase.exceptions.DeserializationException;
 import org.apache.hadoop.hbase.executor.ExecutorType;
+import org.apache.hadoop.hbase.http.InfoServer;
 import org.apache.hadoop.hbase.ipc.RpcServer;
 import org.apache.hadoop.hbase.ipc.ServerNotRunningYetException;
 import org.apache.hadoop.hbase.master.MasterRpcServices.BalanceSwitchMode;
@@ -159,6 +160,7 @@ import org.apache.zookeeper.KeeperException;
 import org.mortbay.jetty.Connector;
 import org.mortbay.jetty.nio.SelectChannelConnector;
 import org.mortbay.jetty.servlet.Context;
+import org.mortbay.jetty.servlet.ServletHolder;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.Maps;
@@ -334,14 +336,42 @@ public class HMaster extends HRegionServer implements 
MasterServices, Server {
   private org.mortbay.jetty.Server masterJettyServer;
 
   public static class RedirectServlet extends HttpServlet {
-    private static final long serialVersionUID = 2894774810058302472L;
-    private static int regionServerInfoPort;
+    private static final long serialVersionUID = 2894774810058302473L;
+    private final int regionServerInfoPort;
+    private final String regionServerHostname;
+
+    /**
+     * @param infoServer that we're trying to send all requests to
+     * @param hostname may be null. if given, will be used for redirects 
instead of host from client.
+     */
+    public RedirectServlet(InfoServer infoServer, String hostname) {
+       regionServerInfoPort = infoServer.getPort();
+       regionServerHostname = hostname;
+    }
 
     @Override
     public void doGet(HttpServletRequest request,
         HttpServletResponse response) throws ServletException, IOException {
+      String redirectHost = regionServerHostname;
+      if(redirectHost == null) {
+        redirectHost = request.getServerName();
+        if(!Addressing.isLocalAddress(InetAddress.getByName(redirectHost))) {
+          LOG.warn("Couldn't resolve '" + redirectHost + "' as an address 
local to this node and '" +
+              MASTER_HOSTNAME_KEY + "' is not set; client will get a HTTP 400 
response. If " +
+              "your HBase deployment relies on client accessible names that 
the region server process " +
+              "can't resolve locally, then you should set the previously 
mentioned configuration variable " +
+              "to an appropriate hostname.");
+          // no sending client provided input back to the client, so the goal 
host is just in the logs.
+          response.sendError(400, "Request was to a host that I can't resolve 
for any of the network interfaces on " +
+              "this node. If this is due to an intermediary such as an HTTP 
load balancer or other proxy, your HBase " +
+              "administrator can set '" + MASTER_HOSTNAME_KEY + "' to point to 
the correct hostname.");
+          return;
+        }
+      }
+      // TODO this scheme should come from looking at the scheme registered in 
the infoserver's http server for the
+      // host and port we're using, but it's buried way too deep to do that 
ATM.
       String redirectUrl = request.getScheme() + "://"
-        + request.getServerName() + ":" + regionServerInfoPort
+        + redirectHost + ":" + regionServerInfoPort
         + request.getRequestURI();
       response.sendRedirect(redirectUrl);
     }
@@ -444,13 +474,16 @@ public class HMaster extends HRegionServer implements 
MasterServices, Server {
     if (!conf.getBoolean("hbase.master.infoserver.redirect", true)) {
       return -1;
     }
-    int infoPort = conf.getInt("hbase.master.info.port.orig",
+    final int infoPort = conf.getInt("hbase.master.info.port.orig",
       HConstants.DEFAULT_MASTER_INFOPORT);
     // -1 is for disabling info server, so no redirecting
     if (infoPort < 0 || infoServer == null) {
       return -1;
     }
-    String addr = conf.get("hbase.master.info.bindAddress", "0.0.0.0");
+    if(infoPort == infoServer.getPort()) {
+      return infoPort;
+    }
+    final String addr = conf.get("hbase.master.info.bindAddress", "0.0.0.0");
     if (!Addressing.isLocalAddress(InetAddress.getByName(addr))) {
       String msg =
           "Failed to start redirecting jetty server. Address " + addr
@@ -460,18 +493,22 @@ public class HMaster extends HRegionServer implements 
MasterServices, Server {
       throw new IOException(msg);
     }
 
-    RedirectServlet.regionServerInfoPort = infoServer.getPort();
-    if(RedirectServlet.regionServerInfoPort == infoPort) {
-      return infoPort;
-    }
+    // TODO I'm pretty sure we could just add another binding to the 
InfoServer run by
+    // the RegionServer and have it run the RedirectServlet instead of 
standing up
+    // a second entire stack here.
     masterJettyServer = new org.mortbay.jetty.Server();
     Connector connector = new SelectChannelConnector();
     connector.setHost(addr);
     connector.setPort(infoPort);
     masterJettyServer.addConnector(connector);
     masterJettyServer.setStopAtShutdown(true);
+
+    final String redirectHostname = shouldUseThisHostnameInstead() ? 
useThisHostnameInstead : null;
+
+    final RedirectServlet redirect = new RedirectServlet(infoServer, 
redirectHostname);
     Context context = new Context(masterJettyServer, "/", Context.NO_SESSIONS);
-    context.addServlet(RedirectServlet.class, "/*");
+    context.addServlet(new ServletHolder(redirect), "/*");
+
     try {
       masterJettyServer.start();
     } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/hbase/blob/daf2dc9a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
index a86c1ef..3f02974 100644
--- 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
+++ 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
@@ -401,14 +401,15 @@ public class HRegionServer extends HasThread implements
   /*
    * hostname specified by hostname config
    */
-  private String useThisHostnameInstead;
+  protected String useThisHostnameInstead;
 
   // key to the config parameter of server hostname
   // the specification of server hostname is optional. The hostname should be 
resolvable from
   // both master and region server
+  @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG)
   final static String RS_HOSTNAME_KEY = "hbase.regionserver.hostname";
-
-  final static String MASTER_HOSTNAME_KEY = "hbase.master.hostname";
+  @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG)
+  protected final static String MASTER_HOSTNAME_KEY = "hbase.master.hostname";
 
   /**
    * This servers startcode.

http://git-wip-us.apache.org/repos/asf/hbase/blob/daf2dc9a/hbase-server/src/test/java/org/apache/hadoop/hbase/TestInfoServers.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/TestInfoServers.java 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/TestInfoServers.java
index 9eeb277..209caf9 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/TestInfoServers.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/TestInfoServers.java
@@ -65,7 +65,8 @@ public class TestInfoServers {
   }
 
   /**
-   * @throws Exception
+   * Ensure when we go to top level index pages that we get redirected to an 
info-server specific status
+   * page.
    */
   @Test
   public void testInfoServersRedirect() throws Exception {

Reply via email to