From 7c3895c8f61c5b7c15bd3fe0f5762e1be7428a5e Mon Sep 17 00:00:00 2001 From: Jian He Date: Wed, 20 May 2015 17:20:21 -0700 Subject: [PATCH] YARN-3654. ContainerLogsPage web UI should not have meta-refresh. Contributed by Xuan Gong (cherry picked from commit 6329bd00fa1f17cc9555efa496ea7607ad93e0ce) --- hadoop-yarn-project/CHANGES.txt | 3 + .../nodemanager/webapp/ContainerLogsPage.java | 3 - .../nodemanager/webapp/NMController.java | 40 +----- .../nodemanager/webapp/NMWebAppFilter.java | 118 ++++++++++++++++++ .../server/nodemanager/webapp/WebServer.java | 7 +- 5 files changed, 128 insertions(+), 43 deletions(-) create mode 100644 hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMWebAppFilter.java diff --git a/hadoop-yarn-project/CHANGES.txt b/hadoop-yarn-project/CHANGES.txt index 9824be60825..a5637da315f 100644 --- a/hadoop-yarn-project/CHANGES.txt +++ b/hadoop-yarn-project/CHANGES.txt @@ -381,6 +381,9 @@ Release 2.8.0 - UNRELEASED YARN-2821. Fixed a problem that DistributedShell AM may hang if restarted. (Varun Vasudev via jianhe) + YARN-3654. ContainerLogsPage web UI should not have meta-refresh. (Xuan Gong + via jianhe) + Release 2.7.1 - UNRELEASED INCOMPATIBLE CHANGES diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/ContainerLogsPage.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/ContainerLogsPage.java index 48e0c87ac60..2fd6b2cdf11 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/ContainerLogsPage.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/ContainerLogsPage.java @@ -59,9 +59,6 @@ public class ContainerLogsPage extends NMView { if (redirectUrl.equals("false")) { set(TITLE, join("Failed redirect for ", $(CONTAINER_ID))); //Error getting redirect url. Fall through. - } else { - set(TITLE, join("Redirecting to log server for ", $(CONTAINER_ID))); - html.meta_http("refresh", "1; url=" + redirectUrl); } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMController.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMController.java index 097532f8d03..5be5b353953 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMController.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMController.java @@ -20,29 +20,16 @@ package org.apache.hadoop.yarn.server.nodemanager.webapp; import static org.apache.hadoop.yarn.util.StringHelper.join; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.yarn.api.records.ApplicationId; -import org.apache.hadoop.yarn.api.records.ContainerId; -import org.apache.hadoop.yarn.conf.YarnConfiguration; -import org.apache.hadoop.yarn.server.nodemanager.Context; -import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.Application; -import org.apache.hadoop.yarn.util.ConverterUtils; import org.apache.hadoop.yarn.webapp.Controller; import org.apache.hadoop.yarn.webapp.YarnWebParams; import com.google.inject.Inject; public class NMController extends Controller implements YarnWebParams { - - private Context nmContext; - private Configuration nmConf; @Inject - public NMController(Configuration nmConf, RequestContext requestContext, - Context nmContext) { + public NMController(RequestContext requestContext) { super(requestContext); - this.nmContext = nmContext; - this.nmConf = nmConf; } @Override @@ -80,31 +67,6 @@ public class NMController extends Controller implements YarnWebParams { } public void logs() { - String containerIdStr = $(CONTAINER_ID); - ContainerId containerId = null; - try { - containerId = ConverterUtils.toContainerId(containerIdStr); - } catch (IllegalArgumentException e) { - render(ContainerLogsPage.class); - return; - } - ApplicationId appId = - containerId.getApplicationAttemptId().getApplicationId(); - Application app = nmContext.getApplications().get(appId); - if (app == null - && nmConf.getBoolean(YarnConfiguration.LOG_AGGREGATION_ENABLED, - YarnConfiguration.DEFAULT_LOG_AGGREGATION_ENABLED)) { - String logServerUrl = nmConf.get(YarnConfiguration.YARN_LOG_SERVER_URL); - String redirectUrl = null; - if (logServerUrl == null || logServerUrl.isEmpty()) { - redirectUrl = "false"; - } else { - redirectUrl = - url(logServerUrl, nmContext.getNodeId().toString(), containerIdStr, - containerIdStr, $(APP_OWNER)); - } - set(ContainerLogsPage.REDIRECT_URL, redirectUrl); - } render(ContainerLogsPage.class); } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMWebAppFilter.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMWebAppFilter.java new file mode 100644 index 00000000000..63fe6ea75b2 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMWebAppFilter.java @@ -0,0 +1,118 @@ +/** + * 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.yarn.server.nodemanager.webapp; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.http.HtmlQuoting; +import org.apache.hadoop.yarn.api.records.ApplicationId; +import org.apache.hadoop.yarn.api.records.ContainerId; +import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.server.nodemanager.Context; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.Application; +import org.apache.hadoop.yarn.webapp.Controller.RequestContext; +import com.google.inject.Injector; +import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; + +@Singleton +public class NMWebAppFilter extends GuiceContainer{ + + private Injector injector; + private Context nmContext; + + private static final long serialVersionUID = 1L; + + @Inject + public NMWebAppFilter(Injector injector, Context nmContext) { + super(injector); + this.injector = injector; + this.nmContext = nmContext; + } + + @Override + public void doFilter(HttpServletRequest request, + HttpServletResponse response, FilterChain chain) throws IOException, + ServletException { + String uri = HtmlQuoting.quoteHtmlChars(request.getRequestURI()); + String redirectPath = containerLogPageRedirectPath(uri); + if (redirectPath != null) { + String redirectMsg = + "Redirecting to log server" + " : " + redirectPath; + PrintWriter out = response.getWriter(); + out.println(redirectMsg); + response.setHeader("Location", redirectPath); + response.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT); + return; + } + super.doFilter(request, response, chain); + } + + private String containerLogPageRedirectPath(String uri) { + String redirectPath = null; + if (!uri.contains("/ws/v1/node") && uri.contains("/containerlogs")) { + String[] parts = uri.split("/"); + String containerIdStr = parts[3]; + String appOwner = parts[4]; + if (containerIdStr != null && !containerIdStr.isEmpty()) { + ContainerId containerId = null; + try { + containerId = ContainerId.fromString(containerIdStr); + } catch (IllegalArgumentException ex) { + return redirectPath; + } + ApplicationId appId = + containerId.getApplicationAttemptId().getApplicationId(); + Application app = nmContext.getApplications().get(appId); + Configuration nmConf = nmContext.getLocalDirsHandler().getConfig(); + if (app == null + && nmConf.getBoolean(YarnConfiguration.LOG_AGGREGATION_ENABLED, + YarnConfiguration.DEFAULT_LOG_AGGREGATION_ENABLED)) { + String logServerUrl = + nmConf.get(YarnConfiguration.YARN_LOG_SERVER_URL); + if (logServerUrl != null && !logServerUrl.isEmpty()) { + StringBuilder sb = new StringBuilder(); + sb.append(logServerUrl); + sb.append("/"); + sb.append(nmContext.getNodeId().toString()); + sb.append("/"); + sb.append(containerIdStr); + sb.append("/"); + sb.append(containerIdStr); + sb.append("/"); + sb.append(appOwner); + redirectPath = sb.toString(); + } else { + injector.getInstance(RequestContext.class).set( + ContainerLogsPage.REDIRECT_URL, "false"); + } + } + } + } + return redirectPath; + } +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/WebServer.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/WebServer.java index 8c0d149eb13..0e0c1e2e248 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/WebServer.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/WebServer.java @@ -22,7 +22,6 @@ import static org.apache.hadoop.yarn.util.StringHelper.pajoin; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.http.HttpConfig; import org.apache.hadoop.service.AbstractService; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.exceptions.YarnRuntimeException; @@ -36,6 +35,8 @@ import org.apache.hadoop.yarn.webapp.WebApps; import org.apache.hadoop.yarn.webapp.YarnWebParams; import org.apache.hadoop.yarn.webapp.util.WebAppUtils; +import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; + public class WebServer extends AbstractService { private static final Log LOG = LogFactory.getLog(WebServer.class); @@ -129,5 +130,9 @@ public class WebServer extends AbstractService { route("/errors-and-warnings", NMController.class, "errorsAndWarnings"); } + @Override + protected Class getWebAppFilterClass() { + return NMWebAppFilter.class; + } } }