HDDS-1974. Implement OM CancelDelegationToken request to use Cache and DoubleBuffer. (#1308)

This commit is contained in:
Bharat Viswanadham 2019-08-18 10:06:00 -07:00 committed by GitHub
parent 3bba8086e0
commit b83eae7bdb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 237 additions and 29 deletions

View File

@ -287,18 +287,40 @@ public class OzoneDelegationTokenSecretManager
throw new AccessControlException(canceller
+ " is not authorized to cancel the token " + formatTokenId(id));
}
try {
store.removeToken(id);
} catch (IOException e) {
LOG.error("Unable to remove token " + id.getSequenceNumber(), e);
}
TokenInfo info = currentTokens.remove(id);
if (info == null) {
throw new InvalidToken("Token not found " + formatTokenId(id));
// For HA ratis will take care of removal.
// This check will be removed, when HA/Non-HA code is merged.
if (!isRatisEnabled) {
try {
store.removeToken(id);
} catch (IOException e) {
LOG.error("Unable to remove token " + id.getSequenceNumber(), e);
}
TokenInfo info = currentTokens.remove(id);
if (info == null) {
throw new InvalidToken("Token not found " + formatTokenId(id));
}
} else {
// Check whether token is there in-memory map of tokens or not on the
// OM leader.
TokenInfo info = currentTokens.get(id);
if (info == null) {
throw new InvalidToken("Token not found in-memory map of tokens" +
formatTokenId(id));
}
}
return id;
}
/**
* Remove the expired token from in-memory map.
* @param ozoneTokenIdentifier
* @throws IOException
*/
public void removeToken(OzoneTokenIdentifier ozoneTokenIdentifier) {
currentTokens.remove(ozoneTokenIdentifier);
}
@Override
public byte[] retrievePassword(OzoneTokenIdentifier identifier)
throws InvalidToken {

View File

@ -152,6 +152,7 @@ public class OMBucketCreateRequest extends OMClientRequest {
throw new OMException("Volume doesn't exist",
OMException.ResultCodes.VOLUME_NOT_FOUND);
}
//Check if bucket already exists
if (metadataManager.getBucketTable().get(bucketKey) != null) {
LOG.debug("bucket: {} already exists ", bucketName);

View File

@ -0,0 +1,125 @@
/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.ozone.om.request.security;
import com.google.common.base.Optional;
import org.apache.hadoop.ozone.om.OMMetadataManager;
import org.apache.hadoop.ozone.om.OzoneManager;
import org.apache.hadoop.ozone.om.ratis.utils.OzoneManagerDoubleBufferHelper;
import org.apache.hadoop.ozone.om.request.OMClientRequest;
import org.apache.hadoop.ozone.om.response.OMClientResponse;
import org.apache.hadoop.ozone.om.response.security.OMCancelDelegationTokenResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CancelDelegationTokenResponseProto;
import org.apache.hadoop.ozone.protocolPB.OMPBHelper;
import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
import org.apache.hadoop.security.proto.SecurityProtos;
import org.apache.hadoop.security.proto.SecurityProtos.CancelDelegationTokenRequestProto;
import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.utils.db.cache.CacheKey;
import org.apache.hadoop.utils.db.cache.CacheValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
/**
* Handle CancelDelegationToken Request.
*/
public class OMCancelDelegationTokenRequest extends OMClientRequest {
private static final Logger LOG =
LoggerFactory.getLogger(OMGetDelegationTokenRequest.class);
public OMCancelDelegationTokenRequest(OMRequest omRequest) {
super(omRequest);
}
@Override
public OMRequest preExecute(OzoneManager ozoneManager) throws IOException {
// Call OM to cancel token, this does check whether we can cancel token
// or not. This does not remove token from DB/in-memory.
ozoneManager.cancelDelegationToken(getToken());
return super.preExecute(ozoneManager);
}
@Override
public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager,
long transactionLogIndex,
OzoneManagerDoubleBufferHelper ozoneManagerDoubleBufferHelper) {
OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager();
OMClientResponse omClientResponse = null;
OMResponse.Builder omResponse =
OMResponse.newBuilder()
.setCmdType(OzoneManagerProtocolProtos.Type.CancelDelegationToken)
.setStatus(OzoneManagerProtocolProtos.Status.OK)
.setSuccess(true);
OzoneTokenIdentifier ozoneTokenIdentifier = null;
try {
ozoneTokenIdentifier =
OzoneTokenIdentifier.readProtoBuf(getToken().getIdentifier());
// Remove token from in-memory.
ozoneManager.getDelegationTokenMgr().removeToken(ozoneTokenIdentifier);
// Update Cache.
omMetadataManager.getDelegationTokenTable().addCacheEntry(
new CacheKey<>(ozoneTokenIdentifier),
new CacheValue<>(Optional.absent(), transactionLogIndex));
omClientResponse =
new OMCancelDelegationTokenResponse(ozoneTokenIdentifier,
omResponse.setCancelDelegationTokenResponse(
CancelDelegationTokenResponseProto.newBuilder().setResponse(
SecurityProtos.CancelDelegationTokenResponseProto
.newBuilder())).build());
} catch (IOException ex) {
LOG.error("Error in cancel DelegationToken {}", ozoneTokenIdentifier, ex);
omClientResponse = new OMCancelDelegationTokenResponse(null,
createErrorOMResponse(omResponse, ex));
} finally {
if (omClientResponse != null) {
omClientResponse.setFlushFuture(
ozoneManagerDoubleBufferHelper.add(omClientResponse,
transactionLogIndex));
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("Cancelled delegation token: {}", ozoneTokenIdentifier);
}
return omClientResponse;
}
public Token<OzoneTokenIdentifier> getToken() {
CancelDelegationTokenRequestProto cancelDelegationTokenRequest =
getOmRequest().getCancelDelegationTokenRequest();
return OMPBHelper.convertToDelegationToken(
cancelDelegationTokenRequest.getToken());
}
}

View File

@ -25,7 +25,7 @@ import org.apache.hadoop.ozone.om.OzoneManager;
import org.apache.hadoop.ozone.om.ratis.utils.OzoneManagerDoubleBufferHelper;
import org.apache.hadoop.ozone.om.request.OMClientRequest;
import org.apache.hadoop.ozone.om.response.OMClientResponse;
import org.apache.hadoop.ozone.om.response.security.OMDelegationTokenResponse;
import org.apache.hadoop.ozone.om.response.security.OMGetDelegationTokenResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetDelegationTokenResponseProto;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest;
@ -65,13 +65,13 @@ public class OMGetDelegationTokenRequest extends OMClientRequest {
.getDelegationToken(new Text(getDelegationTokenRequest.getRenewer()));
// Client issues GetDelegationToken request, when received by OM leader will
// it generate Token. Original GetDelegationToken request is converted to
// UpdateGetDelegationToken request with the generated token information.
// This updated request will be submitted to Ratis. In this way delegation
// token created by leader, will be replicated across all OMs.
// And also original GetDelegationToken request from client does not need
// any proto changes.
// Client issues GetDelegationToken request, when received by OM leader
// it will generate a token. Original GetDelegationToken request is
// converted to UpdateGetDelegationToken request with the generated token
// information. This updated request will be submitted to Ratis. In this
// way delegation token created by leader, will be replicated across all
// OMs. With this approach, original GetDelegationToken request from
// client does not need any proto changes.
// Create UpdateGetDelegationTokenRequest with token response.
OMRequest.Builder omRequest = OMRequest.newBuilder()
@ -129,14 +129,14 @@ public class OMGetDelegationTokenRequest extends OMClientRequest {
new CacheValue<>(Optional.of(renewTime), transactionLogIndex));
omClientResponse =
new OMDelegationTokenResponse(ozoneTokenIdentifier, renewTime,
new OMGetDelegationTokenResponse(ozoneTokenIdentifier, renewTime,
omResponse.setGetDelegationTokenResponse(
updateGetDelegationTokenRequest
.getGetDelegationTokenResponse()).build());
} catch (IOException ex) {
LOG.error("Error in Updating DelegationToken {} to DB",
LOG.error("Error in Updating DelegationToken {}",
ozoneTokenIdentifierToken, ex);
omClientResponse = new OMDelegationTokenResponse(null, -1L,
omClientResponse = new OMGetDelegationTokenResponse(null, -1L,
createErrorOMResponse(omResponse, ex));
} finally {
if (omClientResponse != null) {
@ -147,7 +147,7 @@ public class OMGetDelegationTokenRequest extends OMClientRequest {
}
if (LOG.isDebugEnabled()) {
LOG.debug("Updated delegation token to OM DB: {}",
LOG.debug("Updated delegation token in-memory map: {}",
ozoneTokenIdentifierToken);
}

View File

@ -24,30 +24,32 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
import org.apache.hadoop.utils.db.BatchOperation;
import org.apache.hadoop.utils.db.Table;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
/**
* Handle response for DelegationToken request.
* Handle response for CancelDelegationToken request.
*/
public class OMDelegationTokenResponse extends OMClientResponse {
public class OMCancelDelegationTokenResponse extends OMClientResponse {
private OzoneTokenIdentifier ozoneTokenIdentifier;
private long renewTime;
public OMDelegationTokenResponse(OzoneTokenIdentifier ozoneTokenIdentifier,
long renewTime, OMResponse omResponse) {
public OMCancelDelegationTokenResponse(
@Nullable OzoneTokenIdentifier ozoneTokenIdentifier,
@Nonnull OMResponse omResponse) {
super(omResponse);
this.ozoneTokenIdentifier = ozoneTokenIdentifier;
this.renewTime = renewTime;
}
@Override
public void addToDBBatch(OMMetadataManager omMetadataManager,
BatchOperation batchOperation) throws IOException {
Table table = omMetadataManager.getDelegationTokenTable();
if (getOMResponse().getStatus() == OzoneManagerProtocolProtos.Status.OK) {
omMetadataManager.getDelegationTokenTable().putWithBatch(batchOperation,
ozoneTokenIdentifier, renewTime);
table.deleteWithBatch(batchOperation, ozoneTokenIdentifier);
}
}
}

View File

@ -0,0 +1,58 @@
/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.ozone.om.response.security;
import org.apache.hadoop.ozone.om.OMMetadataManager;
import org.apache.hadoop.ozone.om.response.OMClientResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
import org.apache.hadoop.utils.db.BatchOperation;
import org.apache.hadoop.utils.db.Table;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
/**
* Handle response for GetDelegationToken request.
*/
public class OMGetDelegationTokenResponse extends OMClientResponse {
private OzoneTokenIdentifier ozoneTokenIdentifier;
private long renewTime = -1L;
public OMGetDelegationTokenResponse(
@Nullable OzoneTokenIdentifier ozoneTokenIdentifier,
long renewTime, @Nonnull OMResponse omResponse) {
super(omResponse);
this.ozoneTokenIdentifier = ozoneTokenIdentifier;
this.renewTime = renewTime;
}
@Override
public void addToDBBatch(OMMetadataManager omMetadataManager,
BatchOperation batchOperation) throws IOException {
Table table = omMetadataManager.getDelegationTokenTable();
if (getOMResponse().getStatus() == OzoneManagerProtocolProtos.Status.OK) {
table.putWithBatch(batchOperation, ozoneTokenIdentifier, renewTime);
}
}
}