Author: vinodkv
Date: Mon Sep 9 21:28:18 2013
New Revision: 1521295
URL: http://svn.apache.org/r1521295
Log:
YARN-1152. Fixed a bug in ResourceManager that was causing clients to get
invalid client token key errors when an appliation is about to finish.
Contributed by Jason Lowe.
svn merge --ignore-ancestry -c 1521292 ../../trunk/
Modified:
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/CHANGES.txt
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/RMAppImpl.java
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttempt.java
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttemptImpl.java
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/TestRMAppTransitions.java
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/TestRMAppAttemptTransitions.java
Modified: hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/CHANGES.txt
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/CHANGES.txt?rev=1521295&r1=1521294&r2=1521295&view=diff
==============================================================================
--- hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/CHANGES.txt
(original)
+++ hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/CHANGES.txt Mon
Sep 9 21:28:18 2013
@@ -135,6 +135,10 @@ Release 2.1.1-beta - UNRELEASED
YARN-1144. Unmanaged AMs registering a tracking URI should not be
proxy-fied. (tucu)
+ YARN-1152. Fixed a bug in ResourceManager that was causing clients to get
+ invalid client token key errors when an appliation is about to finish.
+ (Jason Lowe via vinodkv)
+
Release 2.1.0-beta - 2013-08-22
INCOMPATIBLE CHANGES
Modified:
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/RMAppImpl.java
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/RMAppImpl.java?rev=1521295&r1=1521294&r2=1521295&view=diff
==============================================================================
---
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/RMAppImpl.java
(original)
+++
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/RMAppImpl.java
Mon Sep 9 21:28:18 2013
@@ -432,18 +432,18 @@ public class RMAppImpl implements RMApp,
currentApplicationAttemptId = this.currentAttempt.getAppAttemptId();
trackingUrl = this.currentAttempt.getTrackingUrl();
origTrackingUrl = this.currentAttempt.getOriginalTrackingUrl();
- if (UserGroupInformation.isSecurityEnabled()
- && clientUserName != null) {
+ if (UserGroupInformation.isSecurityEnabled()) {
+ // get a token so the client can communicate with the app attempt
+ // NOTE: token may be unavailable if the attempt is not running
Token<ClientToAMTokenIdentifier> attemptClientToAMToken =
- new Token<ClientToAMTokenIdentifier>(
- new ClientToAMTokenIdentifier(
- currentApplicationAttemptId, clientUserName),
- rmContext.getClientToAMTokenSecretManager());
- clientToAMToken = BuilderUtils.newClientToAMToken(
- attemptClientToAMToken.getIdentifier(),
- attemptClientToAMToken.getKind().toString(),
- attemptClientToAMToken.getPassword(),
- attemptClientToAMToken.getService().toString());
+ this.currentAttempt.createClientToken(clientUserName);
+ if (attemptClientToAMToken != null) {
+ clientToAMToken = BuilderUtils.newClientToAMToken(
+ attemptClientToAMToken.getIdentifier(),
+ attemptClientToAMToken.getKind().toString(),
+ attemptClientToAMToken.getPassword(),
+ attemptClientToAMToken.getService().toString());
+ }
}
host = this.currentAttempt.getHost();
rpcPort = this.currentAttempt.getRpcPort();
Modified:
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttempt.java
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttempt.java?rev=1521295&r1=1521294&r2=1521295&view=diff
==============================================================================
---
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttempt.java
(original)
+++
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttempt.java
Mon Sep 9 21:28:18 2013
@@ -34,6 +34,7 @@ import org.apache.hadoop.yarn.api.record
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.event.EventHandler;
import org.apache.hadoop.yarn.security.AMRMTokenIdentifier;
+import org.apache.hadoop.yarn.security.client.ClientToAMTokenIdentifier;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
/**
@@ -156,6 +157,13 @@ public interface RMAppAttempt extends Ev
SecretKey getClientTokenMasterKey();
/**
+ * Create a token for authenticating a client connection to the app attempt
+ * @param clientName the name of the client requesting the token
+ * @return the token or null if the attempt is not running
+ */
+ Token<ClientToAMTokenIdentifier> createClientToken(String clientName);
+
+ /**
* Get application container and resource usage information.
* @return an ApplicationResourceUsageReport object.
*/
Modified:
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttemptImpl.java
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttemptImpl.java?rev=1521295&r1=1521294&r2=1521295&view=diff
==============================================================================
---
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttemptImpl.java
(original)
+++
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttemptImpl.java
Mon Sep 9 21:28:18 2013
@@ -61,6 +61,7 @@ import org.apache.hadoop.yarn.event.Even
import org.apache.hadoop.yarn.factories.RecordFactory;
import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
import org.apache.hadoop.yarn.security.AMRMTokenIdentifier;
+import org.apache.hadoop.yarn.security.client.ClientToAMTokenIdentifier;
import org.apache.hadoop.yarn.server.resourcemanager.ApplicationMasterService;
import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
import
org.apache.hadoop.yarn.server.resourcemanager.amlauncher.AMLauncherEvent;
@@ -89,6 +90,7 @@ import org.apache.hadoop.yarn.server.res
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.YarnScheduler;
import
org.apache.hadoop.yarn.server.resourcemanager.scheduler.event.AppAddedSchedulerEvent;
import
org.apache.hadoop.yarn.server.resourcemanager.scheduler.event.AppRemovedSchedulerEvent;
+import
org.apache.hadoop.yarn.server.resourcemanager.security.ClientToAMTokenSecretManagerInRM;
import org.apache.hadoop.yarn.server.utils.BuilderUtils;
import org.apache.hadoop.yarn.server.webproxy.ProxyUriUtils;
import org.apache.hadoop.yarn.state.InvalidStateTransitonException;
@@ -509,6 +511,26 @@ public class RMAppAttemptImpl implements
}
@Override
+ public Token<ClientToAMTokenIdentifier> createClientToken(String client) {
+ this.readLock.lock();
+
+ try {
+ Token<ClientToAMTokenIdentifier> token = null;
+ ClientToAMTokenSecretManagerInRM secretMgr =
+ this.rmContext.getClientToAMTokenSecretManager();
+ if (client != null &&
+ secretMgr.getMasterKey(this.applicationAttemptId) != null) {
+ token = new Token<ClientToAMTokenIdentifier>(
+ new ClientToAMTokenIdentifier(this.applicationAttemptId, client),
+ secretMgr);
+ }
+ return token;
+ } finally {
+ this.readLock.unlock();
+ }
+ }
+
+ @Override
public String getDiagnostics() {
this.readLock.lock();
Modified:
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/TestRMAppTransitions.java
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/TestRMAppTransitions.java?rev=1521295&r1=1521294&r2=1521295&view=diff
==============================================================================
---
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/TestRMAppTransitions.java
(original)
+++
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/TestRMAppTransitions.java
Mon Sep 9 21:28:18 2013
@@ -19,14 +19,20 @@
package org.apache.hadoop.yarn.server.resourcemanager.rmapp;
import static org.mockito.Mockito.mock;
+import static org.junit.Assume.assumeTrue;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
import junit.framework.Assert;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.security.SecurityUtil;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
import org.apache.hadoop.yarn.MockApps;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.ApplicationReport;
@@ -57,11 +63,16 @@ import org.apache.hadoop.yarn.server.res
import
org.apache.hadoop.yarn.server.resourcemanager.security.NMTokenSecretManagerInRM;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+@RunWith(value = Parameterized.class)
public class TestRMAppTransitions {
static final Log LOG = LogFactory.getLog(TestRMAppTransitions.class);
+ private boolean isSecurityEnabled;
+ private Configuration conf;
private RMContext rmContext;
private static int maxAppAttempts =
YarnConfiguration.DEFAULT_RM_AM_MAX_ATTEMPTS;
@@ -132,10 +143,29 @@ public class TestRMAppTransitions {
public void handle(SchedulerEvent event) {
}
}
+
+ @Parameterized.Parameters
+ public static Collection<Object[]> getTestParameters() {
+ return Arrays.asList(new Object[][] {
+ { Boolean.FALSE },
+ { Boolean.TRUE }
+ });
+ }
+
+ public TestRMAppTransitions(boolean isSecurityEnabled) {
+ this.isSecurityEnabled = isSecurityEnabled;
+ }
@Before
public void setUp() throws Exception {
- Configuration conf = new Configuration();
+ conf = new YarnConfiguration();
+ AuthenticationMethod authMethod = AuthenticationMethod.SIMPLE;
+ if (isSecurityEnabled) {
+ authMethod = AuthenticationMethod.KERBEROS;
+ }
+ SecurityUtil.setAuthenticationMethod(authMethod, conf);
+ UserGroupInformation.setConfiguration(conf);
+
rmDispatcher = new DrainDispatcher();
ContainerAllocationExpirer containerAllocationExpirer =
mock(ContainerAllocationExpirer.class);
@@ -171,7 +201,6 @@ public class TestRMAppTransitions {
String user = MockApps.newUserName();
String name = MockApps.newAppName();
String queue = MockApps.newQueue();
- Configuration conf = new YarnConfiguration();
// ensure max application attempts set to known value
conf.setInt(YarnConfiguration.RM_AM_MAX_ATTEMPTS, maxAppAttempts);
YarnScheduler scheduler = mock(YarnScheduler.class);
@@ -191,6 +220,8 @@ public class TestRMAppTransitions {
System.currentTimeMillis(), "YARN");
testAppStartState(applicationId, user, name, queue, application);
+ this.rmContext.getRMApps().putIfAbsent(application.getApplicationId(),
+ application);
return application;
}
@@ -488,8 +519,6 @@ public class TestRMAppTransitions {
// SUBMITTED => KILLED event RMAppEventType.KILL
RMAppEvent event = new RMAppEvent(application.getApplicationId(),
RMAppEventType.KILL);
- this.rmContext.getRMApps().putIfAbsent(application.getApplicationId(),
- application);
application.handle(event);
rmDispatcher.await();
assertKilled(application);
@@ -535,8 +564,6 @@ public class TestRMAppTransitions {
// ACCEPTED => KILLED event RMAppEventType.KILL
RMAppEvent event = new RMAppEvent(application.getApplicationId(),
RMAppEventType.KILL);
- this.rmContext.getRMApps().putIfAbsent(application.getApplicationId(),
- application);
application.handle(event);
rmDispatcher.await();
assertKilled(application);
@@ -731,4 +758,33 @@ public class TestRMAppTransitions {
report = app.createAndGetApplicationReport("clientuser", true);
Assert.assertNotNull(report.getApplicationResourceUsageReport());
}
+
+ @Test
+ public void testClientTokens() throws Exception {
+ assumeTrue(isSecurityEnabled);
+
+ RMApp app = createNewTestApp(null);
+ assertAppState(RMAppState.NEW, app);
+ ApplicationReport report = app.createAndGetApplicationReport(null, true);
+ Assert.assertNull(report.getClientToAMToken());
+ report = app.createAndGetApplicationReport("clientuser", true);
+ Assert.assertNull(report.getClientToAMToken());
+
+ app = testCreateAppRunning(null);
+ rmDispatcher.await();
+ assertAppState(RMAppState.RUNNING, app);
+ report = app.createAndGetApplicationReport(null, true);
+ Assert.assertNull(report.getClientToAMToken());
+ report = app.createAndGetApplicationReport("clientuser", true);
+ Assert.assertNotNull(report.getClientToAMToken());
+
+ // kill the app attempt and verify client token is unavailable
+ app.handle(new RMAppEvent(app.getApplicationId(), RMAppEventType.KILL));
+ rmDispatcher.await();
+ assertAppAndAttemptKilled(app);
+ report = app.createAndGetApplicationReport(null, true);
+ Assert.assertNull(report.getClientToAMToken());
+ report = app.createAndGetApplicationReport("clientuser", true);
+ Assert.assertNull(report.getClientToAMToken());
+ }
}
Modified:
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/TestRMAppAttemptTransitions.java
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/TestRMAppAttemptTransitions.java?rev=1521295&r1=1521294&r2=1521295&view=diff
==============================================================================
---
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/TestRMAppAttemptTransitions.java
(original)
+++
hadoop/common/branches/branch-2.1-beta/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/TestRMAppAttemptTransitions.java
Mon Sep 9 21:28:18 2013
@@ -30,13 +30,17 @@ import static org.mockito.Mockito.verify
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.spy;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
import org.apache.hadoop.yarn.MockApps;
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
import org.apache.hadoop.yarn.api.records.ApplicationId;
@@ -85,7 +89,10 @@ import org.apache.hadoop.yarn.server.res
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+@RunWith(value = Parameterized.class)
public class TestRMAppAttemptTransitions {
private static final Log LOG =
@@ -95,6 +102,7 @@ public class TestRMAppAttemptTransitions
private static final String RM_WEBAPP_ADDR =
YarnConfiguration.getRMWebAppHostAndPort(new Configuration());
+ private boolean isSecurityEnabled;
private RMContext rmContext;
private YarnScheduler scheduler;
private ApplicationMasterService masterService;
@@ -162,8 +170,26 @@ public class TestRMAppAttemptTransitions
private ApplicationSubmissionContext submissionContext = null;
private boolean unmanagedAM;
+ @Parameterized.Parameters
+ public static Collection<Object[]> getTestParameters() {
+ return Arrays.asList(new Object[][] {
+ { Boolean.FALSE },
+ { Boolean.TRUE }
+ });
+ }
+
+ public TestRMAppAttemptTransitions(Boolean isSecurityEnabled) {
+ this.isSecurityEnabled = isSecurityEnabled;
+ }
+
@Before
public void setUp() throws Exception {
+ AuthenticationMethod authMethod = AuthenticationMethod.SIMPLE;
+ if (isSecurityEnabled) {
+ authMethod = AuthenticationMethod.KERBEROS;
+ }
+ SecurityUtil.setAuthenticationMethod(authMethod, conf);
+ UserGroupInformation.setConfiguration(conf);
InlineDispatcher rmDispatcher = new InlineDispatcher();
ContainerAllocationExpirer containerAllocationExpirer =
@@ -270,7 +296,9 @@ public class TestRMAppAttemptTransitions
if (UserGroupInformation.isSecurityEnabled()) {
verify(clientToAMTokenManager).registerApplication(
applicationAttempt.getAppAttemptId());
+ assertNotNull(applicationAttempt.createClientToken("some client"));
}
+ assertNull(applicationAttempt.createClientToken(null));
assertNotNull(applicationAttempt.getAMRMToken());
// Check events
verify(masterService).
@@ -883,6 +911,9 @@ public class TestRMAppAttemptTransitions
verify(amRMTokenManager,
times(count)).applicationMasterFinished(appAttemptId);
if (UserGroupInformation.isSecurityEnabled()) {
verify(clientToAMTokenManager,
times(count)).unRegisterApplication(appAttemptId);
+ if (count > 0) {
+ assertNull(applicationAttempt.createClientToken("client"));
+ }
}
}
}