Skip to content

Commit b83eae7

Browse files
HDDS-1974. Implement OM CancelDelegationToken request to use Cache and DoubleBuffer. (#1308)
1 parent 3bba808 commit b83eae7

File tree

6 files changed

+237
-29
lines changed

6 files changed

+237
-29
lines changed

hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/OzoneDelegationTokenSecretManager.java

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -287,18 +287,40 @@ public OzoneTokenIdentifier cancelToken(Token<OzoneTokenIdentifier> token,
287287
throw new AccessControlException(canceller
288288
+ " is not authorized to cancel the token " + formatTokenId(id));
289289
}
290-
try {
291-
store.removeToken(id);
292-
} catch (IOException e) {
293-
LOG.error("Unable to remove token " + id.getSequenceNumber(), e);
294-
}
295-
TokenInfo info = currentTokens.remove(id);
296-
if (info == null) {
297-
throw new InvalidToken("Token not found " + formatTokenId(id));
290+
291+
// For HA ratis will take care of removal.
292+
// This check will be removed, when HA/Non-HA code is merged.
293+
if (!isRatisEnabled) {
294+
try {
295+
store.removeToken(id);
296+
} catch (IOException e) {
297+
LOG.error("Unable to remove token " + id.getSequenceNumber(), e);
298+
}
299+
TokenInfo info = currentTokens.remove(id);
300+
if (info == null) {
301+
throw new InvalidToken("Token not found " + formatTokenId(id));
302+
}
303+
} else {
304+
// Check whether token is there in-memory map of tokens or not on the
305+
// OM leader.
306+
TokenInfo info = currentTokens.get(id);
307+
if (info == null) {
308+
throw new InvalidToken("Token not found in-memory map of tokens" +
309+
formatTokenId(id));
310+
}
298311
}
299312
return id;
300313
}
301314

315+
/**
316+
* Remove the expired token from in-memory map.
317+
* @param ozoneTokenIdentifier
318+
* @throws IOException
319+
*/
320+
public void removeToken(OzoneTokenIdentifier ozoneTokenIdentifier) {
321+
currentTokens.remove(ozoneTokenIdentifier);
322+
}
323+
302324
@Override
303325
public byte[] retrievePassword(OzoneTokenIdentifier identifier)
304326
throws InvalidToken {

hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager,
152152
throw new OMException("Volume doesn't exist",
153153
OMException.ResultCodes.VOLUME_NOT_FOUND);
154154
}
155+
155156
//Check if bucket already exists
156157
if (metadataManager.getBucketTable().get(bucketKey) != null) {
157158
LOG.debug("bucket: {} already exists ", bucketName);
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
* <p>
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
* <p>
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.hadoop.ozone.om.request.security;
20+
21+
import com.google.common.base.Optional;
22+
import org.apache.hadoop.ozone.om.OMMetadataManager;
23+
import org.apache.hadoop.ozone.om.OzoneManager;
24+
import org.apache.hadoop.ozone.om.ratis.utils.OzoneManagerDoubleBufferHelper;
25+
import org.apache.hadoop.ozone.om.request.OMClientRequest;
26+
import org.apache.hadoop.ozone.om.response.OMClientResponse;
27+
import org.apache.hadoop.ozone.om.response.security.OMCancelDelegationTokenResponse;
28+
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
29+
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest;
30+
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
31+
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CancelDelegationTokenResponseProto;
32+
import org.apache.hadoop.ozone.protocolPB.OMPBHelper;
33+
import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
34+
import org.apache.hadoop.security.proto.SecurityProtos;
35+
import org.apache.hadoop.security.proto.SecurityProtos.CancelDelegationTokenRequestProto;
36+
import org.apache.hadoop.security.token.Token;
37+
import org.apache.hadoop.utils.db.cache.CacheKey;
38+
import org.apache.hadoop.utils.db.cache.CacheValue;
39+
import org.slf4j.Logger;
40+
import org.slf4j.LoggerFactory;
41+
42+
import java.io.IOException;
43+
44+
/**
45+
* Handle CancelDelegationToken Request.
46+
*/
47+
public class OMCancelDelegationTokenRequest extends OMClientRequest {
48+
49+
private static final Logger LOG =
50+
LoggerFactory.getLogger(OMGetDelegationTokenRequest.class);
51+
52+
public OMCancelDelegationTokenRequest(OMRequest omRequest) {
53+
super(omRequest);
54+
}
55+
56+
@Override
57+
public OMRequest preExecute(OzoneManager ozoneManager) throws IOException {
58+
59+
// Call OM to cancel token, this does check whether we can cancel token
60+
// or not. This does not remove token from DB/in-memory.
61+
ozoneManager.cancelDelegationToken(getToken());
62+
63+
return super.preExecute(ozoneManager);
64+
}
65+
66+
@Override
67+
public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager,
68+
long transactionLogIndex,
69+
OzoneManagerDoubleBufferHelper ozoneManagerDoubleBufferHelper) {
70+
71+
OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager();
72+
73+
OMClientResponse omClientResponse = null;
74+
OMResponse.Builder omResponse =
75+
OMResponse.newBuilder()
76+
.setCmdType(OzoneManagerProtocolProtos.Type.CancelDelegationToken)
77+
.setStatus(OzoneManagerProtocolProtos.Status.OK)
78+
.setSuccess(true);
79+
OzoneTokenIdentifier ozoneTokenIdentifier = null;
80+
try {
81+
ozoneTokenIdentifier =
82+
OzoneTokenIdentifier.readProtoBuf(getToken().getIdentifier());
83+
84+
// Remove token from in-memory.
85+
ozoneManager.getDelegationTokenMgr().removeToken(ozoneTokenIdentifier);
86+
87+
// Update Cache.
88+
omMetadataManager.getDelegationTokenTable().addCacheEntry(
89+
new CacheKey<>(ozoneTokenIdentifier),
90+
new CacheValue<>(Optional.absent(), transactionLogIndex));
91+
92+
omClientResponse =
93+
new OMCancelDelegationTokenResponse(ozoneTokenIdentifier,
94+
omResponse.setCancelDelegationTokenResponse(
95+
CancelDelegationTokenResponseProto.newBuilder().setResponse(
96+
SecurityProtos.CancelDelegationTokenResponseProto
97+
.newBuilder())).build());
98+
} catch (IOException ex) {
99+
LOG.error("Error in cancel DelegationToken {}", ozoneTokenIdentifier, ex);
100+
omClientResponse = new OMCancelDelegationTokenResponse(null,
101+
createErrorOMResponse(omResponse, ex));
102+
} finally {
103+
if (omClientResponse != null) {
104+
omClientResponse.setFlushFuture(
105+
ozoneManagerDoubleBufferHelper.add(omClientResponse,
106+
transactionLogIndex));
107+
}
108+
}
109+
110+
if (LOG.isDebugEnabled()) {
111+
LOG.debug("Cancelled delegation token: {}", ozoneTokenIdentifier);
112+
}
113+
114+
return omClientResponse;
115+
}
116+
117+
118+
public Token<OzoneTokenIdentifier> getToken() {
119+
CancelDelegationTokenRequestProto cancelDelegationTokenRequest =
120+
getOmRequest().getCancelDelegationTokenRequest();
121+
122+
return OMPBHelper.convertToDelegationToken(
123+
cancelDelegationTokenRequest.getToken());
124+
}
125+
}

hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/security/OMGetDelegationTokenRequest.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import org.apache.hadoop.ozone.om.ratis.utils.OzoneManagerDoubleBufferHelper;
2626
import org.apache.hadoop.ozone.om.request.OMClientRequest;
2727
import org.apache.hadoop.ozone.om.response.OMClientResponse;
28-
import org.apache.hadoop.ozone.om.response.security.OMDelegationTokenResponse;
28+
import org.apache.hadoop.ozone.om.response.security.OMGetDelegationTokenResponse;
2929
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
3030
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetDelegationTokenResponseProto;
3131
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest;
@@ -65,13 +65,13 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws IOException {
6565
.getDelegationToken(new Text(getDelegationTokenRequest.getRenewer()));
6666

6767

68-
// Client issues GetDelegationToken request, when received by OM leader will
69-
// it generate Token. Original GetDelegationToken request is converted to
70-
// UpdateGetDelegationToken request with the generated token information.
71-
// This updated request will be submitted to Ratis. In this way delegation
72-
// token created by leader, will be replicated across all OMs.
73-
// And also original GetDelegationToken request from client does not need
74-
// any proto changes.
68+
// Client issues GetDelegationToken request, when received by OM leader
69+
// it will generate a token. Original GetDelegationToken request is
70+
// converted to UpdateGetDelegationToken request with the generated token
71+
// information. This updated request will be submitted to Ratis. In this
72+
// way delegation token created by leader, will be replicated across all
73+
// OMs. With this approach, original GetDelegationToken request from
74+
// client does not need any proto changes.
7575

7676
// Create UpdateGetDelegationTokenRequest with token response.
7777
OMRequest.Builder omRequest = OMRequest.newBuilder()
@@ -129,14 +129,14 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager,
129129
new CacheValue<>(Optional.of(renewTime), transactionLogIndex));
130130

131131
omClientResponse =
132-
new OMDelegationTokenResponse(ozoneTokenIdentifier, renewTime,
132+
new OMGetDelegationTokenResponse(ozoneTokenIdentifier, renewTime,
133133
omResponse.setGetDelegationTokenResponse(
134134
updateGetDelegationTokenRequest
135135
.getGetDelegationTokenResponse()).build());
136136
} catch (IOException ex) {
137-
LOG.error("Error in Updating DelegationToken {} to DB",
137+
LOG.error("Error in Updating DelegationToken {}",
138138
ozoneTokenIdentifierToken, ex);
139-
omClientResponse = new OMDelegationTokenResponse(null, -1L,
139+
omClientResponse = new OMGetDelegationTokenResponse(null, -1L,
140140
createErrorOMResponse(omResponse, ex));
141141
} finally {
142142
if (omClientResponse != null) {
@@ -147,7 +147,7 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager,
147147
}
148148

149149
if (LOG.isDebugEnabled()) {
150-
LOG.debug("Updated delegation token to OM DB: {}",
150+
LOG.debug("Updated delegation token in-memory map: {}",
151151
ozoneTokenIdentifierToken);
152152
}
153153

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,30 +24,32 @@
2424
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
2525
import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
2626
import org.apache.hadoop.utils.db.BatchOperation;
27+
import org.apache.hadoop.utils.db.Table;
2728

29+
import javax.annotation.Nonnull;
30+
import javax.annotation.Nullable;
2831
import java.io.IOException;
2932

3033
/**
31-
* Handle response for DelegationToken request.
34+
* Handle response for CancelDelegationToken request.
3235
*/
33-
public class OMDelegationTokenResponse extends OMClientResponse {
36+
public class OMCancelDelegationTokenResponse extends OMClientResponse {
3437

3538
private OzoneTokenIdentifier ozoneTokenIdentifier;
36-
private long renewTime;
37-
public OMDelegationTokenResponse(OzoneTokenIdentifier ozoneTokenIdentifier,
38-
long renewTime, OMResponse omResponse) {
39+
40+
public OMCancelDelegationTokenResponse(
41+
@Nullable OzoneTokenIdentifier ozoneTokenIdentifier,
42+
@Nonnull OMResponse omResponse) {
3943
super(omResponse);
4044
this.ozoneTokenIdentifier = ozoneTokenIdentifier;
41-
this.renewTime = renewTime;
4245
}
4346

4447
@Override
4548
public void addToDBBatch(OMMetadataManager omMetadataManager,
4649
BatchOperation batchOperation) throws IOException {
47-
50+
Table table = omMetadataManager.getDelegationTokenTable();
4851
if (getOMResponse().getStatus() == OzoneManagerProtocolProtos.Status.OK) {
49-
omMetadataManager.getDelegationTokenTable().putWithBatch(batchOperation,
50-
ozoneTokenIdentifier, renewTime);
52+
table.deleteWithBatch(batchOperation, ozoneTokenIdentifier);
5153
}
5254
}
5355
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
* <p>
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
* <p>
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.hadoop.ozone.om.response.security;
20+
21+
import org.apache.hadoop.ozone.om.OMMetadataManager;
22+
import org.apache.hadoop.ozone.om.response.OMClientResponse;
23+
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
24+
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
25+
import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
26+
import org.apache.hadoop.utils.db.BatchOperation;
27+
import org.apache.hadoop.utils.db.Table;
28+
29+
import javax.annotation.Nonnull;
30+
import javax.annotation.Nullable;
31+
import java.io.IOException;
32+
33+
/**
34+
* Handle response for GetDelegationToken request.
35+
*/
36+
public class OMGetDelegationTokenResponse extends OMClientResponse {
37+
38+
private OzoneTokenIdentifier ozoneTokenIdentifier;
39+
private long renewTime = -1L;
40+
41+
public OMGetDelegationTokenResponse(
42+
@Nullable OzoneTokenIdentifier ozoneTokenIdentifier,
43+
long renewTime, @Nonnull OMResponse omResponse) {
44+
super(omResponse);
45+
this.ozoneTokenIdentifier = ozoneTokenIdentifier;
46+
this.renewTime = renewTime;
47+
}
48+
49+
@Override
50+
public void addToDBBatch(OMMetadataManager omMetadataManager,
51+
BatchOperation batchOperation) throws IOException {
52+
Table table = omMetadataManager.getDelegationTokenTable();
53+
if (getOMResponse().getStatus() == OzoneManagerProtocolProtos.Status.OK) {
54+
table.putWithBatch(batchOperation, ozoneTokenIdentifier, renewTime);
55+
}
56+
}
57+
}
58+

0 commit comments

Comments
 (0)