Browse Source

YARN-9956. Improved connection error message for YARN ApiServerClient.
Contributed by Prabhu Joseph

Eric Yang 5 years ago
parent
commit
d81d45ff2f

+ 43 - 35
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-api/src/main/java/org/apache/hadoop/yarn/service/client/ApiServiceClient.java

@@ -44,6 +44,7 @@ import org.apache.hadoop.yarn.api.records.ApplicationReport;
 import org.apache.hadoop.yarn.client.api.AppAdminClient;
 import org.apache.hadoop.yarn.client.api.YarnClient;
 import org.apache.hadoop.yarn.client.util.YarnClientUtils;
+import org.apache.hadoop.yarn.conf.HAUtil;
 import org.apache.hadoop.yarn.conf.YarnConfiguration;
 import org.apache.hadoop.yarn.exceptions.YarnException;
 import org.apache.hadoop.yarn.service.api.records.Component;
@@ -94,7 +95,7 @@ public class ApiServiceClient extends AppAdminClient {
   /**
    * Calculate Resource Manager address base on working REST API.
    */
-  String getRMWebAddress() {
+  String getRMWebAddress() throws IOException {
     Configuration conf = getConfig();
     String scheme = "http://";
     String path = "/app/v1/services/version";
@@ -105,43 +106,50 @@ public class ApiServiceClient extends AppAdminClient {
       rmAddress = conf
           .get("yarn.resourcemanager.webapp.https.address");
     }
-    boolean useKerberos = UserGroupInformation.isSecurityEnabled();
-    List<String> rmServers = getRMHAWebAddresses(conf);
-    for (String host : rmServers) {
-      try {
-        Client client = Client.create();
-        client.setFollowRedirects(false);
-        StringBuilder sb = new StringBuilder();
-        sb.append(scheme)
-            .append(host)
-            .append(path);
-        if (!useKerberos) {
-          try {
-            String username = UserGroupInformation.getCurrentUser().getShortUserName();
-            sb.append("?user.name=")
-                .append(username);
-          } catch (IOException e) {
-            LOG.debug("Fail to resolve username: {}", e);
+
+    if (HAUtil.isHAEnabled(conf)) {
+      boolean useKerberos = UserGroupInformation.isSecurityEnabled();
+      List<String> rmServers = getRMHAWebAddresses(conf);
+      StringBuilder diagnosticsMsg = new StringBuilder();
+      for (String host : rmServers) {
+        try {
+          Client client = Client.create();
+          client.setFollowRedirects(false);
+          StringBuilder sb = new StringBuilder();
+          sb.append(scheme)
+              .append(host)
+              .append(path);
+          if (!useKerberos) {
+            try {
+              String username = UserGroupInformation.getCurrentUser()
+                  .getShortUserName();
+              sb.append("?user.name=")
+                  .append(username);
+            } catch (IOException e) {
+              LOG.debug("Fail to resolve username: {}", e);
+            }
           }
+          Builder builder = client
+              .resource(sb.toString()).type(MediaType.APPLICATION_JSON);
+          if (useKerberos) {
+            String[] server = host.split(":");
+            String challenge = YarnClientUtils.generateToken(server[0]);
+            builder.header(HttpHeaders.AUTHORIZATION, "Negotiate " +
+                challenge);
+            LOG.debug("Authorization: Negotiate {}", challenge);
+          }
+          ClientResponse test = builder.get(ClientResponse.class);
+          if (test.getStatus() == 200) {
+            return scheme + host;
+          }
+        } catch (Exception e) {
+          LOG.info("Fail to connect to: " + host);
+          LOG.debug("Root cause: ", e);
+          diagnosticsMsg.append("Error connecting to " + host
+              + " due to " + e.getMessage() + "\n");
         }
-        Builder builder = client
-            .resource(sb.toString()).type(MediaType.APPLICATION_JSON);
-        if (useKerberos) {
-          String[] server = host.split(":");
-          String challenge = YarnClientUtils.generateToken(server[0]);
-          builder.header(HttpHeaders.AUTHORIZATION, "Negotiate " +
-              challenge);
-          LOG.debug("Authorization: Negotiate {}", challenge);
-        }
-        ClientResponse test = builder.get(ClientResponse.class);
-        if (test.getStatus() == 200) {
-          rmAddress = host;
-          break;
-        }
-      } catch (Exception e) {
-        LOG.info("Fail to connect to: "+host);
-        LOG.debug("Root cause: {}", e);
       }
+      throw new IOException(diagnosticsMsg.toString());
     }
     return scheme+rmAddress;
   }

+ 22 - 0
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-api/src/test/java/org/apache/hadoop/yarn/service/client/TestApiServiceClient.java

@@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletResponse;
 import com.google.common.collect.Lists;
 
 import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.yarn.conf.YarnConfiguration;
 import org.apache.hadoop.yarn.exceptions.YarnException;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.server.ServerConnector;
@@ -117,6 +118,27 @@ public class TestApiServiceClient {
     server.stop();
   }
 
+  @Test
+  public void testGetRMWebAddress() throws Exception {
+    Configuration conf = new Configuration();
+    conf.setBoolean(YarnConfiguration.RM_HA_ENABLED, true);
+    conf.set(YarnConfiguration.RM_HA_IDS, "rm1");
+    conf.set(YarnConfiguration.RM_HA_ID, "rm1");
+    conf.set("yarn.resourcemanager.webapp.address.rm1", "localhost:0");
+    ApiServiceClient asc1 = new ApiServiceClient(conf);
+    boolean exceptionCaught = false;
+    String diagnosticsMsg = null;
+    try {
+      String rmWebAddress = asc1.getRMWebAddress();
+    } catch (IOException e){
+      exceptionCaught = true;
+      diagnosticsMsg = e.getMessage();
+    }
+    assertTrue("ApiServiceClient failed to throw exception", exceptionCaught);
+    assertTrue("Exception Message does not match",
+        diagnosticsMsg.contains("Error connecting to localhost:0"));
+  }
+
   @Test
   public void testLaunch() {
     String fileName = "target/test-classes/example-app.json";

+ 2 - 0
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-api/src/test/java/org/apache/hadoop/yarn/service/client/TestSecureApiServiceClient.java

@@ -41,6 +41,7 @@ import org.apache.hadoop.security.SecurityUtil;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.security.SaslRpcServer.QualityOfProtection;
 import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
+import org.apache.hadoop.yarn.conf.YarnConfiguration;
 import org.apache.hadoop.yarn.client.util.YarnClientUtils;
 import org.apache.log4j.Logger;
 import org.eclipse.jetty.server.Server;
@@ -152,6 +153,7 @@ public class TestSecureApiServiceClient extends KerberosSecurityTestcase {
     rmServers.add("localhost:8088");
     testConf.set("yarn.resourcemanager.webapp.address",
         "localhost:8088");
+    testConf.setBoolean(YarnConfiguration.RM_HA_ENABLED, true);
     asc = new ApiServiceClient() {
       @Override
       List<String> getRMHAWebAddresses(Configuration conf) {

+ 1 - 1
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/util/YarnClientUtils.java

@@ -247,7 +247,7 @@ public abstract class YarnClientUtils {
                   StandardCharsets.US_ASCII);
             } catch (GSSException | IllegalAccessException
                 | NoSuchFieldException | ClassNotFoundException e) {
-              LOG.error("Error: {}", e);
+              LOG.error("Error: ", e);
               throw new AuthenticationException(e);
             }
           }