From 6893a47788ea731ab6494265b1adbce2320b34c2 Mon Sep 17 00:00:00 2001 From: Jon Bringhurst Date: Mon, 5 Jun 2023 16:34:44 -0700 Subject: [PATCH 1/2] YARN-7747 use injected GuiceFilter instances --- .../java/org/apache/hadoop/http/HttpServer2.java | 15 +++++++++++++-- .../org/apache/hadoop/yarn/webapp/WebApp.java | 3 +++ .../org/apache/hadoop/yarn/webapp/WebApps.java | 4 ---- .../yarn/server/nodemanager/webapp/WebServer.java | 6 +++++- .../server/resourcemanager/ResourceManager.java | 12 +++++++----- 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java index 515148e929817..3a7f146d6fe5c 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java @@ -1212,6 +1212,13 @@ public static void defineFilter(ServletContextHandler ctx, String name, defineFilter(ctx, filterHolder, fmap); } + public static void defineFilter(ServletContextHandler ctx, String name, + Filter filter, Map parameters, String[] urls) { + FilterHolder filterHolder = getFilterHolder(name, filter, parameters); + FilterMapping fmap = getFilterMapping(name, urls); + defineFilter(ctx, filterHolder, fmap); + } + /** * Define a filter for a context and set up default url mappings. */ @@ -1229,11 +1236,15 @@ private static FilterMapping getFilterMapping(String name, String[] urls) { return fmap; } - private static FilterHolder getFilterHolder(String name, String classname, + private static FilterHolder getFilterHolder(String name, Object filter, Map parameters) { FilterHolder holder = new FilterHolder(); holder.setName(name); - holder.setClassName(classname); + if (filter instanceof String) { + holder.setClassName((String)filter); + } else { + holder.setFilter((Filter)filter); + } if (parameters != null) { holder.setInitParameters(parameters); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/WebApp.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/WebApp.java index 6ef1c50cc6df5..5b28c0e1f4dc9 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/WebApp.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/WebApp.java @@ -156,6 +156,9 @@ void setHostClass(Class cls) { void setGuiceFilter(GuiceFilter instance) { guiceFilter = instance; + LOG.info("Registered webapp guice modules"); + HttpServer2.defineFilter(httpServer.getWebAppContext(), "guice", + instance, null, new String[] { "/*" }); } @Override diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/WebApps.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/WebApps.java index 9fef076196e4e..26b8f01c5450a 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/WebApps.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/WebApps.java @@ -406,10 +406,6 @@ public void setup() { restCsrfClassName, params, new String[] {"/*"}); } - - HttpServer2.defineFilter(server.getWebAppContext(), "guice", - GuiceFilter.class.getName(), null, new String[] { "/*" }); - webapp.setConf(conf); webapp.setHttpServer(server); } catch (ClassNotFoundException e) { 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 eab20accf2c68..de26d340e5a21 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 @@ -40,6 +40,8 @@ import org.apache.hadoop.yarn.webapp.util.WebAppUtils; import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; + +import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -123,7 +125,9 @@ protected void serviceStart() throws Exception { .withCSRFProtection(YarnConfiguration.NM_CSRF_PREFIX) .withXFSProtection(YarnConfiguration.NM_XFS_PREFIX) .start(this.nmWebApp); - this.port = this.webApp.httpServer().getConnectorAddress(0).getPort(); + InetSocketAddress webAddr = this.webApp.httpServer().getConnectorAddress(0); + this.port = webAddr.getPort(); + LOG.info("NMWebApp at " + webAddr.getHostName() + ":" + port); } catch (Exception e) { String msg = "NMWebapps failed to start."; LOG.error(msg, e); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java index 52aa466b3f67e..70a2820986f4b 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java @@ -592,7 +592,7 @@ private NMLivelinessMonitor createNMLivelinessMonitor() { protected AMLivelinessMonitor createAMLivelinessMonitor() { return new AMLivelinessMonitor(this.rmDispatcher); } - + protected RMNodeLabelsManager createNodeLabelManager() throws InstantiationException, IllegalAccessException { return new RMNodeLabelsManager(); @@ -613,7 +613,7 @@ protected AllocationTagsManager createAllocationTagsManager() { // Use the in memory Placement Constraint Manager. return new MemoryPlacementConstraintManager(); } - + protected DelegationTokenRenewer createDelegationTokenRenewer() { return new DelegationTokenRenewer(); } @@ -771,7 +771,7 @@ protected void serviceInit(Configuration configuration) throws Exception { AMLivelinessMonitor amFinishingMonitor = createAMLivelinessMonitor(); addService(amFinishingMonitor); rmContext.setAMFinishingMonitor(amFinishingMonitor); - + RMAppLifetimeMonitor rmAppLifetimeMonitor = createRMAppLifetimeMonitor(); addService(rmAppLifetimeMonitor); rmContext.setRMAppLifetimeMonitor(rmAppLifetimeMonitor); @@ -1478,6 +1478,8 @@ protected void startWepApp() { try { webApp = builder.start(new RMWebApp(this), uiWebAppContext); + InetSocketAddress webAddr = webApp.httpServer().getConnectorAddress(0); + LOG.info("RMWebApp at " + webAddr.getHostName() + ":" + webAddr.getPort()); } catch (WebAppException e) { webApp = e.getWebApp(); throw e; @@ -1603,7 +1605,7 @@ protected void serviceStart() throws Exception { transitionToActive(); } } - + protected void doSecureLogin() throws IOException { InetSocketAddress socAddr = getBindAddress(conf); SecurityUtil.login(this.conf, YarnConfiguration.RM_KEYTAB, @@ -1634,7 +1636,7 @@ protected void serviceStop() throws Exception { rmContext.setHAServiceState(HAServiceState.STOPPING); rmStatusInfoBean.unregister(); } - + protected ResourceTrackerService createResourceTrackerService() { return new ResourceTrackerService(this.rmContext, this.nodesListManager, this.nmLivelinessMonitor, From 57c215007bf1372aa9e9f57c99822f123eb2abd6 Mon Sep 17 00:00:00 2001 From: Jon Bringhurst Date: Mon, 5 Jun 2023 18:29:32 -0700 Subject: [PATCH 2/2] Add a basic test to check for webapp response --- .../yarn/server/TestMiniYarnCluster.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-tests/src/test/java/org/apache/hadoop/yarn/server/TestMiniYarnCluster.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-tests/src/test/java/org/apache/hadoop/yarn/server/TestMiniYarnCluster.java index c5c2e3e0f5e65..0c417afaf7758 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-tests/src/test/java/org/apache/hadoop/yarn/server/TestMiniYarnCluster.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-tests/src/test/java/org/apache/hadoop/yarn/server/TestMiniYarnCluster.java @@ -30,6 +30,8 @@ import org.junit.jupiter.api.Test; import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; public class TestMiniYarnCluster { @@ -153,4 +155,40 @@ void testMultiRMConf() throws IOException { assertEquals("rm2", conf2.get(YarnConfiguration.RM_HA_ID)); } } + + @Test + void testWebAppPortBinding() throws Exception { + Configuration conf = new YarnConfiguration(); + int numNodeManagers = 1; + int numLocalDirs = 1; + int numLogDirs = 1; + + try (MiniYARNCluster cluster = + new MiniYARNCluster(TestMiniYarnCluster.class.getSimpleName(), + numNodeManagers, numLocalDirs, numLogDirs, numLogDirs)) { + + cluster.init(conf); + cluster.start(); + + Configuration rmConf = cluster.getResourceManager(0).getConfig(); + Configuration nmConf = cluster.getNodeManager(0).getConfig(); + + URL nmWebappURL = + new URL("http://" + nmConf.get(YarnConfiguration.NM_WEBAPP_ADDRESS) + "/node"); + URL rmWebappURL = + new URL("http://" + rmConf.get(YarnConfiguration.RM_WEBAPP_ADDRESS) + "/cluster"); + + HttpURLConnection nmConn = (HttpURLConnection) nmWebappURL.openConnection(); + nmConn.setRequestMethod("GET"); + nmConn.connect(); + assertEquals(nmConn.getResponseCode(), 200); + + // Check the ResourceManager after the NodeManager to make sure it wasn't + // overwritten. Please see YARN-7747. + HttpURLConnection rmConn = (HttpURLConnection) rmWebappURL.openConnection(); + rmConn.setRequestMethod("GET"); + rmConn.connect(); + assertEquals(rmConn.getResponseCode(), 200); + } + } }