diff --git hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java index d892c5d..ad73c12 100644 --- hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java +++ hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java @@ -169,16 +169,19 @@ protected void removeStoredMasterKey(DelegationKey key) { } // RM - protected void storeNewToken(TokenIdent ident, long renewDate) { - return; + protected boolean storeNewToken(TokenIdent ident, long renewDate, + DelegationTokenInformation info) { + return true; } - // RM - protected void removeStoredToken(TokenIdent ident) throws IOException { + // RM + protected boolean removeStoredToken(TokenIdent ident) throws IOException { + return true; } + // RM - protected void updateStoredToken(TokenIdent ident, long renewDate) { - return; + protected boolean updateStoredToken(TokenIdent ident, long renewDate) { + return true; } /** @@ -283,10 +286,14 @@ private synchronized void removeExpiredKeys() { identifier.setMasterKeyId(currentId); identifier.setSequenceNumber(sequenceNum); LOG.info("Creating password for identifier: " + identifier); - byte[] password = createPassword(identifier.getBytes(), currentKey.getKey()); - storeNewToken(identifier, now + tokenRenewInterval); - currentTokens.put(identifier, new DelegationTokenInformation(now - + tokenRenewInterval, password, getTrackingIdIfEnabled(identifier))); + byte[] password = + createPassword(identifier.getBytes(), currentKey.getKey()); + DelegationTokenInformation info = + new DelegationTokenInformation(now + tokenRenewInterval, password, + getTrackingIdIfEnabled(identifier)); + if (storeNewToken(identifier, now + tokenRenewInterval)) { + currentTokens.put(identifier, info); + } return password; } @@ -397,8 +404,8 @@ public synchronized long renewToken(Token token, if (currentTokens.get(id) == null) { throw new InvalidToken("Renewal request for unknown token"); } - currentTokens.put(id, info); updateStoredToken(id, renewTime); + currentTokens.put(id, info); return renewTime; } @@ -430,11 +437,13 @@ public synchronized TokenIdent cancelToken(Token token, + " is not authorized to cancel the token"); } DelegationTokenInformation info = null; - info = currentTokens.remove(id); + info = currentTokens.get(id); if (info == null) { throw new InvalidToken("Token not found"); } - removeStoredToken(id); + if (removeStoredToken(id)) { + currentTokens.remove(id); + } return id; } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/RMStateStore.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/RMStateStore.java index 2f4b896..b557318 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/RMStateStore.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/recovery/RMStateStore.java @@ -21,6 +21,8 @@ import java.nio.ByteBuffer; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Set; diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMDelegationTokenOperationEvent.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMDelegationTokenOperationEvent.java new file mode 100644 index 0000000..8c2768a --- /dev/null +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMDelegationTokenOperationEvent.java @@ -0,0 +1,46 @@ +/** + * 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.resourcemanager.security; + +import org.apache.hadoop.yarn.event.AbstractEvent; +import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier; + + +public class RMDelegationTokenOperationEvent extends + AbstractEvent { + + private RMDelegationTokenIdentifier id; + private long renewDate; + + public RMDelegationTokenOperationEvent( + RMDelegationTokenOperationEventType type, RMDelegationTokenIdentifier id, + long renewDate) { + super(type); + this.id = id; + this.renewDate = renewDate; + } + + public RMDelegationTokenIdentifier getRMDelegationTokenIdentifier() { + return id; + } + + public long getRenewDate() { + return renewDate; + } +} \ No newline at end of file diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMDelegationTokenOperationEventType.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMDelegationTokenOperationEventType.java new file mode 100644 index 0000000..c2dc389 --- /dev/null +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMDelegationTokenOperationEventType.java @@ -0,0 +1,25 @@ +/** + * 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.resourcemanager.security; + +public enum RMDelegationTokenOperationEventType { + STORE_TOKEN, + RENEW_TOKEN, + REMOVE_TOKEN +} diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMDelegationTokenSecretManager.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMDelegationTokenSecretManager.java index 23939de..2d5033d 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMDelegationTokenSecretManager.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMDelegationTokenSecretManager.java @@ -21,6 +21,8 @@ import java.io.IOException; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Set; @@ -32,6 +34,8 @@ import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager; import org.apache.hadoop.security.token.delegation.DelegationKey; import org.apache.hadoop.util.ExitUtil; +import org.apache.hadoop.yarn.event.AsyncDispatcher; +import org.apache.hadoop.yarn.event.EventHandler; import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier; import org.apache.hadoop.yarn.server.resourcemanager.RMContext; import org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore.RMState; @@ -53,7 +57,9 @@ .getLog(RMDelegationTokenSecretManager.class); protected final RMContext rmContext; - + private AsyncDispatcher dispatcher; + private LinkedHashMap> rmDelegationTokenOperationStatusMap; + /** * Create a secret manager * @param delegationKeyUpdateInterval the number of seconds for rolling new @@ -71,6 +77,12 @@ public RMDelegationTokenSecretManager(long delegationKeyUpdateInterval, RMContext rmContext) { super(delegationKeyUpdateInterval, delegationTokenMaxLifetime, delegationTokenRenewInterval, delegationTokenRemoverScanInterval); + this.dispatcher = new AsyncDispatcher(); + this.dispatcher.init(rmContext.getClientRMService().getConfig()); + this.dispatcher.start(); + this.rmDelegationTokenOperationStatusMap = + new LinkedHashMap>( + 16, 0.75f, true); this.rmContext = rmContext; } @@ -136,16 +148,7 @@ protected void updateStoredToken(RMDelegationTokenIdentifier id, @Override protected void removeStoredToken(RMDelegationTokenIdentifier ident) throws IOException { - try { - LOG.info("removing RMDelegation token with sequence number: " - + ident.getSequenceNumber()); - rmContext.getStateStore().removeRMDelegationToken(ident, - delegationTokenSequenceNumber); - } catch (Exception e) { - LOG.error("Error in removing RMDelegationToken with sequence number: " - + ident.getSequenceNumber()); - ExitUtil.terminate(1, e); - } + } @Private @@ -195,4 +198,105 @@ public void recover(RMState rmState) throws Exception { addPersistedDelegationToken(entry.getKey(), entry.getValue()); } } + + /** + * EventHandler implementation which forward events to the + * RMDelegationTokenSecretManaer. This hides the EventHandle methods of + * the store from its public interface. + */ + private final class ForwardingEventHandler + implements EventHandler { + + @Override + public void handle(RMDelegationTokenOperationEvent event) { + handleRMDelegationTokenOperationEvent(event); + } + } + + private void handleRMDelegationTokenOperationEvent( + RMDelegationTokenOperationEvent event) { + switch (event.getType()) { + case REMOVE_TOKEN : + RMDelegationTokenIdentifier id = + event.getRMDelegationTokenIdentifier(); + try { + LOG.info("removing RMDelegation token with sequence number: " + + id.getSequenceNumber()); + rmContext.getStateStore().removeRMDelegationToken(id, + delegationTokenSequenceNumber); + RMDelegationTokenOperationStatus status = + new RMDelegationTokenOperationStatus( + RMDelegationTokenOperation.CANCEL, + RMDelegationTokenOperationState.SUCCEEDED, "", + System.currentTimeMillis()); + updateDelegationTokenOperationStatus(id, status); + } catch (Throwable t) { + LOG.error("Error in removing RMDelegationToken with sequence number: " + + id.getSequenceNumber()); + } + } + } +} + + +/* For RMDelegationToken operation tracking */ + +enum RMDelegationTokenOperation { + GET, // returns new token + RENEW, // renews token + CANCEL // cancels token +} + +enum RMDelegationTokenOperationState { + PENDING, // operation in progress + FAILED, // operation failed + SUCCEEDED // operation succeeded } + +class RMDelegationTokenOperationStatus { + private RMDelegationTokenOperation operation; + private RMDelegationTokenOperationState state; + private String failureMessage; + private long finishTime; + + public RMDelegationTokenOperationStatus(RMDelegationTokenOperation operation, + RMDelegationTokenOperationState state, String failureMessage, + long finishTime) { + this.operation = operation; + this.state = state; + this.failureMessage = failureMessage; + this.finishTime = finishTime; + } + + public RMDelegationTokenOperation getOperation() { + return operation; + } + + public void setOperation(RMDelegationTokenOperation operation) { + this.operation = operation; + } + + public RMDelegationTokenOperationState getState() { + return state; + } + + public void setState(RMDelegationTokenOperationState state) { + this.state = state; + } + + public String getFailureMessage() { + return failureMessage; + } + + public void setFailureMessage(String failureMessage) { + this.failureMessage = failureMessage; + } + + public long getFinishTime() { + return finishTime; + } + + public void setFinishTime(long finishTime) { + this.finishTime = finishTime; + } +} \ No newline at end of file